Dokumen ini menjelaskan cara mengelola permintaan inferensi di beberapa cluster Ray Serve di Google Kubernetes Engine (GKE) dengan mengonfigurasi Kubernetes Gateway API dan GKE Inference Gateway. Konfigurasi ini memungkinkan Anda memusatkan pengelolaan traffic untuk beberapa tim, mendistribusikan workload di seluruh region untuk kapasitas yang lebih tinggi, dan menerapkan perutean yang mendukung model berdasarkan konten isi permintaan.
Manfaat menggunakan GKE Inference Gateway dan Ray Serve
Penggunaan GKE Inference Gateway dan Ray Serve menawarkan manfaat berikut:
- Perutean jalur: mengonfigurasi setiap RayService dengan awalan jalur, lalu menayangkan
nya dengan satu Gateway yang merutekan ke beberapa Layanan Ray.
- Untuk mengetahui informasi selengkapnya tentang cara menyiapkan aturan awalan jalur, lihat dokumentasi Gateway API.
- Perutean yang mendukung model: memilih RayService yang akan dirutekan berdasarkan isi permintaan—misalnya, dengan mengekstrak model yang diminta dari permintaan JSON OpenAI-API.
- Tata kelola: mewajibkan kunci API untuk menggunakan layanan Anda, atau menerapkan kuota untuk pengguna dengan menggunakan Apigee untuk autentikasi dan pengelolaan API.
- Multi-region: membagi traffic di beberapa cluster GKE dengan RayServices untuk mencapai ketersediaan atau kapasitas yang lebih tinggi dengan Gateway multi-cluster.
- Pemisahan tanggung jawab: menggunakan RayServices terpisah, yang dapat dikelola oleh tim terpisah, mengikuti peluncuran terpisah, dan berjalan pada topologi yang berbeda.
- Keamanan: menggunakan Gateway untuk bertindak sebagai terminator SSL guna membantu mengamankan traffic pengguna Anda melalui internet. Untuk mengetahui informasi selengkapnya, lihat Keamanan gateway.
Untuk mengonfigurasi perutean, Anda harus men-deploy Gateway, HTTPRoute, dan RayService. Layanan Kubernetes untuk setiap cluster Ray target biasanya dibuat oleh KubeRay. Ray Serve menyebarkan beban permintaan dalam cluster, tanpa perlu membuat InferencePool atau Pemilih Endpoint.
Perutean yang mendukung model untuk Ray Serve di GKE
Perutean yang mendukung model diaktifkan oleh ekstensi perutean berbasis isi. Perutean berbasis isi memungkinkan Anda mengarahkan traffic ke RayServices yang berbeda hanya berdasarkan model yang diberi nama dalam permintaan pengguna, yang memungkinkan Anda memiliki satu endpoint yang dapat menayangkan banyak model yang dihosting di beberapa cluster Ray. Pengguna Anda memiliki akses yang disederhanakan, dan developer aplikasi Anda memiliki kontrol atas konfigurasi setiap endpoint Ray.
Untuk mengonfigurasi perutean yang mendukung model, Anda men-deploy komponen utama berikut:
- Ekstensi router berbasis isi untuk mengekstrak nama model dari payload JSON. Ekstensi router ini di-deploy menggunakan Helm.
- GKE Gateway (Load Balancer Aplikasi internal regional L7) untuk menangani traffic masuk.
- Aturan HTTPRoute untuk mengarahkan traffic ke Layanan Ray yang benar menggunakan header yang diisi oleh ekstensi router.
- Beberapa cluster Ray Serve untuk mengelola siklus proses dan penskalaan otomatis model yang terisolasi.
Sebelum memulai
Sebelum memulai, pastikan Anda telah melakukan tugas berikut:
- Aktifkan Google Kubernetes Engine API. Aktifkan Google Kubernetes Engine API
- Jika ingin menggunakan Google Cloud CLI untuk tugas ini,
instal lalu
lakukan inisialisasi gcloud CLI. Jika sebelumnya Anda telah menginstal gcloud CLI, dapatkan versi terbaru dengan menjalankan perintah
gcloud components update. Versi gcloud CLI yang lebih lama mungkin tidak mendukung menjalankan perintah dalam dokumen ini.
- Pastikan Anda telah menginstal Helm.
- Buat akun Hugging Face, jika Anda belum memilikinya.
- Pastikan Anda memiliki a token Hugging Face.
Menyiapkan lingkungan Anda
Siapkan variabel lingkungan:
export CLUSTER=$(whoami)-ray-bbr
export PROJECT_ID=$(gcloud config get-value project)
export LOCATION=us-central1-b
export REGION=us-central1
export HUGGING_FACE_TOKEN=YOUR_HUGGING_FACE_TOKEN
Ganti YOUR_HUGGING_FACE_TOKEN dengan token akses Hugging Face Anda.
Menyiapkan infrastruktur Anda
Di bagian ini, Anda akan menyiapkan cluster GKE yang mendukung Ray dan Gateway dengan GPU L4.
Buat cluster dengan Ray Operator dan Gateway API diaktifkan:
gcloud container clusters create ${CLUSTER} \ --project ${PROJECT_ID} \ --location ${LOCATION} \ --cluster-version 1.35 \ --gateway-api standard \ --addons HttpLoadBalancing,RayOperator \ --enable-ray-cluster-logging \ --enable-ray-cluster-monitoring \ --machine-type e2-standard-4Buat node pool GPU untuk workload model Anda:
gcloud container node-pools create gpu-pool \ --cluster=${CLUSTER} \ --location=${LOCATION} \ --accelerator="type=nvidia-l4,count=1,gpu-driver-version=latest" \ --machine-type=g2-standard-8 \ --num-nodes=4Buat subnet khusus proxy untuk Load Balancer Aplikasi internal regional, yang diperlukan oleh perutean berbasis isi:
gcloud compute networks subnets create bbr-proxy-only-subnet \ --purpose=REGIONAL_MANAGED_PROXY \ --role=ACTIVE \ --region=${REGION} \ --network=default \ --range=192.168.10.0/24Deploy secret Hugging Face Anda:
kubectl create secret generic hf-secret \ --from-literal=hf_api_token=${HUGGING_FACE_TOKEN}
Men-deploy router berbasis isi untuk perutean yang mendukung model
Ekstensi router berbasis isi mencegat permintaan, mengurai isi JSON, dan mengekstrak kolom model ke dalam header X-Gateway-Model-Name.
Buat file bernama
helm-values.yamldengan konten berikut:bbr: plugins: - type: "body-field-to-header" name: "openai-model-extractor" json: field_name: "model" header_name: "X-Gateway-Model-Name"Instal router berbasis isi menggunakan Helm:
helm install body-based-router \ oci://registry.k8s.io/gateway-api-inference-extension/charts/body-based-routing \ --version v1.4.0 \ --set provider.name=gke \ --set inferenceGateway.name=ray-multi-model-gateway \ --values helm-values.yaml
Men-deploy RayServices
Untuk men-deploy model, Anda harus menerapkan manifes RayService. Setiap manifes menentukan cluster Ray yang menjalankan LLM tertentu.
Buat file bernama
gemma-2b-it.yamldengan konten berikut:apiVersion: ray.io/v1 kind: RayService metadata: name: gemma-2b-it spec: serveConfigV2: | applications: - name: llm_app route_prefix: "/" import_path: ray.serve.llm:build_openai_app args: llm_configs: - model_loading_config: model_id: gemma-2b-it model_source: google/gemma-2b-it accelerator_type: L4 log_engine_metrics: true deployment_config: autoscaling_config: min_replicas: 2 max_replicas: 2 health_check_period_s: 600 health_check_timeout_s: 300 rayClusterConfig: headGroupSpec: rayStartParams: dashboard-host: "0.0.0.0" num-cpus: "0" template: spec: containers: - name: ray-head image: rayproject/ray-llm:2.54.0-py311-cu128 resources: limits: memory: "8Gi" ephemeral-storage: "32Gi" requests: cpu: "2" memory: "8Gi" ephemeral-storage: "32Gi" ports: - containerPort: 6379 name: gcs-server - containerPort: 8265 name: dashboard - containerPort: 10001 name: client - containerPort: 8000 name: serve env: - name: RAY_SERVE_THROUGHPUT_OPTIMIZED value: "1" - name: RAY_SERVE_ENABLE_HA_PROXY value: "1" - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token rayVersion: 2.54.0 workerGroupSpecs: - replicas: 2 minReplicas: 2 maxReplicas: 2 groupName: gpu-group rayStartParams: {} template: spec: containers: - name: llm image: rayproject/ray-llm:2.54.0-py311-cu128 env: - name: RAY_SERVE_THROUGHPUT_OPTIMIZED value: "1" - name: RAY_SERVE_ENABLE_HA_PROXY value: "1" - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token resources: limits: nvidia.com/gpu: "1" ephemeral-storage: "24Gi" requests: cpu: "6" memory: "24Gi" nvidia.com/gpu: "1" ephemeral-storage: "24Gi" nodeSelector: cloud.google.com/gke-accelerator: nvidia-l4Buat file bernama
qwen2.5-3b.yamldengan konten berikut:apiVersion: ray.io/v1 kind: RayService metadata: name: qwen-25-3b spec: serveConfigV2: | applications: - name: llm_app route_prefix: "/" import_path: ray.serve.llm:build_openai_app args: llm_configs: - model_loading_config: model_id: qwen-2.5-3b model_source: Qwen/Qwen2.5-3B accelerator_type: L4 log_engine_metrics: true deployment_config: autoscaling_config: min_replicas: 2 max_replicas: 2 health_check_period_s: 600 health_check_timeout_s: 300 rayClusterConfig: headGroupSpec: rayStartParams: dashboard-host: "0.0.0.0" num-cpus: "0" template: spec: containers: - name: ray-head image: rayproject/ray-llm:2.54.0-py311-cu128 resources: limits: memory: "8Gi" ephemeral-storage: "32Gi" requests: cpu: "2" memory: "8Gi" ephemeral-storage: "32Gi" ports: - containerPort: 6379 name: gcs-server - containerPort: 8265 name: dashboard - containerPort: 10001 name: client - containerPort: 8000 name: serve env: - name: RAY_SERVE_THROUGHPUT_OPTIMIZED value: "1" - name: RAY_SERVE_ENABLE_HA_PROXY value: "1" - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token rayVersion: 2.54.0 workerGroupSpecs: - replicas: 2 minReplicas: 2 maxReplicas: 2 groupName: gpu-group rayStartParams: {} template: spec: containers: - name: llm image: rayproject/ray-llm:2.54.0-py311-cu128 env: - name: RAY_SERVE_THROUGHPUT_OPTIMIZED value: "1" - name: RAY_SERVE_ENABLE_HA_PROXY value: "1" - name: HUGGING_FACE_HUB_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token resources: limits: nvidia.com/gpu: "1" ephemeral-storage: "24Gi" requests: cpu: "6" memory: "24Gi" nvidia.com/gpu: "1" ephemeral-storage: "24Gi" nodeSelector: cloud.google.com/gke-accelerator: nvidia-l4Deploy model:
kubectl apply -f gemma-2b-it.yaml kubectl apply -f qwen2.5-3b.yaml
Mengonfigurasi health check
Untuk membantu memastikan load balancer memantau kesehatan pekerja Ray secara akurat, Anda harus menerapkan resource HealthCheckPolicy.
Buat file bernama
healthcheck-policy.yamldengan konten berikut:apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy metadata: name: gemma-serve-healthcheck namespace: default spec: default: checkIntervalSec: 5 timeoutSec: 5 healthyThreshold: 2 unhealthyThreshold: 2 config: type: HTTP httpHealthCheck: port: 8000 requestPath: /-/healthz targetRef: group: "" kind: Service name: gemma-2b-it-serve-svc --- apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy metadata: name: qwen-serve-healthcheck namespace: default spec: default: checkIntervalSec: 5 timeoutSec: 5 healthyThreshold: 2 unhealthyThreshold: 2 config: type: HTTP httpHealthCheck: port: 8000 requestPath: /-/healthz targetRef: group: "" kind: Service name: qwen-25-3b-serve-svcTerapkan kebijakan health check:
kubectl apply -f healthcheck-policy.yaml
Mengonfigurasi perutean
Untuk mengonfigurasi perutean, Anda harus menerapkan manifes Gateway dan HTTPRoute.
HTTPRoute berisi aturan yang cocok dengan header X-Gateway-Model-Name (diisi oleh router berbasis isi) untuk merutekan traffic ke layanan Ray yang sesuai.
Buat file bernama
gateway.yamldengan konten berikut:apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: ray-multi-model-gateway namespace: default spec: gatewayClassName: gke-l7-rilb listeners: - allowedRoutes: namespaces: from: Same name: http port: 80 protocol: HTTP --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: ray-multi-model-route spec: parentRefs: - name: ray-multi-model-gateway rules: - matches: - headers: - type: Exact name: X-Gateway-Model-Name value: gemma-2b-it # Must match model named in JSON request! path: type: PathPrefix value: / backendRefs: - name: gemma-2b-it-serve-svc # Ray service name plus "-serve-svc". kind: Service port: 8000 - matches: - headers: - type: Exact name: X-Gateway-Model-Name value: qwen-2.5-3b # Matches another extracted model name path: type: PathPrefix value: / backendRefs: - name: qwen-25-3b-serve-svc # Target Ray Service. kind: Service port: 8000Terapkan gateway dan rute:
kubectl apply -f gateway.yaml
Melakukan pengujian deployment
Setelah Gateway disediakan dan kedua cluster Ray siap, Anda dapat menguji perutean dengan mengirim permintaan dengan nama model yang berbeda dalam isi JSON.
Dapatkan alamat IP Gateway:
kubectl get gateways ray-multi-model-gatewayMulai shell di jaringan yang dapat menjangkau alamat Gateway. Anda dapat menggunakan curl di salah satu Pod cluster Ray:
POD_NAME=$(kubectl get pods -l ray.io/node-type=head -o jsonpath='{.items[0].metadata.name}') kubectl exec -it $POD_NAME -- bashKirim permintaan dengan menguji perutean ke Gemma:
curl http://GATEWAY_IP_ADDRESS/v1/chat/completions \ --header 'Content-Type: application/json' \ --data '{ "model": "gemma-2b-it", "messages": [{"role": "user", "content": "Tell me about GKE."}] }'Ganti
GATEWAY_IP_ADDRESSdengan alamat IP dari langkah sebelumnya.Outputnya mirip dengan hal berikut ini:
{"id":"chatcmpl-594f7cab-f991-4522-9829-acdbb65d9f67","object":"chat.completion","created":1776379509,"model":"gemma-2b-it","choices":[{"index":0,"message":{"role":"assistant","content":"**Google Kubernetes Engine (GKE)** is a fully managed container orchestration service for Kubernetes [...]Uji perutean ke Qwen:
curl http://GATEWAY_IP_ADDRESS/v1/chat/completions \ --header 'Content-Type: application/json' \ --data '{ "model": "qwen-2.5-3b", "messages": [{"role": "user", "content": "How does Ray Serve work?"}] }'Outputnya mirip dengan hal berikut ini:
{"id":"chatcmpl-dfe3f3b7-45fc-481c-b53e-2fc09c033cdb","object":"chat.completion","created":1776380249,"model":"qwen-2.5-3b","choices":[{"index":0,"message":{"role":"assistant","content":"Ray Serve facilitates the hosting and deployment of scalable microservices. [...]
Router berbasis isi secara otomatis mengekstrak nilai kolom model dan memastikan setiap permintaan mencapai layanan backend yang benar yang dikonfigurasi dalam file gateway.yaml.
Pembersihan
Hapus cluster:
gcloud container clusters delete ${CLUSTER}
Langkah berikutnya
- Pelajari pengoptimalan performa untuk Ray Serve.
- Baca lebih lanjut tentang Gateway di GKE.