O Google Kubernetes Engine (GKE) permite escalonar clusters do Agent Substrate no GKE para oferecer suporte a cargas de trabalho de agentes de IA de alta simultaneidade, minimizando os custos de computação ociosa. Ao combinar pools de nós de infraestrutura de sistema dedicados com ComputeClasses personalizadas e buffers de capacidade, é possível isolar componentes críticos do sistema, automatizar o fallback de hardware em séries de máquinas do Compute Engine e manter a capacidade de worker em espera ativa.
Leia este documento para dimensionar corretamente os componentes do cluster do GKE, isolar a infraestrutura do sistema e os pools de nós do banco de dados, configurar o provisionamento automático de nós para recursos do WorkerPool e planejar a manutenção e os upgrades do cluster. Este documento é destinado a administradores de plataforma que provisionam e gerenciam o Agent Substrate na infraestrutura do GKE.
Antes de começar
Antes de configurar a infraestrutura do cluster para escalonamento, verifique se o ambiente atende aos seguintes requisitos:
- Modo e versão do cluster do GKE: use um cluster do GKE Standard em que o plano de controle e os pools de nós executem a versão 1.37 ou mais recente. Os clusters do Autopilot do GKE não são compatíveis com o Agent Substrate no GKE.
- Instalação do Agent Substrate no GKE: é necessário ter uma instalação do Agent Substrate no GKE ou planejar a instalação do Agent Substrate no GKE com o isolamento de nós da infraestrutura do sistema ativado. Para conferir as etapas de instalação, consulte Instalar o Agent Substrate no GKE.
Dimensionar o cluster do Agent Substrate
Dimensione o cluster para picos simultâneos e taxas de retomada de pico, em vez de médias. Os nós de trabalho precisam conter o número máximo de atores em execução ao mesmo tempo, e os componentes da infraestrutura do sistema e os caminhos de armazenamento precisam acompanhar a taxa mais rápida de retomadas e suspensões de atores.
Estimar os picos de carga de trabalho
Se você não tiver medições de produção, estime a simultaneidade de pico
e a taxa de retomada com base no número total de atores registrados (total_actors), na
fração média de atores em execução simultânea (average_active_fraction),
no multiplicador de pico de tráfego (burst_factor) e na duração média em que um
ator permanece ativo por turno (average_seconds_active_per_resume):
peak_running_actors = total_actors × average_active_fraction × burst_factor
peak_resume_rate = peak_running_actors / average_seconds_active_per_resumePor exemplo, se você tiver 100.000 atores no total, com 10% ativos em média (10.000 atores) e um fator de pico de dois, seu cluster precisará oferecer suporte a 20.000 atores em execução no pico. Se cada ator for executado por uma média de 100 segundos antes de ser suspenso, para manter esse pico, serão necessárias 200 retomadas por segundo e 200 suspensões por segundo.
O Agent Substrate no GKE não suspende automaticamente os atores inativos. Seu aplicativo ou orquestrador precisa acionar a suspensão.
Dimensionar o plano de dados
Nesta seção, abordamos as práticas recomendadas para dimensionar o plano de dados, incluindo pods de worker, nós do GKE, largura de banda de snapshot e o agente de nó atelet.
Calcular pods de worker e nós do GKE
Cada pod de worker em um WorkerPool hospeda vários atores. Um worker pode aceitar um
novo ator enquanto hospeda menos atores do que o limite definido pela flag --max-actors
no contêiner ateworker (padrão 1000) e tem capacidade de CPU
e memória restante suficiente para se ajustar aos limites de ActorTemplate. Para mais informações sobre
como os limites de workers interagem com os limites de atores, consulte o guia de código aberto Recursos de dimensionamento
adequado na API Agent Substrate.
Calcule o número necessário de pods de worker com 20% de capacidade de programação disponível (o fator 0.8):
slots_per_worker = min(max_actors, worker_memory / actor_memory, worker_cpu / actor_cpu)
total_workers = peak_running_actors / (slots_per_worker × 0.8)Nessa fórmula, a variável max_actors assume como padrão 1000 (configurada pela
flag --max-actors). Subtraia a memória que o worker reserva para o próprio processo do valor de worker_memory. Para recursos de WorkerPool de microVM,
adicione a sobrecarga de memória do monitor de máquina virtual (VMM) por ator informada pelo
Worker ao valor actor_memory, porque o posicionamento conta essa sobrecarga
em relação à capacidade do Worker.
Com um pod de worker por nó, o número de workers é igual ao número de nós de trabalho do GKE. Não aloque 100% da CPU e da memória alocáveis de um nó para o pod de worker. Deixe capacidade em cada nó para o DaemonSet atelet (no namespace ate-system) e os daemons do sistema do GKE.
O GKE Standard aceita até 65.000 nós por cluster
e até 512 pods por nó. O
máximo padrão é de 110 pods por nó (configurável com a
flag --max-pods-per-node), e clusters grandes têm requisitos
adicionais.
Dimensionar a largura de banda do snapshot e os discos de nós
Cada suspensão do Actor grava um snapshot no disco do nó local no caminho do diretório /var/lib/ate. No modo SYNCHRONOUS, o agente atelet faz upload
do snapshot para o Cloud Storage antes que a operação de suspensão seja retornada. No modo ASYNCHRONOUS, o agente atelet programa o upload para o Cloud Storage após um atraso de aproximadamente o valor da flag --snapshot-upload-delay (padrão 5m) a partir do momento em que o snapshot é criado. O Agent Substrate armazena em cache o snapshot mais recente no nó pelo
período configurado na flag --snapshot-detach-delay, que tem como padrão um
valor de 30m. Um ator que é retomado dentro dessa janela é programado no mesmo
nó e restaurado do disco local, em vez de fazer o download do snapshot do
Cloud Storage.
Estime o tamanho do snapshot descompactado (snapshot_size) como o
limite de memória do ActorTemplate mais os dados gravados no sistema de arquivos raiz
gravável ou nos diretórios duráveis. O processamento de arquivos esparsos e a compactação zstd
reduzem o tamanho do snapshot compactado (compressed_snapshot_size) transferido de
e para o Cloud Storage, onde o Agent Substrate armazena até
dois snapshots por ator (o anterior e o em andamento):
- Largura de banda de pico do Cloud Storage (cada direção):
peak_resume_rate × compressed_snapshot_size - Capacidade de processamento de gravação de disco de pico por nó:
2 × peak_resume_rate × snapshot_size / total_nodes(tanto os downloads de retomada quanto os checkpoints de suspensão gravam no disco do nó).
O disco de inicialização hyperdisk-balanced padrão de 100 GiB no GKE
oferece 3.600 IOPS e 290 MiB/s de
capacidade de processamento
(o desempenho padrão é dimensionado de acordo com o tamanho do disco), o que pode limitar as operações de snapshot
em caso de E/S pesada do convidado. Ao criar pools de nós de trabalho, monte um disco dedicado no caminho do diretório /var/lib/ate/snapshots ou aumente o desempenho do disco de inicialização usando as flags --boot-disk-provisioned-iops e --boot-disk-provisioned-throughput com o comando gcloud container node-pools create.
Verificar a cota do Security Token Service
Cada transferência de snapshot de ou para o Cloud Storage requer um token com escopo
para o ator, que o componente ate-api-server solicita da
API Security Token Service (STS). O
componente ate-api-server faz até uma solicitação de STS por ator a cada 20 a 40
minutos (normalmente na primeira retomada nessa janela) e reutiliza o token
até 20 minutos antes da expiração.
A cota Exchange token global requests do STS tem como padrão 6.000 solicitações por projeto por minuto e é compartilhada com a Federação de Identidade da Carga de Trabalho para GKE:
- Cota necessária do STS (solicitações por minuto): estimativa de até 60 vezes
a taxa de pico de retomadas para atores cuja última transferência de snapshot foi há mais
de 20 minutos, além da capacidade para
a Federação de Identidade da Carga de Trabalho para GKE. Se você não souber essa taxa, use
a fórmula
60 × peak_resume_ratecomo substituto. Por exemplo, 200 currículos por segundo exigem até 12.000 solicitações por minuto. - Como aumentar a cota: solicite um aumento de cota na página Cotas e limites do sistema no console do Google Cloud . As transferências de snapshot funcionam sem a API Security Token Service ativada no projeto, mas é necessário ativar a API para que a cota apareça na página Cotas e limites do sistema. Para mais informações, consulte Cota para a API Exchange Token no Security Token Service na documentação da Federação de Identidade da Carga de Trabalho para GKE.
Ajustar o agente de nó atelet
O DaemonSet atelet executa um pod por nó de trabalho para restaurar e criar checkpoints de
atores. Em cada pod atelet, o contêiner objectstore-plugin compacta e
transfere snapshots de e para o Cloud Storage.
A tabela a seguir descreve as principais configurações de dimensionamento para os contêineres atelet e
objectstore-plugin:
| Configuração | Padrão | Orientações de dimensionamento |
|---|---|---|
CPU e memória do contêiner atelet e objectstore-plugin
|
Solicitações: 50 mCPU, 128 MiB de memória; sem limites |
Configure a QoS com capacidade de burst sem limites de memória omitindo os limites de memória
em ambos os contêineres, porque atingir um limite de memória interrompe o agente do nó
e todas as retomadas no nó. Aumente as solicitações de CPU e memória para
corresponder ao pico de uso medido em um nó completo na taxa de retomada de pico para que
os pods de worker não consumam os recursos necessários para o agente do
atelet.
|
--upload-memory-budget
(contêiner objectstore-plugin) e
--snapshot-upload-workers (contêiner
atelet)
|
Orçamento de 512 MiB; 2 workers de upload |
Para evitar que uploads simultâneos de snapshots fiquem em fila em nós com vários atores com altas taxas de suspensão, faça o seguinte:
|
Sinalização --drain-timeout e
campo terminationGracePeriodSeconds
|
5 minutos (flag --drain-timeout); 330 segundos
(campo terminationGracePeriodSeconds)
|
Controla por quanto tempo o agente do atelet conclui as restaurações em andamento
e os uploads de snapshot quando o pod é interrompido durante uma drenagem ou
upgrade de nó. Se você aumentar o valor da flag --drain-timeout
para snapshots grandes, aumente também o valor do
campo terminationGracePeriodSeconds no
DaemonSet atelet para que o agente kubelet não
interrompa o agente atelet antes que os uploads sejam concluídos.
|
Dimensionar os componentes da infraestrutura do sistema e o banco de dados
Para implantações de componentes do sistema sem estado no namespace ate-system que
escalonam horizontalmente, estime a contagem de réplicas necessária com 35% de capacidade
disponível (o fator 0.65) mais uma réplica sobressalente (+ 1) para tolerar interrupções
de nós:
replicas = ceil(peak_load / (capacity_per_replica × 0.65)) + 1O escalonamento horizontal para de melhorar a capacidade de processamento depois que uma dependência compartilhada (como a CPU do PostgreSQL ou os limites de conexão) atinge a capacidade máxima. Dimensione os componentes da infraestrutura do sistema e o banco de dados juntos. Para mais informações sobre as flags de componente, consulte o guia de instalação do operador de código aberto.
A tabela a seguir descreve as regras de recursos e escalonamento para cada componente de infraestrutura do sistema:
| Componente | Regras de QoS e de recursos | Escalonamento e ajuste de conexão |
|---|---|---|
Roteador de entrada (atenet-router) |
Configure a QoS garantida: defina solicitações e limites de CPU e memória correspondentes para que o ambiente de execução do Go alinhe a contagem de linhas de execução com o orçamento de CPU do contêiner. | Escalone as réplicas horizontalmente com base no pico de solicitações de entrada por segundo, na sobrecarga de mTLS e nos tamanhos de payload de solicitação. |
Servidor de API (ate-api-server) |
Configure a QoS garantida: defina solicitações e limites de CPU e memória correspondentes para que o ambiente de execução do Go alinhe a contagem de linhas de execução com o orçamento de CPU do contêiner. |
Escalone as réplicas com base nos ciclos de retomada e suspensão de pico por segundo
(aproximadamente 4 ms de CPU por ciclo de retomada e suspensão) e
na carga de pesquisa de solicitações de entrada. Defina explicitamente a
configuração ateapi.postgres.poolMaxConns. Cada réplica abre até
poolMaxConns + 6 conexões de banco de dados, e a soma
de todas as réplicas precisa ser menor que a configuração
max_connections do PostgreSQL.
|
| Banco de dados (PostgreSQL) |
Configure a QoS com capacidade de intermitência com memória garantida: defina
solicitações de memória iguais aos limites para bloquear o cache do shared_buffers
na memória e ajudar a evitar a remoção por falta de memória (OOM, na sigla em inglês). Omita os limites de CPU
ao executar em um nó ate-postgres dedicado para que
a limitação de CPU do kernel não desacelere as intermitências de checkpoint e
autovacuum.
|
Escalone verticalmente esse StatefulSet de instância única. Provisione CPU suficiente
para ficar com menos de 80% de utilização no pico de carga, RAM suficiente para armazenar em cache
a tabela Actor (com o parâmetro shared_buffers definido como
aproximadamente 25% da memória) e um StorageClass com suporte de SSD definido no
momento da instalação com a configuração
ateapi.postgres.storageClass (por exemplo, o StorageClass dynamic-rwo em C4 ou
N4 ou o StorageClass premium-rwo em C3 ou N2). Aumente
o parâmetro max_connections no
ConfigMap postgres-config (o arquivo
postgresql.conf) para que todas as réplicas ate-api-server caibam.
|
Proxy de saída (atenet-egress) |
Regras de recursos: defina uma solicitação de CPU de 512 mCPU (limite de 8 vCPUs) e uma solicitação de memória de 512 MiB (limite de 1 GiB). Aumente as solicitações e os limites se o tráfego de saída do Actor apresentar aumento de latência. | Escalonar réplicas horizontalmente com base no tráfego de solicitações de saída do ator. |
Controlador de worker (ate-controller) |
Regras de recursos: mantenha uma réplica (sem eleição de líder). Defina solicitações de CPU e memória com base no pico de uso durante grandes eventos de escalonamento horizontal do WorkerPool. |
Se os novos pods de worker demorarem muito para serem registrados em frotas grandes, aumente o valor da flag --worker-sync-concurrency
(padrão 2).
|
Controlador de certificado (podcertificate-controller)
|
Regras de recursos: são executadas no
namespace podcertificate-controller-system para assinar certificados
mTLS para novos pods de worker antes que eles possam aceitar atores.
|
Para frotas de milhares de workers, aumente os valores da
configuração podcert.workersPerSigner (padrão 0,
que mantém o padrão do manifesto de 1 worker por signatário),
a flag --kube-api-qps (padrão 5) e a
flag --kube-api-burst (padrão 10).
|
Provedor de identidade (ate-idp-server) |
Regras de recursos: exibe o documento de descoberta do OpenID Connect (OIDC) e o conjunto de chaves da Web JSON (JWKS) no namespace ate-system para verificar os JSON Web Tokens (JWTs) do ator. Defina as solicitações de CPU e memória com base no volume máximo de consultas JWKS.
|
Escalone as réplicas horizontalmente se as partes confiáveis consultarem o endpoint JWKS com altas taxas de solicitação sem armazenar as chaves de cache. |
Provedor de credenciais (k8s-credential-provider)
|
Regras de recursos: são executadas no namespace ate-system
quando a injeção de credenciais do Secret do Kubernetes está ativada. Defina
as solicitações de CPU e memória com base no volume de injeção de credenciais de saída.
|
Escalone as réplicas horizontalmente com base na taxa de solicitações de saída do ator
que exigem a injeção de credenciais do Secret do Kubernetes no
proxy atenet-egress.
|
Isolar a infraestrutura do sistema e os pools de nós de trabalho
Em clusters de produção, o tráfego de snapshots e a programação de atores com alta rotatividade nos nós de trabalho podem competir com os componentes da infraestrutura do sistema por CPU, memória e E/S de disco. Separe o cluster do GKE em três níveis distintos de pool de nós:
- Pool de nós do banco de dados (rótulo
ate-postgres): um pool de nós dedicado para o StatefulSet do PostgreSQL, que armazena todos os metadados de atores e workers. - Pool de nós de infraestrutura do sistema (rótulo
ate-system-infra): um pool de nós dedicado para os serviços restantes de infraestrutura do sistema (os componentesatenet-router,ate-api-server,atenet-egress,ate-controller,ate-idp-serverek8s-credential-provider). - Pools de nós de trabalho (WorkerPool): pools de nós escalonados dinamicamente gerenciados por ComputeClasses personalizadas do GKE e buffers de capacidade do GKE para hospedar sandboxes de atores ativos.
É possível isolar os componentes de infraestrutura do banco de dados e do sistema em nós dedicados ao instalar o Agent Substrate no GKE usando a configuração cordonSystemInfraComponents (ou a flag --cordon-system-infra-components). Antes de instalar, crie
os dois pools de nós com os rótulos necessários e os taints NoSchedule:
# 1. Create the dedicated PostgreSQL node pool
gcloud container node-pools create ate-postgres-pool \
--cluster=CLUSTER_NAME \
--location=LOCATION \
--node-locations=POSTGRES_ZONE \
--machine-type=POSTGRES_MACHINE_TYPE \
--num-nodes=1 \
--node-labels=ate.dev/workloadType=ate-postgres \
--node-taints=ate.dev/workloadType=ate-postgres:NoSchedule
# 2. Create the dedicated system infrastructure node pool
gcloud container node-pools create ate-system-infra-pool \
--cluster=CLUSTER_NAME \
--location=LOCATION \
--machine-type=SYSTEM_INFRA_MACHINE_TYPE \
--num-nodes=2 \
--node-labels=ate.dev/workloadType=ate-system-infra \
--node-taints=ate.dev/workloadType=ate-system-infra:NoSchedule
Substitua:
CLUSTER_NAME: o nome do cluster do GKE Standard.LOCATION: a zona ou região do Compute Engine do plano de controle do cluster.POSTGRES_ZONE: uma única zona do Compute Engine para o StatefulSet do PostgreSQL de réplica única. Para um cluster regional, especifique uma zona na região do cluster para que o pool de nós provisione um único nó na zona em que o disco permanente do StatefulSet será criado. Para um cluster zonal, especifique a zona do cluster.POSTGRES_MACHINE_TYPE: o tipo de máquina do Compute Engine dimensionado para sua instância do PostgreSQL.SYSTEM_INFRA_MACHINE_TYPE: o tipo de máquina do Compute Engine dimensionado para os componentes da infraestrutura do sistema (por exemplo, o tipo de máquinac3-standard-8).
Em um cluster regional, a flag --num-nodes se aplica por zona. Por exemplo,
definir a flag --num-nodes=2 em três zonas cria seis nós no total. Para
colocar o pool de nós ate-system-infra-pool em zonas específicas, adicione a
flag --node-locations.
Se você ativar a configuração cordonSystemInfraComponents durante a instalação e
um dos pool de nós estiver ausente, os pods do sistema correspondentes vão permanecer no
estado Pending.
Automatizar a segmentação de hardware usando ComputeClasses personalizadas
As ComputeClasses personalizadas do GKE permitem definir listas priorizadas de séries de máquinas do Compute Engine para os nós do WorkerPool e usar automaticamente séries de máquinas secundárias se uma zona tiver indisponibilidade de recursos.
Selecionar a série de máquinas do Compute Engine por ambiente de execução
Configure uma ComputeClass separada para cada ambiente de execução de sandbox:
- Ambiente de execução de MicroVM (Cloud Hypervisor): defina o campo
enableNestedVirtualization: truenas prioridades do ComputeClass e segmente as séries de máquinas do Compute Engine x86 que oferecem suporte à virtualização aninhada (como N4, C3, C4 ou N2) ou use tipos de máquina bare metal x86, que executam o KVM de forma nativa e não exigem o campoenableNestedVirtualization. As VMs baseadas em Arm e as séries de máquinas listadas em Restrições de virtualização aninhada não são compatíveis. - Ambiente de execução do gVisor: use como destino séries de máquinas do Compute Engine x86 de uso geral ou otimizadas para computação (como N4, C3, C4 ou N2) sem a virtualização aninhada ativada. As séries de máquinas que são executadas em microarquiteturas de CPU mistas (como E2) e VMs baseadas em Arm não são compatíveis com o Agent Substrate no GKE. Todos os recursos WorkerPool selecionados por um ActorTemplate precisam compartilhar a mesma arquitetura de CPU.
Para uma comparação detalhada, consulte Selecionar um ambiente de execução de sandbox.
Regras de ComputeClass necessárias para o Agent Substrate
Ao criar uma ComputeClass para o Agent Substrate em nós de trabalho do GKE, siga estas regras:
- Use ComputeClasses baseadas em nós: não use o faturamento baseado em pods (o
campo
podFamily), que não é compatível com a virtualização aninhada. - Não defina o campo
nodePoolConfig.sandbox.type: microvm: essa configuração ativa o ambiente de execução do Kata para o GKE Sandbox em cargas de trabalho baseadas em pods e aplica um taintsandbox.gke.io/runtime=microvmque impede que o Agent Substrate nos workers do GKE programe. O Agent Substrate no GKE gerencia o próprio ambiente de execução de microVM e requer apenas a virtualização aninhada do Compute Engine em nós padrão do Container-Optimized OS (tipo de imagemcos_containerd). Defina as configurações do kernel do Linux
sysctlpara alta densidade de sandbox: se um nó de trabalho executar mais de aproximadamente 800 sandboxes simultâneos, será necessário aumentar os limites do kernel do Linux para monitoramento do sistema de arquivos (parâmetrosfs.inotify.*) e para a tabela de vizinhos do protocolo de resolução de endereço (ARP, na sigla em inglês) (parâmetrosnet.ipv4.neigh.default.gc_thresh*). O instalador aplica essas configurações apenas aos clusters que ele cria. Ao configurar ComputeClasses personalizadas (usando o campopriorityDefaults.nodeSystemConfig.linuxNodeConfig.sysctls) ou pré-criar pools de nós de trabalho (usando a flag--system-config-from-file), aplique os seguintes valores desysctl:fs.inotify.max_user_instances:65536fs.inotify.max_user_watches:1048576net.ipv4.neigh.default.gc_thresh1:4096net.ipv4.neigh.default.gc_thresh2:16384net.ipv4.neigh.default.gc_thresh3:32768
Para mais informações sobre como configurar os parâmetros
sysctldo nó, consulte Opções de configuração do Sysctl.
Escolher um padrão de escalonamento vertical para recursos do WorkerPool de microVMs
Os pods de worker da MicroVM solicitam o recurso estendido ate.dev/kvm: 1, que é
anunciado pelo plug-in de dispositivo atelet somente depois que um nó é inicializado e o
agente atelet é iniciado. Como o provisionamento automático de nós do GKE não
vê o recurso estendido ate.dev/kvm em modelos de nós não provisionados, um
pod de worker de microVM pendente não pode acionar o GKE para criar automaticamente um novo
pool de nós a partir de zero réplicas por conta própria. No entanto, se um pool de nós já tiver pelo menos um nó em execução, o GKE poderá escaloná-lo verticalmente.
A tabela a seguir compara os padrões compatíveis para escalonamento de recursos do WorkerPool de microVM no GKE:
| Padrão | Como funciona | Escalona para 0 nós? | Fallback de várias prioridades para indisponibilidade de recursos? | Ideal quando |
|---|---|---|---|---|
Pools criados automaticamente com o campo minimumCapacity
|
Define os campos nodePoolAutoCreation.enabled: true e
minimumCapacity.targetNodeCount: 1 com prioridades
machineType explícitas.
|
Não (mantém um nó de espera em execução) |
Somente no provisionamento inicial para o campo minimumCapacity
no nível da classe. O substituto de intermitência média exige a definição
do campo minimumCapacity.targetNodeCount: 1 em cada
entrada de substituto no campo spec.priorities[] (mantendo um
nó de espera por prioridade)
|
Você quer a criação automatizada de pool de nós e sempre manter pelo menos um nó de trabalho em execução. |
| Pools criados automaticamente com buffers de capacidade |
Combina o campo nodePoolAutoCreation.enabled: true com
um CapacityBuffer ativo ou em espera cujo PodTemplate omite o
recurso estendido ate.dev/kvm.
|
Suspende para o modo de espera (por exemplo, aproximadamente 8% do custo de computação em execução em um nó c3-standard-4 com um disco de inicialização padrão de 100 GiB)
|
Sim (os marcadores de posição de buffer acionam o substituto do provisionamento automático de nós em todas as prioridades) | Você quer um escalonamento rápido de burst (1 a 4 segundos ativo ou 20 a 35 segundos para retomar os nós em espera e 50 a 85 segundos até que os novos workers estejam prontos) com baixo custo de inatividade. |
| Pools de 0 nós pré-criados com rótulos de modelo de nó |
Pré-cria pools de nós com escalonamento automático de 0 nós com o rótulo clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 e os referencia no campo spec.priorities[].nodepools da ComputeClass.
|
Sim (0 nós verdadeiros, sem custo de computação ociosa) | Sim, nos pools de nós pré-criados | Você quer uma redução da escala a zero real sem manter buffers de capacidade em espera. |
Exemplo: ComputeClass com o campo minimumCapacity
Ao usar o campo minimumCapacity, cada entrada no campo spec.priorities
precisa especificar um campo machineType explícito, em vez de especificar apenas
o campo machineFamily:
apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
name: substrate-microvm
spec:
priorityDefaults:
enableNestedVirtualization: true
nodeSystemConfig:
linuxNodeConfig:
sysctls:
fs.inotify.max_user_instances: 65536
fs.inotify.max_user_watches: 1048576
net.ipv4.neigh.default.gc_thresh1: 4096
net.ipv4.neigh.default.gc_thresh2: 16384
net.ipv4.neigh.default.gc_thresh3: 32768
priorities:
- machineType: n4-standard-4
- machineType: c3-standard-4
- machineType: n2-standard-4
nodePoolAutoCreation:
enabled: true
minimumCapacity:
targetNodeCount: 1
nodePoolConfig:
imageType: cos_containerd
whenUnsatisfiable: DoNotScaleUp
Para segmentar um WorkerPool para essa ComputeClass, adicione o campo nodeSelector:
{cloud.google.com/compute-class: substrate-microvm} ao modelo de pod do WorkerPool.
Quando uma ComputeClass faz fallback em diferentes séries de máquinas x86 (como de
N4 para C3 ou N2), a restauração de um snapshot durável com fidelidade de memória (o
modo SNAPSHOT_FIDELITY_MEMORY) requer um worker com recursos de CPU que sejam um
superconjunto dos recursos de CPU do snapshot. Se nenhum Worker compatível tiver capacidade,
o Agent Substrate vai fazer o downgrade da restauração para a fidelidade do sistema de arquivos raiz (o modo SNAPSHOT_FIDELITY_ROOTFS), que preserva o sistema de arquivos raiz
e os dados de volume duráveis ao reiniciar os processos do Actor.
Exemplo: escalonar a partir de zero com pools de nós zero pré-criados
Salve as configurações de
sysctldo kernel do Linux de alta densidade como um arquivosystem-config.yaml:linuxConfig: sysctl: fs.inotify.max_user_instances: '65536' fs.inotify.max_user_watches: '1048576' net.ipv4.neigh.default.gc_thresh1: '4096' net.ipv4.neigh.default.gc_thresh2: '16384' net.ipv4.neigh.default.gc_thresh3: '32768'Crie previamente os pools de nós de virtualização aninhada primários e de fallback em 0 nó com a flag
--system-config-from-file=system-config.yamle o rótuloclusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096para que o escalonador automático de cluster do GKE saiba que o pool vazio fornece o recurso estendidoate.dev/kvm:# Primary N4 pool (0 nodes) gcloud container node-pools create microvm-n4-pool \ --cluster=CLUSTER_NAME \ --location=LOCATION \ --machine-type=n4-standard-4 \ --enable-nested-virtualization \ --system-config-from-file=system-config.yaml \ --num-nodes=0 \ --enable-autoscaling --total-min-nodes=0 --total-max-nodes=10 \ --node-labels=cloud.google.com/compute-class=substrate-microvm-zero,clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 \ --node-taints=cloud.google.com/compute-class=substrate-microvm-zero:NoSchedule # Fallback C3 pool (0 nodes) gcloud container node-pools create microvm-c3-pool \ --cluster=CLUSTER_NAME \ --location=LOCATION \ --machine-type=c3-standard-4 \ --enable-nested-virtualization \ --system-config-from-file=system-config.yaml \ --num-nodes=0 \ --enable-autoscaling --total-min-nodes=0 --total-max-nodes=10 \ --node-labels=cloud.google.com/compute-class=substrate-microvm-zero,clusterautoscaler-nodetemplate-resources.ate.dev/kvm=4096 \ --node-taints=cloud.google.com/compute-class=substrate-microvm-zero:NoScheduleSubstitua:
CLUSTER_NAME: o nome do cluster do GKE Standard.LOCATION: a zona ou a região do Compute Engine do cluster. O uso das sinalizações--total-min-nodese--total-max-nodesdefine os limites de escalonamento automático em todo o pool de nós, em vez de por zona.
Faça referência aos pools pré-criados em ordem de prioridade na sua ComputeClass:
apiVersion: cloud.google.com/v1 kind: ComputeClass metadata: name: substrate-microvm-zero spec: nodePoolAutoCreation: enabled: false priorities: - nodepools: - microvm-n4-pool - nodepools: - microvm-c3-pool whenUnsatisfiable: DoNotScaleUpO campo
priorityDefaultsnão se aplica a prioridades que usam o camponodepools, porque as configurações de nó vêm dos pools de nós pré-criados. Assim como nas prioridades de fallback criadas automaticamente, retomar um ator em uma série de máquinas de fallback com recursos de CPU que não são um superconjunto dos recursos de CPU do snapshot faz o downgrade da restauração para o modoSNAPSHOT_FIDELITY_ROOTFSe reinicia os processos do ator.
Para mais informações sobre a configuração da ComputeClass, consulte Controlar atributos de nós escalonados automaticamente com ComputeClasses personalizadas.
Configurar buffers de capacidade para o escalonamento de burst do WorkerPool
Quando um pico de tráfego de atores excede a capacidade dos pods do WorkerPool
em execução, os novos pods do Worker precisam aguardar o provisionamento de nós do Compute Engine,
a inicialização do agente atelet e o pré-aquecimento de recursos do sandbox antes de
atender aos atores. Os buffers de capacidade do GKE removem o provisionamento de nós e o pré-aquecimento de recursos do atelet do caminho crítico:
- Buffers de capacidade ativos (estratégia
buffer.x-k8s.io/active-capacity): mantêm os nós pré-provisionados em execução e prontos para que novos pods de worker sejam programados em um a quatro segundos, pelo custo total de execução da VM do Compute Engine. - Buffers de capacidade em espera (estratégia
buffer.gke.io/standby-capacity): provisione nós e permita que o agenteateletinicialize e pré-aqueça os recursos do sandbox (o bináriorunscou as imagens do Cloud Hypervisor e do Kata) no disco durante a janela de inicialização em espera antes que o GKE suspenda as VMs do Compute Engine. Essa janela tem como padrão cinco minutos (5m) e é configurada pela anotaçãobuffer.gke.io/standby-capacity-init-timeno CapacityBuffer. Aumente o valor dessa anotação se o pré-aquecimento de recursos levar mais de cinco minutos. Quando ocorre uma intermitência, o GKE retoma os nós suspensos em aproximadamente 20 a 35 segundos, e a prontidão de ponta a ponta do WorkerPool (programação de pods de worker, emissão de certificados de pod e registro de capacidade com o componenteate-api-server) é concluída em aproximadamente 50 a 85 segundos. Enquanto suspensa, você paga apenas pela memória da VM suspensa e pelo armazenamento do disco de inicialização. Por exemplo, o armazenamento suspenso custa aproximadamente 8% do custo de computação em execução em um nóc3-standard-4com um disco de inicializaçãohyperdisk-balancedpadrão de 100 GiB. A porcentagem exata varia de acordo com o formato da máquina, o tamanho do disco de inicialização e as IOPS ou a capacidade de processamento provisionadas.
Para mais informações sobre estratégias de buffer, consulte Estratégias para reduzir a latência de inicialização.
Limitações e regras para buffers de capacidade
Ao configurar buffers de capacidade para o Agent Substrate no GKE, aplique as seguintes regras:
- Restrições de formato de máquina do Compute Engine para buffers de espera:
a suspensão de instâncias do Compute Engine não é compatível com VMs com
SSDs locais anexados ou em formatos de máquina com mais de 208 GB de
memória (como o tipo de máquina
c3-highmem-88ou formatos bare metal). Para formas de nós de trabalho grandes ou nós com SSDs locais, use buffers de capacidade ativos em vez de buffers de espera. - Evite apontar o campo
scalableRefpara um WorkerPool de 0 réplica ou uma implantação de microVM:- O controlador CapacityBuffer do GKE não pode resolver um
recurso personalizado (
kind: WorkerPool) quando o pool é escalonado para 0 réplicas. - Para recursos WorkerPool de microVM, também não aponte o campo
scalableRefpara a implantação subjacente, porque o modelo de pod de implantação inclui o recurso estendidoate.dev/kvm: 1(que impede que o provisionamento automático de nós escalone horizontalmente um pool vazio). Em vez disso, configure buffers referenciando um PodTemplate (no campopodTemplateRef) que selecione a ComputeClass sem solicitar o recurso estendidoate.dev/kvm. - Para recursos do WorkerPool do gVisor (que não solicitam o recurso estendido
ate.dev/kvm), é possível apontar o camposcalableRefdiretamente para a implantação subjacente do WorkerPool ou usar um PodTemplate.
- O controlador CapacityBuffer do GKE não pode resolver um
recurso personalizado (
Exemplo: CapacityBuffer em espera usando um PodTemplate
O manifesto a seguir define um PodTemplate e um CapacityBuffer em espera que funcionam para recursos de microVM ou gVisor WorkerPool:
apiVersion: v1
kind: PodTemplate
metadata:
name: substrate-worker-buffer-template
namespace: WORKERPOOL_NAMESPACE
template:
spec:
nodeSelector:
cloud.google.com/compute-class: COMPUTE_CLASS_NAME
containers:
- name: buffer-placeholder
image: registry.k8s.io/pause:3.9
resources:
requests:
cpu: "WORKER_CPU_REQUEST"
memory: "WORKER_MEMORY_REQUEST"
---
apiVersion: autoscaling.x-k8s.io/v1beta1
kind: CapacityBuffer
metadata:
name: substrate-standby-buffer
namespace: WORKERPOOL_NAMESPACE
spec:
podTemplateRef:
name: substrate-worker-buffer-template
replicas: BUFFER_REPLICAS
provisioningStrategy: buffer.gke.io/standby-capacity
Substitua:
WORKERPOOL_NAMESPACE: o namespace do Kubernetes do WorkerPool (por exemplo,my-workerpool).COMPUTE_CLASS_NAME: o nome da ComputeClass personalizada visada pelo WorkerPool (por exemplo,substrate-microvm).WORKER_CPU_REQUESTeWORKER_MEMORY_REQUEST: as solicitações de CPU e memória de um único pod de worker no WorkerPool (por exemplo,2CPUs e4Gide memória em um nó de 4 vCPUs), deixando a capacidade do nó para o agenteatelete os daemons do sistema do GKE. A correspondência desses valores com as solicitações de um pod de worker ajuda a garantir que cada réplica de buffer provisione um nó de trabalho em espera, em vez de empacotar vários marcadores de buffer em um único nó.BUFFER_REPLICAS: o número de nós de trabalho em espera a serem mantidos pré-aquecidos (por exemplo, nós4).
Ao usar buffers de capacidade de espera, adicione uma tolerância para o taint buffer.gke.io/standby-capacity-node-suspended (com o campo operator:
"Exists") ao DaemonSet atelet para que os pods atelet de substituição possam permanecer programados em nós de espera suspensos (por exemplo, durante uma atualização gradual do DaemonSet). Para ver um exemplo de configuração do DaemonSet, consulte Pré-carregar imagens em buffers de espera.
Se várias cargas de trabalho compartilharem a mesma ComputeClass, adicione tolerâncias de separação de carga de trabalho correspondentes e rótulos nodeSelector ao modelo de pod do WorkerPool e ao PodTemplate do buffer para que o GKE provisione nós com taints dedicados que outras cargas de trabalho não reivindicam. Adicione também uma
tolerância correspondente ao DaemonSet atelet para que o agente atelet possa
programar nesses nós dedicados. Para instruções detalhadas, consulte Configurar
buffers de capacidade.
Gerenciar upgrades e interações do escalonador automático
Nesta seção, descrevemos como gerenciar atualizações do DaemonSet atelet, eventos de redução de escala vertical do escalonador automático de cluster e upgrades de nós sem interromper os atores ativos.
Atualizar o DaemonSet atelet com buffers de espera
Os nós de buffer em espera suspensos carregam o taint buffer.gke.io/standby-capacity-node-suspended e um taint inacessível enquanto suspensos. Portanto, o agente kubelet em um nó suspenso não pode confirmar as exclusões de pods. Verifique se o DaemonSet atelet tolera o
taint buffer.gke.io/standby-capacity-node-suspended (com o campo operator:
"Exists"). Mesmo com essa tolerância, durante uma atualização gradual padrão do
DaemonSet atelet (com o campo maxUnavailable: 1), os pods em nós suspensos
entram no estado Terminating e podem impedir que a atualização avance nos
nós em execução.
Antes de atualizar o DaemonSet atelet em um cluster com nós de espera suspensos, faça o seguinte:
- Para que os nós de espera inacessíveis não esgotem o orçamento de atualização, defina o
campo
spec.updateStrategy.rollingUpdate.maxUnavailableno DaemonSetateletcomo um valor maior que o número máximo de nós de espera suspensos. Antes de atualizar o DaemonSet
atelet, escalone temporariamente as réplicas de CapacityBuffer em espera para0e aguarde até que o escalonador automático de cluster remova todos os nós de buffer em espera suspensos (normalmente de 10 a 15 minutos). Para verificar se algum nó ainda informa um status de condiçãoSuspendeddeTrue, execute o seguinte comando:kubectl get nodes -o custom-columns='NAME:.metadata.name,SUSPENDED:.status.conditions[?(@.type=="Suspended")].status'
Proteger atores ativos durante a redução de escala vertical e os upgrades
Como os atores ativos são executados em sandboxes gerenciados pelo agente atelet,
em vez de pods individuais do Kubernetes, as solicitações de CPU e memória de um nó
podem parecer baixas para o escalonador automático de cluster do GKE, mesmo quando um
pod de worker nesse nó está hospedando atores ativos. Quando um nó é drenado, o agente kubelet envia um sinal SIGTERM para o pod do worker, e o worker encaminha o sinal SIGTERM para o processo principal de cada contêiner de cada ator que ele hospeda. Cada ator ativo tem até 30 minutos para ser suspenso
antes que o worker seja interrompido. Dê a cada ator com estado um gerenciador SIGTERM que
não saia no sinal e que chame o método SuspendActor com o
modo DURABILITY_MODE_SYNCHRONOUS. Um ator cujo processo principal é encerrado no
sinal SIGTERM perde o estado não salvo imediatamente. Se o pod de worker parar enquanto
ainda estiver hospedando um ator ativo, o ator vai entrar no estado
ACTOR_STATE_CRASHED.
Para minimizar as interrupções durante eventos de redução de escala vertical e upgrades de cluster do GKE, aplique as seguintes práticas:
- Evite usar VMs spot para nós de WorkerPool com estado, porque a preempção de VM spot fornece apenas de 15 segundos a 2 minutos de aviso de encerramento antes de interromper o nó.
- Coordene o esvaziamento no seu orquestrador para que os atores ativos sejam verificados
e suspensos antes que os pods de worker sejam interrompidos ou impeça que o escalonador automático de clusters
remova os pods de worker ativos (por exemplo, usando a
anotação de pod
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"). Se você definir a anotaçãosafe-to-evict: "false"de forma estática no modelo de pod do WorkerPool, o escalonador automático de clusters não vai reduzir a escala vertical de um nó enquanto um pod de worker estiver programado nele, mesmo quando esse worker hospedar zero atores ativos. Para liberar nós inativos, reduza a escala vertical das réplicas do WorkerPool ou gerencie a anotação dinamicamente. Para mais informações sobre o ciclo de vida de remoção de workers e a recuperação de atores que falharam com o métodoRevertActor, consulte Remoção no guia da API Agent Substrate. - Configure os upgrades súbitos do GKE e revise o Upgrade em um ambiente com restrição de recursos para que novos nós de trabalho sejam provisionados antes que os nós de trabalho atuais sejam isolados e drenados.
A seguir
- Saiba como escolher o modelo de orquestração, o ambiente de execução do sandbox, os controles de isolamento e as opções de armazenamento certos em Planejar uma arquitetura para cargas de trabalho de agentes de IA no GKE.
- Saiba mais sobre as ComputeClasses personalizadas do GKE e os buffers de capacidade do GKE.
- Confira mais recursos no repositório do Agent Substrate no GitHub.