Entenda como fazer a manutenção do host no GKE

Durante o ciclo de vida de um cluster do GKE de longa duração, as interrupções periódicas nas cargas de trabalho ocorrem devido a interrupções de infraestrutura que Cloud de Confiance by S3NS emite. Esses eventos automáticos podem ocorrer para responder a decisões de programação (eventos de preempção) ou atualizações de nós, que incluem upgrades automáticos de nós do GKE (eventos de manutenção) ou correção de problemas detectados (eventos de encerramento).

Este documento ajuda você a entender o que significa interrupção de nós no GKE e a minimizar o impacto da interrupção nos nós do GKE.

Para detalhes sobre como monitorar notificações e eventos de manutenção, consulte Monitorar eventos de manutenção.

Este documento se aplica aos seguintes tipos de máquina:

Este documento é destinado a administradores e operadores de plataforma que gerenciam o ciclo de vida da infraestrutura técnica subjacente. Para saber mais sobre papéis comuns e tarefas de exemplo referenciados no Cloud de Confiance by S3NS conteúdo, consulte Funções e tarefas comuns do usuário do GKE.

O que significa interrupção de infraestrutura no GKE?

Seus clusters do GKE gerenciam o ciclo de vida dos nós do GKE. Esses nós são provisionados em VMs do Compute Engine, que passam periodicamente pelas seguintes interrupções:

  • Correção de problemas detectados (TerminationEvent): esses eventos ocorrem porque Cloud de Confiance by S3NS detecta um problema e interrompe a infraestrutura do cluster. Os eventos TerminationEvent não oferecem suporte ao encerramento normal. Os eventos TerminationEvent são acionados pelos seguintes problemas:

    • O reparo automático ocorre quando o GKE repara um nó após repetidas verificações de integridade com falha.
    • HostError ocorre quando um erro de hardware ou software na máquina física faz com que a VM pare.
  • Eventos de manutenção ou upgrade (MaintenanceEvent): esses eventos ocorrem quando Cloud de Confiance by S3NS precisa interromper uma VM para realizar a manutenção. Esses eventos são acionados pelas seguintes tarefas de manutenção:

    Para mais informações sobre como você e o GKE gerenciam mudanças durante o ciclo de vida de um cluster, consulte Tipos de mudanças.

  • Resposta a decisões de programação (PreemptionEvent): esses eventos ocorrem quando Cloud de Confiance by S3NS precisa preemptar VMs para disponibilizar capacidade para recursos de maior prioridade. Os eventos PreemptionEvent podem ser qualquer um dos seguintes:

    • Remoção: ocorre quando a infraestrutura preemptiva ou do Spot é preemptada para acomodar uma VM de maior prioridade.
    • Desfragmentação:ocorre quando o GKE preempta uma fração de TPU menor para acomodar uma fração de TPU maior. A desfragmentação ocorre apenas em frações de TPU.

Durante o ciclo de vida de um cluster do GKE de longa duração, os nós podem sofrer interrupções periódicas nas cargas de trabalho. Quando essas interrupções afetam os nós do GKE que executam suas cargas de trabalho, o GKE precisa reiniciar as cargas de trabalho em execução e o nó subjacente.

Por que os nós que não oferecem suporte à migração em tempo real exigem gerenciamento de interrupção

Com algumas exceções, a maioria das VMs do Compute Engine tem a política de manutenção do host definida como migração em tempo real, o que significa que as cargas de trabalho em execução geralmente sofrem pouca ou nenhuma interrupção. No entanto, algumas classes de VMs não oferecem suporte à migração em tempo real, incluindo VMs com GPUs e TPUs anexadas, tipos de máquina Z3 com mais de 18 TiB de SSD, tipos de máquina H4D e o tipo dec4a-highmem-96-metal máquina. Por exemplo, quando um evento de host acontece na VM em uma fração de TPU, toda a fração é interrompida e reprogramada porque todos os eventos de manutenção são coordenados no nível da fração. Portanto, se você criar uma fração de TPU com centenas de VMs, todas elas vão receber a mesma programação de eventos de manutenção.

