全部产品
Search
文档中心

Alibaba Cloud Service Mesh:Routing cerdas dengan antrian, KV Cache, dan LoRA

更新时间:Mar 12, 2026

Load balancing tradisional mendistribusikan permintaan secara merata di seluruh backend, tetapi beban kerja inferensi LLM pada dasarnya tidak merata. Prompt pendek mungkin selesai dalam milidetik, sementara penyelesaian panjang dapat membebani GPU selama beberapa detik. Service Mesh (ASM) mengatasi hal ini dengan mengarahkan permintaan berdasarkan status real-time setiap backend vLLM: kedalaman antrian permintaan dan pemanfaatan cache KV. Hasilnya adalah waktu hingga token pertama (TTFT) lebih rendah, throughput lebih tinggi, serta pemanfaatan GPU yang seimbang di seluruh armada inferensi Anda.

Topik ini memandu Anda melalui penerapan layanan inferensi Llama 2 berbasis vLLM, konfigurasi routing yang sadar LLM melalui ASM, dan penyiapan dasbor observabilitas untuk memantau traffic inferensi.

Penting

Saat ini, hanya layanan inferensi LLM berbasis vLLM yang didukung.

Latar Belakang

Large language models (LLMs)

Large language models (LLMs) adalah model bahasa berbasis jaringan saraf dengan miliaran parameter, diwakili oleh GPT, Qwen, dan Llama. Model-model ini dilatih pada dataset yang beragam dan luas—termasuk teks web, literatur profesional, dan kode—dan terutama digunakan untuk tugas generasi teks seperti pelengkapan dan dialog.

Untuk memanfaatkan LLM dalam membangun aplikasi, Anda dapat:

  • Menggunakan layanan API LLM eksternal dari platform seperti OpenAI, Alibaba Cloud Model Studio, atau Moonshot.

  • Membangun layanan inferensi LLM sendiri menggunakan model dan framework open-source atau proprietary seperti vLLM, lalu menerapkannya di kluster Kubernetes. Pendekatan ini cocok untuk skenario yang memerlukan kendali atas layanan inferensi atau kustomisasi tingkat tinggi terhadap kemampuan inferensi LLM.

vLLM

vLLM adalah framework yang dirancang untuk membangun layanan inferensi LLM secara efisien dan mudah digunakan. Framework ini mendukung berbagai model bahasa besar, termasuk Qwen, serta mengoptimalkan efisiensi inferensi melalui teknik seperti PagedAttention, inferensi batch dinamis (Continuous Batching), dan kuantisasi model.

Cara kerja load balancing yang sadar LLM

Mengapa load balancing tradisional kurang optimal untuk inferensi LLM

Algoritma klasik seperti round-robin dan least-connections mengasumsikan setiap permintaan memberikan beban serupa. Inferensi LLM melanggar asumsi ini:

  • Waktu pemrosesan bervariasi. Setiap permintaan melewati dua fase—prefill (encoding prompt) dan decode (menghasilkan token satu per satu). Panjang fase decode tidak dapat diprediksi karena jumlah token output bervariasi per permintaan.

  • Kontensi memori GPU. vLLM mengalokasikan memori GPU terlebih dahulu untuk cache KV. Saat cache terisi, server mengantrikan permintaan baru atau menukarnya ke memori CPU, yang secara drastis meningkatkan latensi.

Tanpa mempertimbangkan faktor-faktor ini, permintaan menumpuk di beberapa backend sementara yang lain menganggur—meningkatkan tail latency dan membuang sumber daya GPU.

Cara ASM mengarahkan traffic LLM

ASM mengevaluasi metrik multidimensi dari setiap backend vLLM untuk membuat keputusan routing:

MetricSourceRouting signal
Kedalaman antrian permintaanvllm:num_requests_waitingLebih sedikit permintaan dalam antrian menunjukkan pemrosesan lebih cepat
Pemanfaatan cache KVvllm:gpu_cache_usage_percPemanfaatan lebih rendah berarti lebih banyak memori GPU tersedia untuk permintaan baru

