Load balancing Kubernetes standar mendistribusikan permintaan inferensi LLM menggunakan pemilihan round-robin sederhana atau acak tanpa mempertimbangkan status cache GPU dan kedalaman antrian. Hal ini menyebabkan pemanfaatan cache KV yang tidak merata di antara replika, meningkatkan komputasi redundan dan latensi respons. Gateway with Inference Extension mengatasi masalah ini dengan mengarahkan setiap permintaan ke replika yang paling sesuai berdasarkan metrik server inferensi real-time.
Topik ini menjelaskan cara menerapkan Gateway with Inference Extension pada kluster ACK yang dikelola, mengonfigurasi perutean yang sadar inferensi menggunakan InferencePool dan InferenceModel, serta memverifikasi peningkatan performa melalui pengujian beban dan dasbor Grafana.
Cara kerja
Gateway membuka dua port dengan perilaku perutean berbeda:
Port 8080 — HTTPRoute standar. Permintaan langsung diarahkan ke layanan backend vLLM menggunakan load balancing standar.
Port 8081 — HTTPRoute yang sadar inferensi. Permintaan melewati ekstensi layanan inferensi (LLM Route), yang memilih replika terbaik berdasarkan panjang antrian permintaan dan pemanfaatan cache GPU sebelum meneruskan ke backend.
InferencePool mendeklarasikan pod yang membentuk backend inferensi. InferenceModel memetakan nama model masuk ke kebijakan distribusi traffic dalam pool tersebut. Saat permintaan tiba di port 8081, ekstensi membaca metrik langsung dari setiap pod dan memilih replika dengan kapasitas paling besar untuk melayani permintaan tersebut secara efisien.
Konsep utama
| Resource | Deskripsi |
|---|---|
| InferencePool | CRD Kubernetes yang mengelompokkan sekumpulan pod inferensi LLM menjadi satu backend yang dapat dialamatkan. Menggantikan Service biasa sebagai backendRef dalam HTTPRoute. |
| InferenceModel | CRD Kubernetes yang memetakan nama model masuk ke kebijakan distribusi traffic dalam InferencePool. |
| Gateway with Inference Extension | Komponen ACK yang menyematkan endpoint picker (EPP) ke bidang data Envoy Gateway. EPP mengumpulkan metrik vLLM per-pod dan menerapkan load balancing yang sadar inferensi. |
| KV cache | Status key-value per-permintaan yang disimpan vLLM di memori GPU untuk menghindari komputasi ulang konteks historis. Mengarahkan permintaan dengan awalan yang sama ke pod yang sama memaksimalkan penggunaan ulang cache KV dan mengurangi latensi. |
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
Kluster ACK yang dikelola dengan kelompok node GPU
(Opsional) Komponen ACK Virtual Node yang telah diinstal untuk menggunakan daya komputasi GPU ACS pada kluster ACK Pro
Langkah 1: Terapkan layanan inferensi contoh
Buat file bernama
vllm-service.yamldengan konten berikut. Lihat YAMLUntuk kartu GPU, gunakan kartu A10 untuk kluster ACK dan kartu GN8IS (GPU B generasi ke-8) untuk daya komputasi GPU Alibaba Cloud Container Compute Service (ACS). Image LLM berukuran besar — transfer terlebih dahulu ke Container Registry dan tarik melalui jaringan internal. Kecepatan tarik melalui jaringan publik bergantung pada bandwidth EIP kluster dan mungkin lambat.
Terapkan layanan inferensi.
kubectl apply -f vllm-service.yaml
Langkah 2: Instal komponen Gateway with Inference Extension
Instal komponen ACK Gateway with Inference Extension dan pilih Enable Gateway API Inference Extension.