Quando um evento de host ocorre, o GKE encerra o nó e os pods dele. Se os pods forem implantados como parte de uma carga de trabalho maior, como um job ou implantação, o GKE reinicia os pods no nó afetado.

Gerenciar eventos de manutenção

O restante deste documento descreve como gerenciar interrupções de MaintenanceEvent.

O gerenciamento de interrupções de nós durante eventos de manutenção do host segue um fluxo de trabalho de três estágios:

  1. Detectar a manutenção programada do host: use rótulos de nós do GKE, endpoints de metadados ou registros.
  2. Agir na manutenção detectada: se a manutenção estiver programada, avalie sua infraestrutura e cargas de trabalho e determine a melhor ação para seu caso de uso. Tome a ação apropriada, como permitir que o sistema processe o evento de manutenção automaticamente, iniciar manualmente a manutenção do host ou orquestrar estratégias de manutenção.
  3. Verificar o resultado do evento de manutenção: verifique se o evento de manutenção foi iniciado corretamente, quando o Compute Engine inicia o evento de manutenção na programação ou quando você o inicia manualmente.

Detectar a manutenção programada do host

Para monitorar e detectar eventos de manutenção futuros, é necessário visualizar as notificações do GKE e do Compute Engine.

Para detalhes sobre como monitorar notificações e eventos de manutenção, consulte Monitorar eventos de manutenção.

Agir na manutenção detectada

Se você receber uma notificação de manutenção programada para um ou mais nós no cluster, use a árvore de decisão a seguir para determinar a melhor maneira de lidar com a interrupção:

  1. Manutenção automática:permita que o Compute Engine inicie o evento de manutenção na programação. Suas VMs serão migradas automaticamente em tempo real em segundo plano com interrupção mínima ou nenhuma.

    1. Se a VM do host oferecer suporte à migração em tempo real, recomendamos que você permita que o evento de manutenção ocorra automaticamente.
    2. Se as cargas de trabalho forem executadas em nós flexíveis inativos, você poderá otimizar o tempo de manutenção automaticamente configurando a manutenção oportunista. Isso aciona as atualizações necessárias apenas durante períodos de tempo ocioso natural.
  2. Iniciar manualmente um evento de manutenção do host:avalie as seguintes perguntas para determinar a melhor maneira de lidar manualmente com a interrupção:

    1. Os nós afetados são VMs únicas ou isoladas?

      • Sim (estou executando uma VM única ou isolada):
        • Se você não precisar de controles de tempo precisos, permita que o Compute Engine inicie o evento de manutenção na programação (automático padrão).
        • Se você precisar evitar a preempção inesperada, inicie manualmente o evento de manutenção do host no nó individual em um horário conveniente, por exemplo, durante janelas de tráfego menores.
      • Não (estou executando um pool de nós de aceleradores): escolha uma das opções na próxima etapa.
    2. Escolha uma das seguintes opções com base no seu caso de uso:

      • Se o pool de aceleradores executar tarefas de treinamento de IA/ML acopladas: implemente a estratégia paralela. Salve o estado de treinamento em um checkpoint, desligue o pool normalmente e execute atualizações de host e upgrades de cluster do GKE simultaneamente antes de reiniciar.

      • Se o pool de aceleradores executar endpoints de veiculação de IA/ML de alta disponibilidade ou inferência: implemente a estratégia de rolling. Coordene a manutenção programada do host e os upgrades de versão em lotes de rolling dentro dos limites da zona ou do pool, usando réplicas ativas para proteger os SLAs.

Iniciar manualmente um evento de manutenção do host em VMs únicas ou isoladas

É possível iniciar manualmente a manutenção reprogramável quando ela se adequar à sua programação, como durante períodos de baixa atividade. Para fazer isso, aplique o rótulo cloud.google.com/perform-maintenance=true se as seguintes condições forem atendidas:

  • O Compute Engine emite uma notificação sobre um evento de manutenção programado.
  • O evento de manutenção subjacente do Compute Engine é reprogramável. Para verificar se o evento é reprogramável, procure a notificação can_reschedule=TRUEnos metadados do evento. Se o evento não for reprogramável, definir o rótulo cloud.google.com/perform-maintenance=true não terá efeito, e a manutenção ocorrerá no horário programado originalmente.