Saat permintaan baru tiba, ASM memilih backend dengan kombinasi sinyal terbaik. Hal ini menjaga beban GPU seimbang di seluruh replika inferensi, mengurangi TTFT, dan meningkatkan throughput keseluruhan dibandingkan algoritma tradisional.

Observabilitas traffic LLM

Proxy standar mengurai Header HTTP dan path URL tetapi mengabaikan badan permintaan. Karena API inferensi LLM (format kompatibel OpenAI) membawa nama model dan parameter token dalam badan permintaan, observabilitas tradisional melewatkan dimensi penting.

ASM memperluas observabilitas untuk traffic inferensi LLM:

  • Log akses mencakup nama model dan jumlah token input/output per permintaan.

  • Metrik pemantauan menambahkan dimensi model untuk analisis per model.

  • Metrik token (asm_llm_proxy_prompt_tokens, asm_llm_proxy_completion_tokens) melacak konsumsi token di seluruh beban kerja.

Prasyarat

Sebelum memulai, pastikan Anda telah memiliki:

Langkah 1: Terapkan layanan inferensi vLLM contoh

Terapkan model Llama 2 yang disajikan oleh vLLM dengan beberapa adapter LoRA. Penerapan mencakup Service Kubernetes, ConfigMap untuk templat chat, dan Deployment dengan 3 replika berbasis GPU.

Catatan

Gambar kontainer memerlukan GPU dengan memori video lebih dari 16 GiB. Gunakan tipe GPU A10 untuk kluster ACK atau GPU B generasi ke-8 untuk kluster ACS. T4 (16 GiB) tidak menyediakan memori yang cukup. Untuk detail model, kirim tiket.

