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 de vários clusters 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 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 do Identity and Access Management (IAM)
roles/container.admineroles/iam.serviceAccountAdminno projeto.Conclua os seguintes pré-requisitos da 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-2gNUM_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-2gNUM_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 as 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
Aviso: Cloud de Confiance by S3NS permite que cada rede VPC tenha apenas uma
sub-rede somente proxy por região. Se a região de destino já tiver uma sub-rede somente proxy com a configuração purpose=REGIONAL_MANAGED_PROXY, a criação da sub-rede GLOBAL_MANAGED_PROXY vai falhar. Primeiro, exclua a sub-rede somente proxy regional atual. A exclusão de uma sub-rede somente proxy regional afeta todos os
balanceadores de carga regionais baseados no Envoy nessa região que a usam. Portanto, planeje a
mudança de acordo.
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 modelos 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 é transferido 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: 600 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 gateway de inferência multicluster (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 mais baixa: o valor de meta da métrica na configuração do HPA precisa ser menor que a configuração
maxUtilizationPercentdefinida emGCPBackendPolicy. 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 mais baixa 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 aproximar 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 as 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.
Fazer o teste de carga do gateway
Aplique uma carga sustentada 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) processe.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
h100em ambos os clusters. - Métricas personalizadas: observe 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 de servidor de modelo 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 horizontalmente 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 gateway do GKE.
- Saiba mais sobre o Gateway de inferência de vários clusters do GKE.
- Saiba mais sobre a entrada de vários clusters.