Se as condições anteriores forem atendidas, em um nó no pool de nós, defina o rótulo do nó cloud.google.com/perform-maintenance como true. Exemplo:

kubectl label nodes <node-name> cloud.google.com/perform-maintenance=true

Se você iniciar um evento de manutenção, o GKE executará as seguintes operações:

  1. Contamina o nó.
  2. Remove os pods normalmente.
  3. Solicita que o Compute Engine inicie o evento de manutenção imediatamente, em vez de aguardar o horário programado.

Verificar o resultado do evento de manutenção

Depois de detectar um evento de manutenção futuro e decidir o melhor curso de ação, você poderá verificar o resultado do evento de manutenção.

O Compute Engine inicia o evento de manutenção na programação

Quando o evento de manutenção é iniciado, um nó pode ser desligado uma ou mais vezes com um curto período de notificação antes do encerramento iminente. Nesses casos, o GKE faz o possível para encerrar as cargas de trabalho e remover os pods normalmente.

A manutenção programada é iniciada

Quando a manutenção programada é iniciada, o Compute Engine atualiza os metadados no diretório http://metadata.google.internal/computeMetadata/v1/instance/attributes/. O Compute Engine atualiza os rótulos de metadados da seguinte maneira:

  • Define maintenance-event como TERMINATE_ON_HOST_MAINTENANCE.
  • Em upcoming-maintenance, define maintenance_status como ONGOING.

O GKE detecta e processa o evento de manutenção programada do host, seja acionado manualmente ou automaticamente.

A seguinte métrica do sistema do GKE informa a contagem de interrupções de um nó do GKE desde a última amostra (a métrica é amostrada a cada 60 segundos):

  • kubernetes.io/node/interruption_count

Os campos interruption_type (como TerminationEvent, MaintenanceEvent ou PreemptionEvent) e interruption_reason (como HostError, Eviction ou AutoRepair) podem ajudar a fornecer o motivo pelo qual um nó foi interrompido.

Para receber um detalhamento das interrupções e das causas delas nos nós de TPU nos clusters do seu projeto, use a seguinte consulta do PromQL:

  sum by (interruption_type,interruption_reason)(
    sum_over_time(
      kubernetes_io:node_interruption_count{monitored_resource="k8s_node"}[${__interval}]))

Para ver apenas os eventos de manutenção do host, atualize a consulta para filtrar o valor HW/SW Maintenance para interruption_reason. Use a seguinte consulta do PromQL:

  sum by (interruption_type,interruption_reason)(
    sum_over_time(
      kubernetes_io:node_interruption_count{monitored_resource="k8s_node", interruption_reason="HW/SW Maintenance"}[${__interval}]))

Para ver a contagem de interrupções agregada por pool de nós, use a seguinte consulta do PromQL:

  sum by (node_pool_name,interruption_type,interruption_reason)(
    sum_over_time(
      kubernetes_io:node_pool_interruption_count{monitored_resource="k8s_node_pool", interruption_reason="HW/SW Maintenance", node_pool_name=NODE_POOL_NAME }[${__interval}]))

Configurações avançadas para minimizar a interrupção

Esta seção descreve outras ferramentas para configurar o cluster e as cargas de trabalho para minimizar a interrupção.

Ativar o tratamento de interrupções

apiVersion: v1
kind: ConfigMap
metadata:
  name: gke-disruption-handling
  namespace: kube-system
data:
  maintenance-experience.yaml: |
    gracefulTermination: true

Para ativar o tratamento de interrupções, crie um arquivo chamado maintenance-config.yaml com esse ConfigMap. Aplique o ConfigMap ao cluster com o seguinte comando:

kubectl apply -f my-configmap.yaml

Configure o GKE para encerrar as cargas de trabalho normalmente

Nesta seção, você configura o GKE para gerenciar o ciclo de vida do seu aplicativo e minimizar a interrupção da carga de trabalho. Se você não configurar uma período de carência, o período de carência é de 30 segundos por padrão.