Gambar LLM berukuran besar. Simpan terlebih dahulu di Alibaba Cloud Container Registry (ACR) dan tarik melalui jaringan internal untuk menghindari unduhan lambat melalui titik akhir publik.

  1. Buat file bernama vllm-service.yaml dengan konten berikut.

    Kluster ACK

       apiVersion: v1
       kind: Service
       metadata:
         name: vllm-llama2-7b-pool
       spec:
         selector:
           app: vllm-llama2-7b-pool
         ports:
         - protocol: TCP
           port: 8000
           targetPort: 8000
         type: ClusterIP
       ---
       apiVersion: v1
       kind: ConfigMap
       metadata:
         name: chat-template
       data:
         llama-2-chat.jinja: |
           {% if messages[0]['role'] == 'system' %}
             {% set system_message = '<<SYS>>\n' + messages[0]['content'] | trim + '\n<</SYS>>\n\n' %}
             {% set messages = messages[1:] %}
           {% else %}
               {% set system_message = '' %}
           {% endif %}
    
           {% for message in messages %}
               {% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}
                   {{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}
               {% endif %}
    
               {% if loop.index0 == 0 %}
                   {% set content = system_message + message['content'] %}
               {% else %}
                   {% set content = message['content'] %}
               {% endif %}
               {% if message['role'] == 'user' %}
                   {{ bos_token + '[INST] ' + content | trim + ' [/INST]' }}
               {% elif message['role'] == 'assistant' %}
                   {{ ' ' + content | trim + ' ' + eos_token }}
               {% endif %}
           {% endfor %}
       ---
       apiVersion: apps/v1
       kind: Deployment
       metadata:
         name: vllm-llama2-7b-pool
         namespace: default
       spec:
         replicas: 3
         selector:
           matchLabels:
             app: vllm-llama2-7b-pool
         template:
           metadata:
             annotations:
               prometheus.io/path: /metrics
               prometheus.io/port: '8000'
               prometheus.io/scrape: 'true'
             labels:
               app: vllm-llama2-7b-pool
           spec:
             containers:
               - name: lora
                 image: "registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/llama2-with-lora:v0.2"
                 imagePullPolicy: IfNotPresent
                 command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
                 args:
                 - "--model"
                 - "/model/llama2"
                 - "--tensor-parallel-size"
                 - "1"
                 - "--port"
                 - "8000"
                 - '--gpu_memory_utilization'
                 - '0.8'
                 - "--enable-lora"
                 - "--max-loras"
                 - "4"
                 - "--max-cpu-loras"
                 - "12"
                 - "--lora-modules"
                 - 'sql-lora=/adapters/yard1/llama-2-7b-sql-lora-test_0'
                 - 'sql-lora-1=/adapters/yard1/llama-2-7b-sql-lora-test_1'
                 - 'sql-lora-2=/adapters/yard1/llama-2-7b-sql-lora-test_2'
                 - 'sql-lora-3=/adapters/yard1/llama-2-7b-sql-lora-test_3'
                 - 'sql-lora-4=/adapters/yard1/llama-2-7b-sql-lora-test_4'
                 - 'tweet-summary=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_0'
                 - 'tweet-summary-1=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_1'
                 - 'tweet-summary-2=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_2'
                 - 'tweet-summary-3=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_3'
                 - 'tweet-summary-4=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_4'
                 - '--chat-template'
                 - '/etc/vllm/llama-2-chat.jinja'
                 env:
                   - name: PORT
                     value: "8000"
                 ports:
                   - containerPort: 8000
                     name: http
                     protocol: TCP
                 livenessProbe:
                   failureThreshold: 2400
                   httpGet:
                     path: /health
                     port: http
                     scheme: HTTP
                   initialDelaySeconds: 5
                   periodSeconds: 5
                   successThreshold: 1
                   timeoutSeconds: 1
                 readinessProbe:
                   failureThreshold: 6000
                   httpGet:
                     path: /health
                     port: http
                     scheme: HTTP
                   initialDelaySeconds: 5
                   periodSeconds: 5
                   successThreshold: 1
                   timeoutSeconds: 1
                 resources:
                   limits:
                     nvidia.com/gpu: 1
                   requests:
                     nvidia.com/gpu: 1
                 volumeMounts:
                   - mountPath: /data
                     name: data
                   - mountPath: /dev/shm
                     name: shm
                   - mountPath: /etc/vllm
                     name: chat-template
             restartPolicy: Always
             schedulerName: default-scheduler
             terminationGracePeriodSeconds: 30
             volumes:
               - name: data
                 emptyDir: {}
               - name: shm
                 emptyDir:
                   medium: Memory
               - name: chat-template
                 configMap:
                   name: chat-template

    Kluster ACS

       apiVersion: v1
       kind: Service
       metadata:
         name: vllm-llama2-7b-pool
       spec:
         selector:
           app: vllm-llama2-7b-pool
         ports:
         - protocol: TCP
           port: 8000
           targetPort: 8000
         type: ClusterIP
       ---
       apiVersion: v1
       kind: ConfigMap
       metadata:
         name: chat-template
       data:
         llama-2-chat.jinja: |
           {% if messages[0]['role'] == 'system' %}
             {% set system_message = '<<SYS>>\n' + messages[0]['content'] | trim + '\n<</SYS>>\n\n' %}
             {% set messages = messages[1:] %}
           {% else %}
               {% set system_message = '' %}
           {% endif %}
    
           {% for message in messages %}
               {% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}
                   {{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}
               {% endif %}
    
               {% if loop.index0 == 0 %}
                   {% set content = system_message + message['content'] %}
               {% else %}
                   {% set content = message['content'] %}
               {% endif %}
               {% if message['role'] == 'user' %}
                   {{ bos_token + '[INST] ' + content | trim + ' [/INST]' }}
               {% elif message['role'] == 'assistant' %}
                   {{ ' ' + content | trim + ' ' + eos_token }}
               {% endif %}
           {% endfor %}
       ---
       apiVersion: apps/v1
       kind: Deployment
       metadata:
         name: vllm-llama2-7b-pool
         namespace: default
       spec:
         replicas: 3
         selector:
           matchLabels:
             app: vllm-llama2-7b-pool
         template:
           metadata:
             annotations:
               prometheus.io/path: /metrics
               prometheus.io/port: '8000'
               prometheus.io/scrape: 'true'
             labels:
               app: vllm-llama2-7b-pool
               alibabacloud.com/compute-class: gpu  # Tentukan daya komputasi GPU
               alibabacloud.com/compute-qos: default
               alibabacloud.com/gpu-model-series: "example-model" # Ganti dengan seri model GPU Anda
           spec:
             containers:
               - name: lora
                 image: "registry-cn-hangzhou.ack.aliyuncs.com/ack-demo/llama2-with-lora:v0.2"
                 imagePullPolicy: IfNotPresent
                 command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
                 args:
                 - "--model"
                 - "/model/llama2"
                 - "--tensor-parallel-size"
                 - "1"
                 - "--port"
                 - "8000"
                 - '--gpu_memory_utilization'
                 - '0.8'
                 - "--enable-lora"
                 - "--max-loras"
                 - "4"
                 - "--max-cpu-loras"
                 - "12"
                 - "--lora-modules"
                 - 'sql-lora=/adapters/yard1/llama-2-7b-sql-lora-test_0'
                 - 'sql-lora-1=/adapters/yard1/llama-2-7b-sql-lora-test_1'
                 - 'sql-lora-2=/adapters/yard1/llama-2-7b-sql-lora-test_2'
                 - 'sql-lora-3=/adapters/yard1/llama-2-7b-sql-lora-test_3'
                 - 'sql-lora-4=/adapters/yard1/llama-2-7b-sql-lora-test_4'
                 - 'tweet-summary=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_0'
                 - 'tweet-summary-1=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_1'
                 - 'tweet-summary-2=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_2'
                 - 'tweet-summary-3=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_3'
                 - 'tweet-summary-4=/adapters/vineetsharma/qlora-adapter-Llama-2-7b-hf-TweetSumm_4'
                 - '--chat-template'
                 - '/etc/vllm/llama-2-chat.jinja'
                 env:
                   - name: PORT
                     value: "8000"
                 ports:
                   - containerPort: 8000
                     name: http
                     protocol: TCP
                 livenessProbe:
                   failureThreshold: 2400
                   httpGet:
                     path: /health
                     port: http
                     scheme: HTTP
                   initialDelaySeconds: 5
                   periodSeconds: 5
                   successThreshold: 1
                   timeoutSeconds: 1
                 readinessProbe:
                   failureThreshold: 6000
                   httpGet:
                     path: /health
                     port: http
                     scheme: HTTP
                   initialDelaySeconds: 5
                   periodSeconds: 5
                   successThreshold: 1
                   timeoutSeconds: 1
                 resources:
                   limits:
                     cpu: 16
                     memory: 64Gi
                     nvidia.com/gpu: 1
                   requests:
                     cpu: 8
                     memory: 30Gi
                     nvidia.com/gpu: 1
                 volumeMounts:
                   - mountPath: /data
                     name: data
                   - mountPath: /dev/shm
                     name: shm
                   - mountPath: /etc/vllm
                     name: chat-template
             restartPolicy: Always
             schedulerName: default-scheduler
             terminationGracePeriodSeconds: 30
             volumes:
               - name: data
                 emptyDir: {}
               - name: shm
                 emptyDir:
                   medium: Memory
               - name: chat-template
                 configMap:
                   name: chat-template
  2. Terapkan layanan inferensi.

       kubectl apply -f vllm-service.yaml
  3. Tunggu hingga ketiga replika siap. Gambar LLM berukuran besar, sehingga pengambilan awal mungkin memakan waktu beberapa menit. Ketiga Pod harus mencapai status Running dengan kontainer siap 1/1 sebelum melanjutkan.

       kubectl get pods -l app=vllm-llama2-7b-pool -w

Langkah 2: Konfigurasikan aturan gateway ASM

Buat resource Gateway untuk mengaktifkan traffic HTTP pada Port 8080 gerbang masuk ASM.

  1. Buat file bernama gateway.yaml dengan konten berikut.

       apiVersion: networking.istio.io/v1
       kind: Gateway
       metadata:
         name: llm-inference-gateway
         namespace: default
       spec:
         selector:
           istio: ingressgateway
         servers:
           - hosts:
               - '*'
             port:
               name: http-service
               number: 8080
               protocol: HTTP
  2. Terapkan sumber daya Gateway.

       kubectl apply -f gateway.yaml

Langkah 3: Konfigurasikan routing dan load balancing untuk layanan inferensi LLM

Catatan

Untuk membandingkan load balancing yang sadar LLM dengan load balancing tradisional, selesaikan langkah-langkah di (Opsional) Bandingkan dengan load balancing tradisional sebelum melanjutkan.

Langkah ini membuat tiga resource yang menghubungkan gateway ASM ke backend vLLM dengan routing yang sadar LLM:

ResourcePurpose
InferencePoolMengelompokkan Pod vLLM berdasarkan pemilih label dan menentukan port inferensi
InferenceModelMemetakan nama model dari badan permintaan ke Pod backend dan menentukan distribusi traffic
LLMRouteMenghubungkan gateway ASM ke InferencePool untuk routing yang sadar LLM

Aktifkan routing inferensi LLM

Jalankan perintah berikut menggunakan kubeconfig instans ASM Anda:

kubectl patch asmmeshconfig default --type=merge \
  --patch='{"spec":{"gatewayAPIInferenceExtension":{"enabled":true}}}'

Buat InferencePool

InferencePool mengelompokkan Pod vLLM berdasarkan pemilih label dan menentukan port inferensi.

  1. Buat file bernama inferencepool.yaml dengan konten berikut.

    FieldDescription
    .spec.targetPortNumberPort pada setiap Pod yang melayani permintaan inferensi
    .spec.selectorPemilih label yang sesuai dengan Pod inferensi. Kunci harus app dan nilainya harus sesuai dengan nama Service terkait
       apiVersion: inference.networking.x-k8s.io/v1alpha1
       kind: InferencePool
       metadata:
         name: vllm-llama2-7b-pool
       spec:
         targetPortNumber: 8000
         selector:
           app: vllm-llama2-7b-pool
  2. Terapkan InferencePool menggunakan kubeconfig kluster bidang data.

       kubectl apply -f inferencepool.yaml
  3. Verifikasi bahwa InferencePool aktif. Status harus mencakup Accepted=True dan ResolvedRefs=True sebelum melanjutkan.

       kubectl get inferencepool vllm-llama2-7b-pool -o yaml

Buat InferenceModel

InferenceModel memetakan parameter model dalam permintaan masuk ke Pod backend tertentu dan menentukan bobot distribusi traffic.

  1. Buat file bernama inferencemodel.yaml dengan konten berikut.

    FieldDescription
    .spec.modelNameSesuai dengan parameter model dalam badan permintaan
    .spec.targetModelsMenentukan aturan routing traffic. Dalam contoh ini, semua permintaan dengan model: tweet-summary diarahkan ke Pod yang menjalankan model tersebut
       apiVersion: inference.networking.x-k8s.io/v1alpha1
       kind: InferenceModel
       metadata:
         name: inferencemodel-sample
       spec:
         modelName: tweet-summary
         poolRef:
           group: inference.networking.x-k8s.io
           kind: InferencePool
           name: vllm-llama2-7b-pool
         targetModels:
         - name: tweet-summary
           weight: 100
  2. Terapkan InferenceModel.

       kubectl apply -f inferencemodel.yaml
  3. Verifikasi bahwa InferenceModel aktif. Status harus mencakup Accepted=True dan ResolvedRefs=True.

       kubectl get inferencemodel inferencemodel-sample -o yaml

Buat LLMRoute

LLMRoute menghubungkan gateway ASM ke InferencePool, meneruskan semua permintaan pada Port 8080 ke layanan inferensi dengan load balancing yang sadar LLM.

  1. Buat file bernama llmroute.yaml dengan konten berikut.

       apiVersion: istio.alibabacloud.com/v1
       kind: LLMRoute
       metadata:
         name: test-llm-route
       spec:
         gateways:
         - llm-inference-gateway
         host: test.com
         rules:
         - backendRefs:
           - backendRef:
               group: inference.networking.x-k8s.io
               kind: InferencePool
               name: vllm-llama2-7b-pool
  2. Terapkan LLMRoute.

       kubectl apply -f llmroute.yaml

Langkah 4: Verifikasi konfigurasi

Kirim permintaan uji melalui gateway ASM untuk memastikan routing yang sadar LLM berfungsi.

curl -v \
  -H "host: test.com" \
  -H "Content-Type: application/json" \
  http://${ASM_GATEWAY_IP}:8080/v1/completions \
  -d '{
    "model": "tweet-summary",
    "prompt": "Write as if you were a critic: San Francisco",
    "max_tokens": 100,
    "temperature": 0
  }'

Ganti ${ASM_GATEWAY_IP} dengan alamat IP gerbang masuk ASM Anda.

Tanggapan sukses terlihat seperti ini:

{
  "id": "cmpl-2fc9a351-d866-422b-b561-874a30843a6b",
  "object": "text_completion",
  "created": 1736933141,
  "model": "tweet-summary",
  "choices": [
    {
      "index": 0,
      "text": "...",
      "logprobs": null,
      "finish_reason": "length",
      "stop_reason": null,
      "prompt_logprobs": null
    }
  ],
  "usage": {
    "prompt_tokens": 2,
    "total_tokens": 102,
    "completion_tokens": 100,
    "prompt_tokens_details": null
  }
}

Jalankan perintah beberapa kali untuk mengamati bahwa permintaan didistribusikan ke Pod backend berbeda berdasarkan beban real-time mereka.

(Opsional) Langkah 5: Siapkan observabilitas untuk layanan inferensi LLM

Setelah mengonfigurasi InferencePool, InferenceModel, dan LLMRoute, siapkan pemantauan untuk melacak laju permintaan inferensi, throughput token, dan kesehatan backend vLLM.

Aktifkan observabilitas traffic LLM di ASM

  1. Aktifkan field log, metrik, dan dimensi metrik khusus LLM di konsol ASM. Lihat Observasi traffic: Kelola traffic LLM secara efisien menggunakan ASM untuk detail konfigurasi. Setelah dikonfigurasi, metrik pemantauan ASM mencakup dimensi model. Kumpulkan metrik ini menggunakan salah satu:

  2. Tambahkan aturan scrape untuk metrik token khusus ASM (asm_llm_proxy_prompt_tokens dan asm_llm_proxy_completion_tokens) ke konfigurasi Prometheus Anda. Lihat Konfigurasi service discovery Prometheus lainnya untuk detail penyiapan.

       scrape_configs:
       - job_name: asm-envoy-stats-llm
         scrape_interval: 30s
         scrape_timeout: 30s
         metrics_path: /stats/prometheus
         scheme: http
         kubernetes_sd_configs:
         - role: pod
         relabel_configs:
         - source_labels:
           - __meta_kubernetes_pod_container_port_name
           action: keep
           regex: .*-envoy-prom
         - source_labels:
           - __address__
           - __meta_kubernetes_pod_annotation_prometheus_io_port
           action: replace
           regex: ([^:]+)(?::\d+)?;(\d+)
           replacement: $1:15090
           target_label: __address__
         - action: labelmap
           regex: __meta_kubernetes_pod_label_(.+)
         - source_labels:
           - __meta_kubernetes_namespace
           action: replace
           target_label: namespace
         - source_labels:
           - __meta_kubernetes_pod_name
           action: replace
           target_label: pod_name
         metric_relabel_configs:
         - action: keep
           source_labels:
           - __name__
           regex: asm_llm_.*

Kumpulkan metrik backend vLLM

Layanan vLLM mengekspos metrik Prometheus di /metrics pada Port 8000. Deployment contoh sudah mencakup anotasi yang diperlukan:

annotations:
  prometheus.io/path: /metrics
  prometheus.io/port: "8000"
  prometheus.io/scrape: "true"

Prometheus menemukan dan mengambil endpoint ini secara otomatis melalui mekanisme service discovery default-nya. Lihat Service discovery Pod default untuk detailnya.

Metrik vLLM utama yang perlu dipantau:

MetricDescription
vllm:gpu_cache_usage_percPemanfaatan cache KV. Nilai lebih rendah menunjukkan lebih banyak memori GPU tersedia untuk permintaan baru
vllm:request_queue_time_seconds_sumWaktu yang dihabiskan permintaan dalam antrian sebelum penjadwal vLLM menjalankan prefill dan decode
vllm:num_requests_running, vllm:num_requests_waiting, vllm:num_requests_swappedJumlah permintaan yang menjalankan inferensi, menunggu dalam antrian, atau ditukar ke memori CPU. Gunakan ini untuk menilai tekanan backend
vllm:avg_generation_throughput_toks_per_s, vllm:avg_prompt_throughput_toks_per_sThroughput token untuk tahap decode dan prefill per detik
vllm:time_to_first_token_seconds_bucketDistribusi TTFT. Mengukur seberapa cepat klien menerima token pertama setelah mengirim permintaan—metrik kunci untuk latensi yang dirasakan pengguna

Buat Dasbor Grafana

Siapkan Dasbor Grafana yang menggabungkan metrik ASM (laju permintaan, throughput token) dengan metrik vLLM (cache GPU, kedalaman antrian, TTFT) untuk tampilan terpadu armada inferensi Anda.

  1. Pastikan sumber data Prometheus Anda di Grafana mengumpulkan metrik ASM dan vLLM.

  2. Impor JSON dasbor berikut ke Grafana. Unduh JSON dasbor lengkap dari halaman dokumentasi ASM (perluas Dashboard JSON di halaman tersebut untuk menyalin konten lengkapnya).

  3. Di Grafana, buka Dashboards > Import, tempel JSON, lalu pilih sumber data Prometheus Anda.

Grafana dashboard for LLM inference monitoring

(Opsional) Bandingkan dengan load balancing tradisional

Gunakan dasbor observabilitas untuk mengukur perbedaan antara load balancing yang sadar LLM dan load balancing tradisional. Jalankan perbandingan ini sebelum mengonfigurasi routing yang sadar LLM di Langkah 3.

Catatan

Jika Anda telah menyelesaikan Langkah 3, bersihkan terlebih dahulu resource routing LLM:

kubectl delete inferencemodel --all
kubectl delete inferencepool --all
kubectl delete llmroute --all
  1. Buat VirtualService yang mengarahkan traffic menggunakan load balancing round-robin tradisional.

       kubectl apply -f- <<EOF
       apiVersion: networking.istio.io/v1
       kind: VirtualService
       metadata:
         name: llm-vs
         namespace: default
       spec:
         gateways:
           - default/llm-inference-gateway
         hosts:
           - '*'
         http:
           - name: any-host
             route:
               - destination:
                   host: vllm-llama2-7b-pool.default.svc.cluster.local
                   port:
                     number: 8000
       EOF
  2. Jalankan uji stres terhadap layanan inferensi menggunakan tool seperti llmperf.

  3. Hapus VirtualService, lalu selesaikan Langkah 3 untuk mengonfigurasi routing yang sadar LLM. Pastikan tidak ada resource VirtualService yang tersisa sebelum melanjutkan. Jalankan uji stres yang sama lagi.

  4. Bandingkan hasilnya di Dasbor Grafana. Load balancing yang sadar LLM memberikan:

    • TTFT lebih rendah (waktu hingga token pertama)

    • Throughput token lebih tinggi

    • Pemanfaatan cache KV lebih merata di seluruh replika

Performance comparison: traditional vs. LLM-aware load balancing

Bersihkan

Untuk menghapus semua resource yang dibuat dalam tutorial ini:

# Hapus resource routing LLM
kubectl delete inferencemodel --all
kubectl delete inferencepool --all
kubectl delete llmroute --all

# Hapus gateway
kubectl delete -f gateway.yaml

# Hapus layanan inferensi
kubectl delete -f vllm-service.yaml

Topik terkait