Neste documento, mostramos como configurar a alta disponibilidade elástica entre regiões para cargas de trabalho de inferência de IA usando o gateway de inferência multicluster do Google Kubernetes Engine (GKE) e o recurso de escalonamento automático do GKE. Essa configuração permite balancear a carga de maneira inteligente em várias cargas de trabalho em diferentes clusters do GKE em regiões distintas.
Para mais informações sobre o GKE Multi-Cluster Inference Gateway, consulte Sobre o GKE Multi-Cluster Inference Gateway.
Antes de começar
Ative a API do Google Kubernetes Engine.
Instale e inicialize a Google Cloud CLI se você planeja usá-la para essa tarefa.
Verifique se o projeto tem cota suficiente para GPUs H100. Para mais informações, consulte cota de GPU e alocação de recursos.
Use o GKE versão 1.34.1-gke.1127000 ou posterior.
Use a CLI gcloud versão 480.0.0 ou mais recente.
Verifique se a conta de serviço usada pelos nós tem as permissões
roles/monitoring.metricWritereroles/stackdriver.resourceMetadata.writer.Verifique se você tem os papéis
roles/container.admineroles/iam.serviceAccountAdmindo Identity and Access Management (IAM) no projeto.Conclua os seguintes pré-requisitos do Hugging Face:
- Crie uma conta do Hugging Face.
- Solicite e receba aprovação para acessar o modelo Llama 3.1 no Hugging Face.
- Assine o contrato de consentimento de licença na página do modelo no Hugging Face.
- Gere um token de acesso do Hugging Face com pelo menos permissões de leitura.
Criar clusters e pools de nós
Para criar dois clusters do GKE em regiões diferentes e configurar os pools de nós deles, siga estas etapas:
Crie o primeiro cluster:
gcloud container clusters create gke-west --zone \ CLUSTER_1_ZONE \ --project=PROJECT_ID \ --gateway-api=standard \ --cluster-version=GKE_VERSION \ --machine-type="MACHINE_TYPE" \ --disk-type="DISK_TYPE" \ --enable-managed-prometheus --monitoring=SYSTEM,DCGM \ --hpa-profile=performance \ --workload-pool=PROJECT_ID.s3ns.svc.id.goog \ --asyncSubstitua:
PROJECT_ID: ID do projeto;CLUSTER_1_ZONE: a zona do primeiro cluster, por exemplo,europe-west3-cGKE_VERSION: a versão do GKE a ser usada, por exemplo,1.34.1-gke.1127000MACHINE_TYPE: o tipo de máquina para os nós do cluster, por exemplo,c2-standard-16.DISK_TYPE: o tipo de disco para os nós do cluster, por exemplo,pd-standard.
Crie um pool de nós H100 no primeiro cluster:
gcloud container node-pools create h100 \ --accelerator "type=nvidia-h100-80gb,count=2,gpu-driver-version=latest" \ --project=PROJECT_ID \ --location=CLUSTER_1_ZONE \ --node-locations=CLUSTER_1_ZONE \ --cluster=CLUSTER_1_NAME \ --machine-type=NODE_POOL_MACHINE_TYPE \ --num-nodes=NUM_NODES \ --spot \ --min-nodes=MIN_NUM_NODES \ --max-nodes=MAX_NUM_NODES \ --enable-autoscaling \ --asyncSubstitua:
PROJECT_ID: ID do projeto;CLUSTER_1_ZONE: a zona do primeiro cluster, por exemplo,europe-west3-cCLUSTER_1_NAME: o nome do primeiro cluster, por exemplo,gke-westNODE_POOL_MACHINE_TYPE: o tipo de máquina do pool de nós, por exemplo,a3-highgpu-2g.NUM_NODES: o número de nós no pool de nós, por exemplo,3MIN_NUM_NODES: o número mínimo de nós para escalonamento automático no pool de nós, por exemplo,1MAX_NUM_NODES: o número máximo de nós para escalonamento automático no pool de nós, por exemplo,10
Receba as credenciais e crie um secret de token do Hugging Face no primeiro cluster:
gcloud container clusters get-credentials CLUSTER_1_NAME \ --location CLUSTER_1_ZONE \ --project=PROJECT_ID kubectl create secret generic hf-token \ --from-literal=token=HF_TOKENSubstitua:
PROJECT_ID: ID do projeto;CLUSTER_1_NAME: o nome do primeiro cluster, por exemplo,gke-westCLUSTER_1_ZONE: a zona do primeiro cluster, por exemplo,europe-west3-cHF_TOKEN: seu token de acesso do Hugging Face
Crie o segundo cluster em uma região diferente do primeiro:
gcloud container clusters create gke-east --zone CLUSTER_2_ZONE \ --project=PROJECT_ID \ --gateway-api=standard \ --cluster-version=GKE_VERSION \ --machine-type="MACHINE_TYPE" \ --disk-type="DISK_TYPE" \ --enable-managed-prometheus \ --monitoring=SYSTEM,DCGM \ --hpa-profile=performance \ --workload-pool=PROJECT_ID.s3ns.svc.id.goog \ --asyncSubstitua
CLUSTER_2_ZONEpela zona do segundo cluster, por exemplo,us-east4-a.Crie um pool de nós H100 para o segundo cluster:
gcloud container node-pools create h100 \ --accelerator "type=nvidia-h100-80gb,count=2,gpu-driver-version=latest" \ --project=PROJECT_ID \ --location=CLUSTER_2_ZONE \ --node-locations=CLUSTER_2_ZONE \ --cluster=CLUSTER_2_NAME \ --machine-type=NODE_POOL_MACHINE_TYPE \ --num-nodes=NUM_NODES \ --spot \ --min-nodes=MIN_NUM_NODES \ --max-nodes=MAX_NUM_NODES \ --enable-autoscaling \ --asyncSubstitua:
PROJECT_ID: ID do projeto;CLUSTER_2_ZONE: a zona do segundo cluster, por exemplo,us-east4-aCLUSTER_2_NAME: o nome do segundo cluster, por exemplo,gke-eastNODE_POOL_MACHINE_TYPE: o tipo de máquina do pool de nós, por exemplo,a3-highgpu-2g.NUM_NODES: o número de nós no pool de nós, por exemplo,3MIN_NUM_NODES: o número mínimo de nós para escalonamento automático no pool de nós, por exemplo,1MAX_NUM_NODES: o número máximo de nós para escalonamento automático no pool de nós, por exemplo,10
Receba as credenciais e crie um secret para o token do Hugging Face no segundo cluster:
gcloud container clusters get-credentials CLUSTER_2_NAME \ --location CLUSTER_2_ZONE \ --project=PROJECT_ID kubectl create secret generic hf-token --from-literal=token=HF_TOKENSubstitua o seguinte: Para definições de outras variáveis, consulte as etapas anteriores:
HF_TOKEN: seu token de acesso do Hugging Face
Registrar clusters em uma frota
Registre os clusters na frota do projeto:
gcloud container fleet memberships register CLUSTER_1_NAME \ --gke-cluster CLUSTER_1_ZONE/CLUSTER_1_NAME \ --location=global \ --project=PROJECT_ID gcloud container fleet memberships register CLUSTER_2_NAME \ --gke-cluster CLUSTER_2_ZONE/CLUSTER_2_NAME \ --location=global \ --project=PROJECT_IDSubstitua o seguinte e consulte as etapas anteriores para ver definições de outras variáveis:
CLUSTER_1_NAME: o nome do primeiro cluster, por exemplo,gke-westCLUSTER_2_NAME: o nome do segundo cluster, por exemplo,gke-east
Ative o recurso de Entrada de vários clusters e designe um cluster de configuração:
gcloud container fleet ingress enable \ --config-membership=projects/PROJECT_ID/locations/global/memberships/CLUSTER_1_NAMESubstitua o seguinte: Para definições de outras variáveis, consulte as etapas anteriores:
PROJECT_ID: ID do projeto;CLUSTER_1_NAME: o nome do primeiro cluster, por exemplo,gke-west
Criar sub-redes somente proxy
Crie uma sub-rede na região do primeiro cluster:
gcloud compute networks subnets create CLUSTER_1_REGION-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=CLUSTER_1_REGION \ --network=default \ --range=SUBNET_RANGE_1 \ --project=PROJECT_IDSubstitua:
PROJECT_ID: ID do projeto;CLUSTER_1_REGION: a região do primeiro cluster, por exemplo,europe-west3SUBNET_RANGE_1: o intervalo de IP da sub-rede somente proxy na região do primeiro cluster, por exemplo,10.0.0.0/23
Crie uma sub-rede na região do segundo cluster:
gcloud compute networks subnets create CLUSTER_2_REGION-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=CLUSTER_2_REGION \ --network=default \ --range=SUBNET_RANGE_2 \ --project=PROJECT_IDSubstitua:
PROJECT_ID: ID do projeto;CLUSTER_2_REGION: a região do segundo cluster, por exemplo,us-east4SUBNET_RANGE_2: o intervalo de IP da sub-rede somente proxy na região do segundo cluster, por exemplo,10.5.0.0/23
Instalar os recursos personalizados necessários
Defina variáveis de contexto para seus clusters:
CLUSTER1_CONTEXT="gke_PROJECT_ID_CLUSTER_1_ZONE_CLUSTER_1_NAME" CLUSTER2_CONTEXT="gke_PROJECT_ID_CLUSTER_2_ZONE_CLUSTER_2_NAME"Substitua:
PROJECT_ID: ID do projeto;CLUSTER_1_ZONE: a zona do primeiro cluster, por exemplo,europe-west3-cCLUSTER_1_NAME: o nome do primeiro cluster, por exemplo,gke-westCLUSTER_2_ZONE: a zona do segundo cluster, por exemplo,us-east4-aCLUSTER_2_NAME: o nome do segundo cluster, por exemplo,gke-east
Instale o recurso personalizado InferencePool e InferenceObjective nos dois clusters:
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/v1.0.1/manifests.yaml --context=$CLUSTER1_CONTEXT kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/v1.0.1/manifests.yaml --context=$CLUSTER2_CONTEXT
Implantar recursos nos clusters de destino
Implante os servidores de modelo nos dois clusters:
kubectl apply -f \ https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/release-1.0/config/manifests/vllm/gpu-deployment.yaml \ --context=$CLUSTER1_CONTEXT kubectl apply -f \ https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/release-1.0/config/manifests/vllm/gpu-deployment.yaml \ --context=$CLUSTER2_CONTEXTSalve o seguinte manifesto em um arquivo chamado
inference-objective.yaml:apiVersion: inference.networking.x-k8s.io/v1alpha2 kind: InferenceObjective metadata: name: food-review spec: priority: 10 poolRef: name: llama3-8b-instruct group: "inference.networking.k8s.io"Aplique o manifesto aos dois clusters:
kubectl apply -f inference-objective.yaml --context=$CLUSTER1_CONTEXT kubectl apply -f inference-objective.yaml --context=$CLUSTER2_CONTEXTImplante os recursos do InferencePool nos dois clusters usando o Helm:
helm install vllm-llama3-8b-instruct \ --kube-context $CLUSTER1_CONTEXT \ --set inferencePool.modelServers.matchLabels.app=vllm-llama3-8b-instruct \ --set provider.name=gke \ --set inferenceExtension.monitoring.gke.enabled=true \ --version v1.0.1 \ oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepool helm install vllm-llama3-8b-instruct \ --kube-context $CLUSTER2_CONTEXT \ --set inferencePool.modelServers.matchLabels.app=vllm-llama3-8b-instruct \ --set provider.name=gke \ --set inferenceExtension.monitoring.gke.enabled=true \ --version v1.0.1 \ oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepoolNos dois clusters, marque os recursos
InferencePoolcomo exportados:kubectl annotate inferencepool vllm-llama3-8b-instruct networking.gke.io/export="True" \ --context=$CLUSTER1_CONTEXT kubectl annotate inferencepool vllm-llama3-8b-instruct networking.gke.io/export="True" \ --context=$CLUSTER2_CONTEXT
Implantar o gateway de inferência entre regiões
Salve o seguinte manifesto como
mygateway.yaml:--- kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: cross-region-gateway namespace: default spec: gatewayClassName: gke-l7-cross-regional-internal-managed-mc addresses: - type: networking.gke.io/ephemeral-ipv4-address/europe-west3 value: "europe-west3" - type: networking.gke.io/ephemeral-ipv4-address/us-east4 value: "us-east4" listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute namespaces: from: All --- apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: vllm-llama3-8b-instruct-default spec: parentRefs: - name: cross-region-gateway kind: Gateway rules: - backendRefs: - group: networking.gke.io kind: GCPInferencePoolImport name: vllm-llama3-8b-instruct --- kind: HealthCheckPolicy apiVersion: networking.gke.io/v1 metadata: name: health-check-policy namespace: default spec: targetRef: group: "networking.gke.io" kind: GCPInferencePoolImport name: vllm-llama3-8b-instruct default: config: type: HTTP httpHealthCheck: requestPath: /health port: 8000Aplique o manifesto ao cluster de configuração:
kubectl apply -f mygateway.yaml --context=CLUSTER1_CONTEXTSubstitua:
CLUSTER1_CONTEXT: o contexto do primeiro cluster, por exemplo,gke_my-project_europe-west3-c_gke-west
Ativar relatórios de métricas personalizadas
Crie um arquivo chamado
metrics.yamlcom o conteúdo a seguir:apiVersion: autoscaling.gke.io/v1beta1 kind: AutoscalingMetric metadata: name: gpu-cache namespace: default spec: selector: matchLabels: app: vllm-llama3-8b-instruct endpoints: - port: 8000 path: /metrics metrics: - name: vllm:kv_cache_usage_perc exportName: kv-cache - name: vllm:gpu_cache_usage_perc exportName: kv-cache-oldPara cada cluster, aplique a configuração de métricas:
kubectl apply -f metrics.yaml --context=CLUSTER1_CONTEXT kubectl apply -f metrics.yaml --context=CLUSTER2_CONTEXTPara definições de
CLUSTER1_CONTEXTeCLUSTER2_CONTEXT, consulte Instalar os recursos personalizados necessários.
Configurar a política de balanceamento de carga
Nesta seção, descrevemos como configurar a política de balanceamento de carga. Essa política define como o tráfego é distribuído entre seus pools de inferência com base em métricas personalizadas e preferências regionais. A configuração a seguir define us-east4 como a região preferida. O tráfego transborda para outras regiões somente quando a métrica personalizada gke.named_metrics.kv-cache na região us-east4 atinge 80% de utilização.
- Para as versões v0.10.2 e mais recentes do vLLM, use a métrica
gke.named_metrics.kv-cache. - Para versões anteriores, use a métrica
gke.named_metrics.kv-cache-old.
Crie um arquivo chamado
backend-policy.yamlcom o conteúdo a seguir:kind: GCPBackendPolicy apiVersion: networking.gke.io/v1 metadata: name: my-backend-policy spec: targetRef: group: "networking.gke.io" kind: GCPInferencePoolImport name: vllm-llama3-8b-instruct default: timeoutSec: 100 balancingMode: CUSTOM_METRICS trafficDuration: LONG customMetrics: - name: gke.named_metrics.kv-cache maxUtilizationPercent: 80 dryRun: false scopes: - selector: gke.io/region: "us-east4" backendPreference: PREFERREDAplique a nova política:
kubectl apply -f backend-policy.yaml --context=CLUSTER1_CONTEXTSubstitua
CLUSTER1_CONTEXTpelo contexto do primeiro cluster, por exemplo,gke_my-project_europe-west3-c_gke-west.
Configure o escalonamento automático
Para garantir que cada cluster possa lidar com uma carga crescente antes que o tráfego seja transferido para outras regiões, configure o escalonador automático horizontal de pods (HPA) para as implantações do servidor de modelo.
Princípios importantes de configuração
Use as mesmas métricas personalizadas: o HPA precisa ser configurado para escalonar com base nas mesmas métricas personalizadas usadas no
GCPBackendPolicydo Multi-Cluster Inference Gateway (por exemplo,vllm:kv_cache_usage_perc). Essa abordagem ajuda a garantir que as decisões de balanceamento de carga e escalonamento sejam impulsionadas pelo mesmo sinal dos servidores de inferência. As métricas escolhidas precisam ter um valor entre 0 e 1 para representar a utilização. Se o valor da métrica for maior que 1, ele será interpretado como 100% de utilização pelo balanceador de carga, o que pode causar comportamentos de roteamento inesperados.Defina uma meta de HPA menor: o valor da meta para a métrica na configuração do HPA precisa ser menor que a configuração
maxUtilizationPercentdefinida noGCPBackendPolicy. Ao definir uma meta de utilização menor para o HPA (por exemplo, o HPA é escalonado com 50% de utilização média), você permite que o cluster adicione mais réplicas antes que o limite do balanceador de carga (por exemplo, 80% de utilização) seja atingido. Essa abordagem ajuda a maximizar a capacidade na região preferida. Uma meta de utilização menor também ajuda a evitar o transbordamento prematuro de tráfego, reservando a alta disponibilidade elástica entre regiões para quando a região atual realmente se aproxima dos limites.
Permita que o usuário crie os papéis de autorização necessários:
kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole cluster-admin --user "$(gcloud config get-value account)" --context=CLUSTER1_CONTEXT kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole cluster-admin --user "$(gcloud config get-value account)" --context=CLUSTER2_CONTEXTAs variáveis
CLUSTER1_CONTEXTeCLUSTER2_CONTEXTsão definidas na seção Instalar os recursos personalizados necessários.Para cada cluster, aplique o manifesto:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml --context=CLUSTER1_CONTEXT kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml --context=CLUSTER2_CONTEXTPermita que a conta de serviço
custom-metrics-stackdriver-adapterleia métricas do Cloud Monitoring:PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)") gcloud projects add-iam-policy-binding projects/PROJECT_ID \ --role roles/monitoring.viewer \ --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.s3ns.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapterSubstitua
PROJECT_IDpelo ID do projeto.Salve o seguinte manifesto em um arquivo chamado
pod-monitoring.yaml:apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: inference-server-podmon spec: selector: matchLabels: app: vllm-llama3-8b-instruct endpoints: - port: 8000 path: /metrics interval: 5sAplique o manifesto aos dois clusters:
kubectl apply -f pod-monitoring.yaml --context=CLUSTER1_CONTEXT kubectl apply -f pod-monitoring.yaml --context=CLUSTER2_CONTEXTSalve o seguinte manifesto em um arquivo chamado
hpa.yaml:apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: inference-server-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: vllm-llama3-8b-instruct minReplicas: 1 maxReplicas: 10 metrics: - type: Pods pods: metric: name: prometheus.googleapis.com|vllm:gpu_cache_usage_perc|gauge target: type: AverageValue averageValue: "0.5"Aplique o manifesto aos dois clusters:
kubectl apply -f hpa.yaml --context=CLUSTER1_CONTEXT kubectl apply -f hpa.yaml --context=CLUSTER2_CONTEXT
Verificar a implantação
Consiga o endereço IP do gateway:
export GW_IP=$(kubectl get gateway/cross-region-gateway -n default --context=CLUSTER1_CONTEXT -o jsonpath='{.status.addresses[0].value}') echo ${GW_IP}A variável
CLUSTER1_CONTEXTé definida na seção Instalar os recursos personalizados necessários.Inicie uma sessão interativa do
shem um pod temporário:kubectl run -it --rm --image=curlimages/curl curly --context=CLUSTER1_CONTEXT -- /bin/shA variável
CLUSTER1_CONTEXTé definida na seção Instalar os recursos personalizados necessários.De dentro do pod
curly, envie uma solicitação de teste:curl -i -X POST <var>GW_IP</var>:80/v1/completions \ -H 'Content-Type: application/json' \ -d '{ "model": "food-review-1", "prompt": "What is the best pizza in the world?", "max_tokens": 100, "temperature": 0 }'Substitua
GW_IPpelo endereço IP do gateway da etapa anterior.
Testar a carga do gateway
Aplique uma carga constante ao endereço IP do gateway usando um gerador de carga na mesma rede VPC.
Comece com uma carga moderada que você espera que a região preferencial (
us-east4) consiga processar.Aumente gradualmente a taxa de solicitação ou a simultaneidade do teste de carga.
Enquanto o teste de carga é executado, monitore o sistema no console do Cloud de Confiance ou usando
kubectl:- Escalonamento de pods (HPA): verifique o número de pods na implantação
vllm-llama3-8b-instructnos dois clusters. - Escalonamento de nós (escalonador automático de clusters): monitore o número de nós nos pools de nós
h100nos dois clusters. - Métricas personalizadas: monitore a métrica
vllm:kv_cache_usage_perc(para vllm versão v0.10.2 e mais recente) ou a métricavllm:gpu_cache_usage_perc(para vllm versão anterior a v.0.10.2) no Monitoring para implantações do servidor de modelos nos dois clusters. - Métricas do balanceador de carga: examine as métricas do balanceador de carga associado ao
cross-region-gatewayno Monitoring.
- Escalonamento de pods (HPA): verifique o número de pods na implantação
À medida que você aumenta a carga, a utilização em us-east4 aumenta. Quando o HPA no cluster gke-east aumenta a escala e a utilização média se aproxima do valor maxUtilization (80%) definido em GCPBackendPolicy, o balanceador de carga começa a rotear solicitações para o cluster gke-west em europe-west3.
A seguir
- Saiba mais sobre a API GKE Gateway.
- Saiba mais sobre o gateway de inferência de vários clusters do GKE.
- Saiba mais sobre a entrada de vários clusters.