O GKE se esforça para encerrar esses pods da melhor maneira possível e executar a ação de encerramento definida por você, por exemplo, salvando um estado de treinamento. O GKE envia um sinal SIGTERM para os pods no início do período de carência. Se os pods não forem encerrados até o final do período de carência, o GKE envia um sinal SIGKILL de acompanhamento para os processos que ainda estão em execução contêiner no pod.

Para configurar o período de encerramento normal, defina o período de carência de encerramento (segundos) no campo spec.terminationGracePeriodSeconds do manifesto do pod. Por exemplo, para receber um tempo de notificação de 10 minutos, defina o campo spec.terminationGracePeriodSeconds no manifesto do pod como 600 segundos da seguinte maneira:

    spec:
      terminationGracePeriodSeconds: 600

Recomendamos que você defina um período de carência de rescisão longo o suficiente para que todas as tarefas em andamento sejam concluídas dentro do período de notificação. Se a carga de trabalho usar um framework de ML, como MaxText, Pax ou JAX com Orbax, as cargas de trabalho vão poder capturar o sinal SIGTERM e iniciar um processo de checkpoint. Para saber mais, consulte Checkpoint automático da TPU.

Processo de encerramento sem dificuldades

Quando um evento de manutenção iniciado manualmente começa, o Compute Engine sinaliza o encerramento iminente da máquina atualizando a chave de metadados maintenance-event. O GKE inicia o encerramento normal.

O fluxo de trabalho a seguir mostra como o GKE executa o encerramento normal do nó quando há um encerramento de nó iminente:

  1. Em 60 segundos, ocorre o seguinte:
    1. Os componentes do sistema aplicam o rótulo de nó cloud.google.com/active-node-maintenance definido como ONGOING para indicar que as cargas de trabalho estão sendo interrompidas.
    2. O GKE aplica o taint do nó para evitar que novos pods sejam programados no nó. O taint tem a chave cloud.google.com/impending-node-termination:NoSchedule. Recomendamos que você não modifique as cargas de trabalho para tolerar esse taint devido ao encerramento conhecido que ocorre.
  2. O componente de tratamento de manutenção começa a remover pods, primeiro removendo os pods de carga de trabalho e, em seguida, os pods do sistema (por exemplo, kube-system).
  3. O GKE envia um sinal de encerramento SIGTERM para os pods de carga de trabalho em execução no nó para alertá-los sobre um encerramento iminente. Os pods podem usar esse alerta para concluir quaisquer tarefas em andamento. O GKE faz o possível para encerrar esses pods normalmente.
  4. Depois que a remoção é concluída, o GKE atualiza o valor do rótulo cloud.google.com/active-node-maintenance para terminating para indicar que o nó está pronto para ser encerrado.

Em seguida, o nó é encerrado e um substituto é alocado. O GKE limpa os rótulos e as contaminações quando o processo é concluído. Para aumentar a janela de encerramento para suas cargas de trabalho usando GPUs ou TPUs, conclua as etapas na seção Iniciar manualmente um evento de manutenção do host.

Verificar o progresso de uma finalização suave ativa

É possível filtrar os registros do GKE pelos seguintes eventos de encerramento normal:

  • Quando a VM detecta uma interrupção devido a um encerramento de nó iminente, como o evento de manutenção do host do Compute Engine, o GKE define cloud.google.com/active-node-maintenance como ONGOING quando as cargas de trabalho estão sendo interrompidas e como terminating quando as cargas de trabalho são concluídas e o nó está pronto para ser encerrado.
  • Ao restringir a programação de novas cargas de trabalho, o GKE aplica o taint cloud.google.com/impending-node-termination:NoSchedule.

Minimizar a interrupção de cargas de trabalho em execução com manutenção oportunista

É possível minimizar a interrupção de cargas de trabalho em execução acionando automaticamente a manutenção quando o GKE detecta que os nós com GPUs ou TPUs estão inativos. Para ativar esse recurso, crie um novo pool de nós. Não é possível ativar a manutenção oportunista em um pool de nós atual.

Criar um novo pool de nós com manutenção oportunista

O comando a seguir demonstra como criar um pool de nós com a manutenção oportunista ativada:

