In diesem Dokument wird erläutert, wie Sie Anfragen für die Inferenz über mehrere Ray Serve-Cluster in Google Kubernetes Engine (GKE) hinweg verwalten. Dazu konfigurieren Sie die Kubernetes Gateway API und das GKE Inference Gateway. Mit dieser Konfiguration können Sie die Trafficverwaltung für mehrere Teams zentralisieren, Arbeitslasten zur Erhöhung der Kapazität auf mehrere Regionen verteilen und modellbasiertes Routing basierend auf dem Inhalt des Anfragetextes implementieren.
Vorteile der Verwendung von GKE Inference Gateway und Ray Serve
Die Verwendung von GKE Inference Gateway und Ray Serve bietet folgende Vorteile:
- Pfadrouting: Konfigurieren Sie jeden RayService mit einem Pfadpräfix und stellen Sie ihn dann mit einem Gateway bereit, das Traffic an mehrere RayServices weiterleitet.
- Weitere Informationen zum Einrichten von Regeln für Pfadpräfixe finden Sie in der Gateway API-Dokumentation.
- Modellbasiertes Routing: Wählen Sie basierend auf dem Anfragetext einen RayService aus, an den weitergeleitet werden soll. Sie können beispielsweise das angeforderte Modell aus einer JSON-Anfrage der OpenAI API extrahieren.
- Governance: Sie können API-Schlüssel für die Verwendung Ihres Dienstes anfordern oder Kontingente für Nutzer erzwingen, indem Sie Apigee für die Authentifizierung und API-Verwaltung verwenden.
- Multiregional: Verteilen Sie Traffic auf mehrere GKE-Cluster mit RayServices, um mit Multi-Cluster-Gateways eine höhere Verfügbarkeit oder Kapazität zu erzielen.
- Trennung von Zuständigkeiten: Verwenden Sie separate RayServices, die von separaten Teams verwaltet werden können, separate Roll-outs durchlaufen und auf verschiedenen Topologien ausgeführt werden können.
- Sicherheit: Verwenden Sie das Gateway als SSL-Terminator, um den Traffic Ihrer Nutzer im Internet zu schützen. Weitere Informationen finden Sie unter Gateway-Sicherheit.
Zum Konfigurieren des Routings müssen Sie ein Gateway, eine HTTPRoute und einen RayService bereitstellen. Ein Kubernetes-Dienst für jeden Ziel-Ray-Cluster wird in der Regel von KubeRay erstellt. Ray Serve verteilt die Anfragelast im Cluster, ohne dass ein InferencePool oder Endpoint Picker erstellt werden muss.
Modellbasiertes Routing für Ray Serve in GKE
Das modellbasierte Routing wird durch eine Erweiterung für das textkörperbasierte Routing aktiviert. Mit dem textkörperbasierten Routing können Sie Traffic basierend auf dem in der Anfrage des Nutzers genannten Modell an verschiedene RayServices weiterleiten. So haben Sie einen einzigen Endpunkt, der viele Modelle bereitstellen kann, die in mehreren Ray-Clustern gehostet werden. Ihre Nutzer haben einen vereinfachten Zugriff und Ihre App-Entwickler können jeden Ray-Endpunkt konfigurieren.
Zum Konfigurieren des modellbasierten Routings stellen Sie die folgenden Schlüsselkomponenten bereit:
- Eine Erweiterung für den textkörperbasierten Router, um Modellnamen aus JSON-Nutzlasten zu extrahieren. Diese Routererweiterung wird mit Helm bereitgestellt.
- Ein GKE-Gateway (regionaler interner Application Load Balancer der Ebene 7) zur Verarbeitung des eingehenden Traffics.
- HTTPRoute-Regeln, um Traffic mithilfe von Headern, die von der Routererweiterung ausgefüllt werden, an den richtigen Ray-Dienst weiterzuleiten.
- Mehrere Ray Serve-Cluster, um den Lebenszyklus und das Autoscaling von isolierten Modellen zu verwalten.
Hinweis
Führen Sie die folgenden Aufgaben aus, bevor Sie beginnen:
- Aktivieren Sie die Google Kubernetes Engine API. Google Kubernetes Engine API aktivieren
- Wenn Sie die Google Cloud CLI für diesen Task verwenden möchten,
installieren und dann
initialisieren Sie die
gcloud CLI. Wenn Sie die gcloud CLI bereits installiert haben, rufen Sie die neueste
Version mit dem
gcloud components updateBefehl ab. Ältere gcloud CLI-Versionen unterstützen möglicherweise nicht die Ausführung der Befehle in diesem Dokument.
- Achten Sie darauf, dass Helm installiert ist.
- Erstellen Sie ein Hugging Face-Konto, falls Sie noch keines haben.
- Sie benötigen ein Hugging Face-Token.
Umgebung vorbereiten
Richten Sie Umgebungsvariablen ein:
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
Ersetzen Sie YOUR_HUGGING_FACE_TOKEN durch Ihr Hugging Face-Zugriffstoken.
Infrastruktur vorbereiten
In diesem Abschnitt richten Sie einen GKE-Cluster mit aktivierter Ray- und Gateway-Funktion mit L4-GPUs ein.
Erstellen Sie einen Cluster mit aktiviertem Ray-Operator und aktivierter Gateway API:
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-4Erstellen Sie einen GPU-Knotenpool für Ihre Modell-Arbeitslasten:
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=4Erstellen Sie ein Nur-Proxy-Subnetz für den regionalen internen Application Load Balancer, der für das textkörperbasierte Routing erforderlich ist:
gcloud compute networks subnets create bbr-proxy-only-subnet \ --purpose=REGIONAL_MANAGED_PROXY \ --role=ACTIVE \ --region=${REGION} \ --network=default \ --range=192.168.10.0/24Stellen Sie Ihr Hugging Face-Secret bereit:
kubectl create secret generic hf-secret \ --from-literal=hf_api_token=${HUGGING_FACE_TOKEN}
Textkörperbasierten Router für modellbasiertes Routing bereitstellen
Die Erweiterung für den textkörperbasierten Router fängt Anfragen ab, parst den JSON-Text und extrahiert das Modellfeld in einen X-Gateway-Model-Name-Header.
Erstellen Sie eine Datei mit dem Namen
helm-values.yamlund dem folgenden Inhalt:bbr: plugins: - type: "body-field-to-header" name: "openai-model-extractor" json: field_name: "model" header_name: "X-Gateway-Model-Name"Installieren Sie den textkörperbasierten Router mit 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
RayServices bereitstellen
Um Ihre Modelle bereitzustellen, müssen Sie die RayService-Manifeste anwenden. Jedes Manifest definiert einen Ray-Cluster, in dem ein bestimmtes LLM ausgeführt wird.
Erstellen Sie eine Datei mit dem Namen
gemma-2b-it.yamlund dem folgenden Inhalt: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-l4Erstellen Sie eine Datei mit dem Namen
qwen2.5-3b.yamlund dem folgenden Inhalt: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-l4Stellen Sie die Modelle bereit:
kubectl apply -f gemma-2b-it.yaml kubectl apply -f qwen2.5-3b.yaml
Systemdiagnosen konfigurieren
Damit der Load Balancer den Zustand der Ray-Worker genau überwachen kann, müssen Sie die Ressource HealthCheckPolicy anwenden.
Erstellen Sie eine Datei mit dem Namen
healthcheck-policy.yamlund dem folgenden Inhalt: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-svcWenden Sie die Systemdiagnoserichtlinie an:
kubectl apply -f healthcheck-policy.yaml
Routing konfigurieren
Zum Konfigurieren des Routings müssen Sie die Manifeste Gateway und HTTPRoute anwenden.
HTTPRoute enthält Regeln, die den X-Gateway-Model-Name-Header (der vom textkörperbasierten Router ausgefüllt wird) abgleichen, um Traffic an den entsprechenden Ray-Dienst weiterzuleiten.
Erstellen Sie eine Datei mit dem Namen
gateway.yamlund dem folgenden Inhalt: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: 8000Wenden Sie das Gateway und die Route an:
kubectl apply -f gateway.yaml
Deployment testen
Nachdem das Gateway bereitgestellt und beide Ray-Cluster bereit sind, können Sie das Routing testen, indem Sie Anfragen mit verschiedenen Modellnamen im JSON-Text senden.
Rufen Sie die IP-Adresse des Gateways ab:
kubectl get gateways ray-multi-model-gatewayStarten Sie eine Shell in einem Netzwerk, das die Gateway-Adresse erreichen kann. Sie können curl in einem der Ray-Cluster-Pods verwenden:
POD_NAME=$(kubectl get pods -l ray.io/node-type=head -o jsonpath='{.items[0].metadata.name}') kubectl exec -it $POD_NAME -- bashSenden Sie Anfragen, indem Sie das Routing zu Gemma testen:
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."}] }'Ersetzen Sie
GATEWAY_IP_ADDRESSdurch die IP-Adresse aus dem vorherigen Schritt.Die Ausgabe sieht etwa so aus:
{"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 [...]Testen Sie das Routing zu 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?"}] }'Die Ausgabe sieht etwa so aus:
{"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. [...]
Der textkörperbasierte Router extrahiert automatisch den Wert des Felds model und sorgt dafür, dass jede Anfrage den richtigen Backend-Dienst erreicht, der in der Datei gateway.yaml konfiguriert ist.
Bereinigen
Löschen Sie den Cluster:
gcloud container clusters delete ${CLUSTER}
Nächste Schritte
- Informationen zu Leistungsoptimierungen für Ray Serve.
- Weitere Informationen zu Gateway in GKE.