Langkah 3: Terapkan perutean inferensi
Langkah ini membuat resource InferencePool dan InferenceModel yang mendefinisikan backend inferensi dan kebijakan peruteannya.
Buat file bernama
inference-pool.yaml.apiVersion: inference.networking.x-k8s.io/v1alpha2 kind: InferencePool metadata: name: vllm-qwen-pool spec: targetPortNumber: 8000 selector: app: qwen extensionRef: name: inference-gateway-ext-proc --- apiVersion: inference.networking.x-k8s.io/v1alpha2 kind: InferenceModel metadata: name: inferencemodel-qwen spec: modelName: /model/qwen criticality: Critical poolRef: group: inference.networking.x-k8s.io kind: InferencePool name: vllm-qwen-pool targetModels: - name: /model/qwen weight: 100Terapkan resource perutean.
kubectl apply -f inference-gateway-llm.yaml
Langkah 4: Terapkan dan verifikasi gateway
Langkah ini membuat gateway dengan dua listener: port 8080 untuk perutean HTTP standar dan port 8081 untuk perutean yang sadar inferensi.
Buat file bernama
inference-gateway.yaml.apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: qwen-inference-gateway-class spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: qwen-inference-gateway spec: gatewayClassName: qwen-inference-gateway-class listeners: - name: http protocol: HTTP port: 8080 - name: llm-gw protocol: HTTP port: 8081 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: qwen-backend spec: parentRefs: - name: qwen-inference-gateway sectionName: llm-gw rules: - backendRefs: - group: inference.networking.x-k8s.io kind: InferencePool name: vllm-qwen-pool matches: - path: type: PathPrefix value: / --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: qwen-backend-no-inference spec: parentRefs: - group: gateway.networking.k8s.io kind: Gateway name: qwen-inference-gateway sectionName: http rules: - backendRefs: - group: "" kind: Service name: qwen port: 8000 weight: 1 matches: - path: type: PathPrefix value: / --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: name: backend-timeout spec: timeout: http: requestTimeout: 1h targetRef: group: gateway.networking.k8s.io kind: Gateway name: qwen-inference-gatewayTerapkan gateway.
kubectl apply -f inference-gateway.yamlIni akan membuat namespace
envoy-gateway-systemdan Service bernamaenvoy-default-inference-gateway-645xxxxxdi kluster.Dapatkan alamat IP publik gateway.
export GATEWAY_HOST=$(kubectl get gateway/qwen-inference-gateway -o jsonpath='{.status.addresses[0].value}')Verifikasi perutean HTTP standar pada port 8080.
curl -X POST ${GATEWAY_HOST}:8080/v1/chat/completions \ -H 'Content-Type: application/json' \ -d '{ "model": "/model/qwen", "max_completion_tokens": 100, "temperature": 0, "messages": [ { "role": "user", "content": "Write as if you were a critic: San Francisco" } ] }'Output yang diharapkan:
{"id":"chatcmpl-aa6438e2-d65b-4211-afb8-ae8e76e7a692","object":"chat.completion","created":1747191180,"model":"/model/qwen","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":null,"content":"San Francisco, a city that has long been a beacon of innovation, culture, and diversity, continues to captivate the world with its unique charm and character. As a critic, I find myself both enamored and occasionally perplexed by the city's multifaceted personality.\n\nSan Francisco's architecture is a testament to its rich history and progressive spirit. The iconic cable cars, Victorian houses, and the Golden Gate Bridge are not just tourist attractions but symbols of the city's enduring appeal. However, the","tool_calls":[]},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":39,"total_tokens":139,"completion_tokens":100,"prompt_tokens_details":null},"prompt_logprobs":null}Verifikasi perutean yang sadar inferensi pada port 8081.
curl -X POST ${GATEWAY_HOST}:8081/v1/chat/completions \ -H 'Content-Type: application/json' \ -d '{ "model": "/model/qwen", "max_completion_tokens": 100, "temperature": 0, "messages": [ { "role": "user", "content": "Write as if you were a critic: Los Angeles" } ] }'Output yang diharapkan:
{"id":"chatcmpl-cc4fcd0a-6a66-4684-8dc9-284d4eb77bb7","object":"chat.completion","created":1747191969,"model":"/model/qwen","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":null,"content":"Los Angeles, the sprawling metropolis often referred to as \"L.A.,\" is a city that defies easy description. It is a place where dreams are made and broken, where the sun never sets, and where the line between reality and fantasy is as blurred as the smog that often hangs over its valleys. As a critic, I find myself both captivated and perplexed by this city that is as much a state of mind as it is a physical place.\n\nOn one hand, Los","tool_calls":[]},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":39,"total_tokens":139,"completion_tokens":100,"prompt_tokens_details":null},"prompt_logprobs":null}
(Opsional) Langkah 5: Konfigurasikan metrik observabilitas dan dasbor
Langkah ini memerlukan Managed Service for Prometheus, yang mungkin menimbulkan biaya tambahan.
Aktifkan pengumpulan metrik Prometheus
vllm-service.yaml pada Langkah 1 sudah mencakup anotasi berikut, yang mengaktifkan penemuan layanan default untuk instance Prometheus:
annotations:
prometheus.io/path: /metrics # Jalur tempat vLLM mengekspos metrik
prometheus.io/port: "8000" # Port pendengar server vLLM
prometheus.io/scrape: "true" # Aktifkan scraping untuk pod iniMetrik vLLM berikut tersedia setelah scraping diaktifkan:
| Metric | Apa yang ditunjukkan |
|---|---|
vllm:gpu_cache_usage_perc | Porsi cache KV GPU yang digunakan per pod. Nilai lebih rendah berarti ruang lebih besar untuk permintaan baru. |
vllm:request_queue_time_seconds_sum | Waktu tunggu permintaan sebelum diproses oleh penjadwal vLLM. Nilai tinggi menunjukkan pod kelebihan beban. |
vllm:num_requests_running / vllm:num_requests_waiting / vllm:num_requests_swapped | Tekanan permintaan real-time di seluruh status running, waiting, dan swapped. |
vllm:avg_generation_throughput_toks_per_s / vllm:avg_prompt_throughput_toks_per_s | Laju generasi token selama tahap decode dan prefill. |
vllm:time_to_first_token_seconds_bucket | Latensi dari pengiriman permintaan hingga token pertama dikembalikan — metrik kunci pengalaman pengguna. |
Tetapkan aturan alert pada metrik ini untuk mendeteksi anomali performa layanan LLM secara otomatis.
Impor dasbor Grafana
Impor JSON berikut ke Grafana untuk memvisualisasikan laju permintaan, throughput token, waktu hingga token pertama (TTFT), pemanfaatan cache KV, status penjadwal, dan waktu antrian untuk deployment vLLM Anda.