gcloud beta container node-pools create NODE_POOL_NAME \
    --cluster CLUSTER_NAME \
    --accelerator ACCELERATOR_ARG \
    --machine-type MACHINE_TYPE \
    --num-nodes NODE_COUNT \
    --zone ZONE \
    --project=PROJECT_ID \
    --opportunistic-maintenance=node-idle-time=NODE_IDLE_TIME,min-nodes=MIN_NODES,window=WINDOW

Substitua os seguintes valores:

  • NODE_POOL_NAME: o nome do pool de nós do GKE.
  • CLUSTER_NAME : o nome do cluster do GKE.
  • NODE_IDLE_TIME : o período em que um nó pode permanecer inativo (ou seja, nenhuma carga de trabalho que consome acelerador está em execução) antes que a manutenção seja acionada. O valor representa a duração em segundos, com até nove dígitos fracionários, e termina com o s caractere, por exemplo: 80000s.
  • MIN_NODES : o número mínimo de nós que precisam estar disponíveis em um pool de nós. Essa opção bloqueia a manutenção se ela fizer com que o número de nós em execução fique abaixo desse valor, por exemplo: 10.
  • WINDOW : a janela de tempo, em segundos, em que a manutenção oportunista pode ser executada. O valor termina com um caractere s. Por exemplo, um valor de 14 dias ou 1209600s implica que a manutenção oportunista só pode ser executada nas duas semanas anteriores à data de manutenção programada. Um valor de 28 dias ou 2419200s permite que a manutenção oportunista seja executada a qualquer momento durante a janela de manutenção programada. Essa janela para manutenção do host do Compute Engine é diferente das janelas de manutenção do GKE, que determinam quando a manutenção do cluster do GKE pode ocorrer e são configuradas separadamente.

Exemplo de configuração para manutenção oportunista

Veja o exemplo a seguir. Você tem um pool de nós com quatro nós e a configuração de manutenção oportunista está definida como --opportunistic-maintenance=node-idle-time=600s,window=2419200s,min-nodes=3. Nesse cenário, ocorre o seguinte:

  • node1 tem uma carga de trabalho de GPU em execução. Esse nó não está inativo, então ele é ignorado.
  • node2 está inativo há 60 segundos. Esse nó não está inativo por tempo suficiente, então ele é ignorado.
  • node3 está inativo há 600 segundos. Esse nó atende ao requisito de inatividade.
  • node4 está inativo há 600 segundos. Esse nó atende ao requisito de inatividade.

node3 e node4 atendem ao requisito de inatividade. No entanto, apenas um desses nós vai acionar a manutenção oportunista porque o valor da opção min-nodes está definido como 3.

Verificar a configuração e o estado dos nós com manutenção oportunista

Verifique se a manutenção oportunista está configurada para um nó executando o seguinte comando:

kubectl describe node NODE_NAME | grep node.gke.io/opportunistic-config

Substitua NODE_NAME pelo nome do nó que você quer verificar.

Verifique se um nó configurado com manutenção oportunista está em manutenção:

kubectl describe node NODE_NAME | grep node.gke.io/maintenance-state

Se o nó for acionado pela manutenção oportunista, a anotação maintenance-state mostrará opportunistic-triggered como true.

Limitações

Esteja ciente das seguintes limitações da manutenção oportunista:

  • Esse recurso só pode ser usado com pools de nós de GPU e TPU.
  • A manutenção oportunista não é compatível com o escalonamento automático de clusters porque o escalonador automático de clusters já reduz verticalmente os nós inativos.
  • Para pools de nós de TPU de vários hosts, o valor da configuração min-nodes-per-pool precisa ser 0 porque esses pools de nós são atômicos.
  • A versão mínima compatível do GKE é a 1.33.3-gke.1118000.
  • Somente a manutenção planejada que inclui a can_reschedule=TRUE notificação é aceita.
  • Para desativar esse recurso, é necessário recriar o pool de nós sem as flags correspondentes. Ou, você pode desativar manualmente o recurso em nós específicos com cloud.google.com/opportunistic-disable=true.
  • Em casos raros, a manutenção pode levar mais tempo para ser concluída em um nó. Os clientes que usam esse recurso podem ter menos nós disponíveis, até o valor da configuração min-nodes-per-pool, por um período.

A seguir