Pratinjau:

Jalankan pengujian beban untuk membandingkan strategi perutean
Gunakan benchmark vLLM untuk menguji stres kedua jalur perutean dan bandingkan hasilnya di dasbor Grafana.
Terapkan beban kerja benchmark.
kubectl apply -f- <<EOF apiVersion: apps/v1 kind: Deployment metadata: labels: app: vllm-benchmark name: vllm-benchmark namespace: default spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: vllm-benchmark strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: vllm-benchmark spec: containers: - command: - sh - -c - sleep inf image: registry-cn-hangzhou.ack.aliyuncs.com/dev/llm-benchmark:random-and-qa imagePullPolicy: IfNotPresent name: vllm-benchmark resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 EOFDapatkan IP kluster internal gateway.
export GW_IP=$(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=qwen-inference-gateway -o jsonpath='{.items[0].spec.clusterIP}')Jalankan pengujian stres.
Normal HTTP route
kubectl exec -it deploy/vllm-benchmark -- env GW_IP=${GW_IP} python3 /root/vllm/benchmarks/benchmark_serving.py \ --backend vllm \ --model /models/DeepSeek-R1-Distill-Qwen-7B \ --served-model-name /model/qwen \ --trust-remote-code \ --dataset-name random \ --random-prefix-len 10 \ --random-input-len 1550 \ --random-output-len 1800 \ --random-range-ratio 0.2 \ --num-prompts 3000 \ --max-concurrency 200 \ --host $GW_IP \ --port 8080 \ --endpoint /v1/completions \ --save-result \ 2>&1 | tee benchmark_serving.txtInference service route
kubectl exec -it deploy/vllm-benchmark -- env GW_IP=${GW_IP} python3 /root/vllm/benchmarks/benchmark_serving.py \ --backend vllm \ --model /models/DeepSeek-R1-Distill-Qwen-7B \ --served-model-name /model/qwen \ --trust-remote-code \ --dataset-name random \ --random-prefix-len 10 \ --random-input-len 1550 \ --random-output-len 1800 \ --random-range-ratio 0.2 \ --num-prompts 3000 \ --max-concurrency 200 \ --host $GW_IP \ --port 8081 \ --endpoint /v1/completions \ --save-result \ 2>&1 | tee benchmark_serving.txtBuka panel Cache Utilization di dasbor Grafana Anda dan bandingkan kedua pengujian tersebut. Dengan perutean HTTP standar, pemanfaatan cache GPU tidak merata — beberapa pod jenuh sementara yang lain menganggur. Dengan perutean yang sadar inferensi, pemanfaatan tersebar merata di semua pod, sehingga mengurangi komputasi cache KV redundan dan menurunkan latensi saat beban tinggi.

Langkah selanjutnya
Gateway with Inference Extension mendukung berbagai kebijakan load balancing. Tetapkan anotasi inference.networking.x-k8s.io/routing-strategy pada InferencePool untuk memilih kebijakan bagi pool tersebut.
Contoh berikut menggunakan kebijakan default:
apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferencePool
metadata:
name: vllm-app-pool
annotations:
inference.networking.x-k8s.io/routing-strategy: "DEFAULT"
spec:
targetPortNumber: 8000
selector:
app: vllm-app
extensionRef:
name: inference-gateway-ext-proc| Kebijakan | Paling cocok untuk |
|---|---|
DEFAULT | Beban kerja umum. Melakukan perutean berdasarkan panjang antrian permintaan dan pemanfaatan cache GPU untuk menyeimbangkan beban di semua pod. |
PREFIX_CACHE | Beban kerja dengan banyak permintaan yang memiliki awalan sama. Mengarahkan permintaan yang cocok ke pod yang sama untuk memaksimalkan penggunaan ulang cache KV. Kasus penggunaan khas: Q&A dokumen panjang (panduan pengguna, laporan tahunan) dan percakapan multi-putaran. Memerlukan fitur auto prefix caching yang diaktifkan pada server inferensi. |