Colocar nós no modo de manutenção

Quando você precisar reparar ou manter os nós, primeiro coloque-os no modo de manutenção. Isso drena normalmente os pods e as cargas de trabalho, exceto os pods críticos do sistema, como o servidor de API. O modo de manutenção também impede que o nó receba novas atribuições de pods. No modo de manutenção, é possível trabalhar nos nós sem o risco de interromper o tráfego do pod.

Como funciona

O Google Distributed Cloud oferece uma maneira de colocar os nós no modo de manutenção. Essa abordagem permite que outros componentes do cluster saibam corretamente que o nó está no modo de manutenção. Ao colocar um nó no modo de manutenção, nenhum pod adicional pode ser programado no nó, e os pods existentes são interrompidos.

Em vez de usar o modo de manutenção, é possível usar manualmente os comandos do Kubernetes, como kubectl cordon e kubectl drain, em um nó específico.

Quando você usa o processo do modo de manutenção, o Google Distributed Cloud faz o seguinte:

1.29

  • O Google Distributed Cloud adiciona o taint baremetal.cluster.gke.io/maintenance:NoSchedule aos nós especificados para evitar a programação de novos pods no nó.

  • O Google Distributed Cloud usa a API Eviction para remover cada pod. Esse método de drenagem de nós respeita PodDisruptionBudgets (PDBs). É possível configurar PDBs para proteger suas cargas de trabalho especificando um nível tolerável de interrupção para um conjunto de pods usando os campos minAvailable e maxUnavailable. Drenar os nós dessa maneira oferece melhor proteção contra interrupções de carga de trabalho. A diminuição de nós baseada em remoção está disponível como GA na versão 1.29.

  • É aplicado um tempo limite de 20 minutos para garantir que os nós não fiquem travados enquanto os pods são interrompidos. Os pods não serão encerrados se estiverem configurados para tolerar todos os taints ou tiverem finalizadores. O Google Distributed Cloud tenta interromper todos os pods, mas se o tempo limite for excedido, o nó será colocado em modo de manutenção. Esse tempo limite impede que os pods em execução bloqueiem os upgrades.

1.28 e anterior

  • O Google Distributed Cloud adiciona o taint baremetal.cluster.gke.io/maintenance:NoSchedule aos nós especificados para evitar a programação de novos pods no nó.

  • O Google Distributed Cloud adiciona o taint baremetal.cluster.gke.io/maintenance:NoExecute. Agindo no taint NoExecute, o Google Distributed Cloud kube-scheduler interrompe os pods e drena o nó. Esse método de drenagem de nós não respeita PDBs.

  • É aplicado um tempo limite de 20 minutos para garantir que os nós não fiquem travados enquanto os pods são interrompidos. Os pods não serão encerrados se estiverem configurados para tolerar todos os taints ou tiverem finalizadores. O Google Distributed Cloud tenta interromper todos os pods, mas se o tempo limite for excedido, o nó será colocado em modo de manutenção. Esse tempo limite impede que os pods em execução bloqueiem os upgrades.

Drenagem baseada em remoção

Não há alterações de procedimento associadas à mudança para drenagem de nós baseada em remoção por meio de taint. A chave afeta apenas a lógica de reconciliação.

Esse recurso não está na mesma etapa de lançamento para todas as versões compatíveis:

  • 1,29: GA
  • 1.28: Não disponível
  • 1.16: Não disponível

Ordem de drenagem

Antes da versão 1.29, a drenagem de nós com base em taint que é realizada pelo kube-scheduler do Google Distributed Cloud não emprega um algoritmo específico para drenar pods de um nó. Com a drenagem de nós baseada em remoção, os pods são removidos em uma ordem específica com base na prioridade. A prioridade de remoção está associada a critérios específicos do pod, conforme mostrado na tabela a seguir:

Ordem de drenagem critérios de pods (precisam corresponder a todos) e
1

Os pods que correspondem aos critérios a seguir são removidos:

  • Pods sem spec.prorityClassName
  • Pods que não correspondem a nenhum nome conhecido da interface de armazenamento em contêiner (CSI, na sigla em inglês)
  • Pods que não pertencem a um DaemonSet
2

Os pods que correspondem aos critérios a seguir são removidos:

  • Pods que pertencem a um DaemonSet
  • Os pods não têm PriorityClass
  • Pods que não correspondem a nenhum nome conhecido da interface de armazenamento em contêiner (CSI, na sigla em inglês)
3

Os pods que correspondem aos critérios a seguir são removidos:

  • Pods com Spec.ProrityClassName
  • Pods que não correspondem a nenhum nome conhecido da interface de armazenamento em contêiner (CSI, na sigla em inglês)

A ordem de remoção dos pods correspondentes é baseada em PriorityClass.value, de menor para maior.

4

Aguarde até que o CSI limpe as ativações de PV/PVC depois que todos os pods forem removidos. Use Node.Status.VolumesInUse para indicar que todos os volumes foram limpos.

5

Os pods que correspondem aos critérios a seguir são removidos:

  • Pods que correspondem a um nome conhecido da interface de armazenamento em contêiner (CSI, na sigla em inglês)

Esses pods ainda precisam ser drenados, porque o kubelet não oferece compatibilidade de atualização no local.

Como a drenagem de nós baseada em remoção respeita os PDBs, as configurações do PDB podem bloquear a diminuição do nó em algumas circunstâncias. Para informações sobre solução de problemas sobre diminuição do pool de nós, consulte Como verificar por que um nó está no status de diminuição há muito tempo.

Desativar a drenagem de nós com base em remoção

A drenagem de nós baseada em remoção é ativada por padrão para clusters na versão secundária 1.29 ou clusters que estão sendo atualizados para a versão secundária 1.29. Se a diminuição do nó baseado em remoção estiver causando problemas com os upgrades ou a manutenção do cluster, será possível reverter para a diminuição do nó baseada em taint adicionando a anotação baremetal.cluster.gke.io/maintenance-mode-ignore-pdb: true ao recurso do cluster.

Colocar um nó no modo de manutenção

Escolha os nós que você quer colocar no modo de manutenção especificando os intervalos de IPs dos nós selecionados em maintenanceBlocks no arquivo de configuração do cluster. Os nós escolhidos precisam estar prontos e funcionando no cluster.

Para colocar nós no modo de manutenção:

  1. Edite o arquivo de configuração do cluster para selecionar os nós que você quer colocar no modo de manutenção.

    É possível editar o arquivo de configuração com um editor de sua preferência ou editar o recurso personalizado do cluster diretamente executando o seguinte comando:

    kubectl -n CLUSTER_NAMESPACE edit cluster CLUSTER_NAME
    

    Substitua:

    • CLUSTER_NAMESPACE: o namespace do cluster.
    • CLUSTER_NAME: o nome do cluster.
  2. Adicione a seção maintenanceBlocks ao arquivo de configuração do cluster para especificar um único endereço IP ou um intervalo de endereços para os nós que você quer colocar no modo de manutenção.

    O exemplo a seguir mostra como selecionar vários nós especificando um intervalo de endereços IP:

    metadata:
      name: my-cluster
      namespace: cluster-my-cluster
    spec:
      maintenanceBlocks:
        cidrBlocks:
        - 172.16.128.1-172.16.128.64
    
  3. Salve e aplique a configuração atualizada do cluster.

    O Google Distributed Cloud começa a colocar os nós no modo de manutenção.

  4. Execute o seguinte comando para ver o status dos nós no cluster:

    kubectl get nodes --kubeconfig=KUBECONFIG
    

    O resultado será assim:

    NAME                       STATUS   ROLES           AGE     VERSION
    user-anthos-baremetal-01   Ready    control-plane   2d22h   v1.27.4-gke.1600
    user-anthos-baremetal-04   Ready    worker          2d22h   v1.27.4-gke.1600
    user-anthos-baremetal-05   Ready    worker          2d22h   v1.27.4-gke.1600
    user-anthos-baremetal-06   Ready    worker          2d22h   v1.27.4-gke.1600
    

    Os nós ainda são programáveis, mas os taints impedem a programação de qualquer pod (sem uma tolerância adequada).

  5. Execute o seguinte comando para ver o número de nós no modo de manutenção:

    kubectl get nodepools --kubeconfig ADMIN_KUBECONFIG 
    

    A resposta será semelhante a esta:

    NAME   READY   RECONCILING   STALLED   UNDERMAINTENANCE   UNKNOWN
    np1    3       0             0         1                  0
    

    Na coluna UNDERMAINTENANCE neste exemplo, vemos que um nó está no modo de manutenção.

    O Google Distributed Cloud também adiciona os seguintes taints aos nós quando eles são colocados no modo de manutenção:

    • baremetal.cluster.gke.io/maintenance:NoExecute
    • baremetal.cluster.gke.io/maintenance:NoSchedule

Remover um nó do modo de manutenção

Para remover nós do modo de manutenção:

  1. Edite o arquivo de configuração do cluster para limpar os nós que você quer remover do modo de manutenção.

    É possível editar o arquivo de configuração com um editor de sua preferência ou editar o recurso personalizado do cluster diretamente executando o seguinte comando:

    kubectl -n CLUSTER_NAMESPACE edit cluster CLUSTER_NAME
    

    Substitua:

    • CLUSTER_NAMESPACE: o namespace do cluster.
    • CLUSTER_NAME: o nome do cluster.
  2. Edite os endereços IP para remover nós específicos do modo de manutenção ou remova a seção maintenanceBlocks para remover todos os nós do modo de manutenção.

  3. Salve e aplique a configuração atualizada do cluster.

  4. Use comandos kubectl para verificar o status dos nós.

Encerrar e reiniciar um cluster

Se for necessário desativar um cluster completo, use as instruções nas seções a seguir para encerrar um cluster e recuperá-lo com segurança.

Encerrar um cluster

Se você estiver encerrando um cluster que gerencia clusters de usuário, primeiro precisa encerrar todos os clusters de usuário gerenciados. As instruções a seguir se aplicam a todos os tipos de cluster do Google Distributed Cloud.

  1. Verifique o status de todos os nós do cluster:

    kubectl get nodes --kubeconfig CLUSTER_KUBECONFIG
    

    Substitua CLUSTER_KUBECONFIG pelo caminho do arquivo kubeconfig do cluster.

    O resultado será assim:

    NAME        STATUS   ROLES           AGE    VERSION
    control-0   Ready    control-plane   202d   v1.27.4-gke.1600
    control-1   Ready    control-plane   202d   v1.27.4-gke.1600
    control-2   Ready    control-plane   202d   v1.27.4-gke.1600
    worker-0    Ready    worker          202d   v1.27.4-gke.1600
    worker-1    Ready    worker          202d   v1.27.4-gke.1600
    worker-2    Ready    worker          202d   v1.27.4-gke.1600
    worker-3    Ready    worker          202d   v1.27.4-gke.1600
    worker-4    Ready    worker          154d   v1.27.4-gke.1600
    worker-5    Ready    worker          154d   v1.27.4-gke.1600
    worker-6    Ready    worker          154d   v1.27.4-gke.1600
    worker-7    Ready    worker          154d   v1.27.4-gke.1600
    worker-8    Ready    worker          154d   v1.27.4-gke.1600
    worker-9    Ready    worker          154d   v1.27.4-gke.1600
    

    Se o STATUS de um nó não for Ready, é altamente recomendável solucionar o problema do nó e continuar somente quando todos os nós forem Ready.

  2. Se você estiver encerrando um cluster de usuário, verifique o status dos nós do cluster de administrador:

    kubectl get nodes --kubeconfig ADMIN_KUBECONFIG
    

    Substitua ADMIN_KUBECONFIG pelo caminho do arquivo kubeconfig para o cluster de gerenciamento.

    As etapas subsequentes dependem do cluster de administrador. Se o STATUS de um nó não for Ready, recomendamos que você solucione o problema do nó e continue somente quando todos os nós forem Ready.

  3. Verifique a integridade do cluster que você quer encerrar:

    bmctl check cluster -c CLUSTER_NAME --kubeconfig ADMIN_KUBECONFIG
    

    Substitua:

    • CLUSTER_NAME: o nome do cluster que você está verificando.

    • ADMIN_KUBECONFIG: o caminho do arquivo kubeconfig para o cluster de gerenciamento.

    Corrija todos os problemas informados antes de continuar.

  4. No cluster que você está encerrando, verifique se todos os pods etcd estão em execução:

    kubectl get pods --kubeconfig CLUSTER_KUBECONFIG -A \
        -l component=etcd
    

    Substitua CLUSTER_KUBECONFIG pelo caminho do arquivo kubeconfig do cluster.

    O resultado será assim:

    NAMESPACE     NAME                   READY   STATUS    RESTARTS   AGE
    kube-system   etcd-control-0-admin   1/1     Running   0          2d22h
    kube-system   etcd-control-1-admin   1/1     Running   0          2d22h
    kube-system   etcd-control-2-admin   1/1     Running   0          2d22h
    

    Se o STATUS de um pod não for Running, recomendamos que você solucione o problema do pod e prossiga somente quando todos os pods forem Running.

  5. Faça um backup conforme descrito em Fazer backup de um cluster.

    É importante fazer um backup do etcd antes de encerrar seu cluster para que ele possa ser restaurado se você encontrar problemas ao reiniciar o cluster. Corrupção de etcd, falhas de hardware do nó, problemas de conectividade de rede e potencialmente outras condições podem impedir que o cluster seja reiniciado corretamente.

  6. Se você estiver encerrando um cluster que tenha nós de trabalho, coloque esses nós no modo de manutenção.

    Esta etapa minimiza a quantidade de gravação no etcd, o que reduz a probabilidade de que uma grande quantidade de gravações do etcd precise ser reconciliada quando o cluster for reiniciado.

  7. Coloque os nós do plano de controle no modo de manutenção.

    Esta etapa evita gravações corrompidas para cargas de trabalho com estado durante o encerramento do nó.

  8. Desative os nós do cluster na seguinte sequência:

    1. Nós de trabalho
    2. Nós do balanceador de carga do plano de controle
    3. Nós do plano de controle, começando com os seguidores do etcd e terminando com o líder do etcd.

      Se você tiver um cluster de alta disponibilidade (HA, na sigla em inglês), poderá encontrar o líder do etcd usando o SSH para se conectar a cada nó do plano de controle e executando o seguinte comando etcdctl:

      ETCDCTL_API=3 etcdctl \
          --cacert /etc/kubernetes/pki/etcd/ca.crt \
          --cert /etc/kubernetes/pki/etcd/server.crt \
          --key /etc/kubernetes/pki/etcd/server.key \
          --write-out=table endpoint status
      

      A resposta inclui uma coluna IS LEADER, que retorna true se o nó for o líder do etcd.

Nesse momento, o cluster está completamente desligado. Depois de realizar a manutenção necessária, reinicie o cluster conforme descrito na próxima seção.

Reiniciar o cluster

Use as etapas a seguir para reiniciar um cluster que foi completamente desligado.

  1. Ligue as máquinas de nós na ordem inversa da sequência de desligamento.

  2. Remova os nós do plano de controle do modo de manutenção.

    Para mais instruções, consulte Remover um nó do modo de manutenção.

  3. Remova os nós de trabalho do modo de manutenção.

  4. Execute as verificações de integridade do cluster para garantir que ele esteja funcionando corretamente:

    bmctl check cluster -c CLUSTER_NAME --kubeconfig ADMIN_KUBECONFIG
    
  5. Se um problema, como o crashloop do etcd, impedir que o cluster seja reiniciado corretamente, tente restaurá-lo com base no último backup em bom estado. Para instruções, consulte Restaurar um cluster.

Modo de faturamento e manutenção

O faturamento do Google Distributed Cloud é baseado no número de vCPUs que o cluster tem para nós que podem executar cargas de trabalho. Quando você coloca um nó no modo de manutenção, os taints NoExecute e NoSchedule são adicionados ao nó, mas não desativam o faturamento. Depois de colocar um nó no modo de manutenção, demarque o nó (kubectl cordon NODE_NAME) para marcá-lo como não programável. Depois que um nó é marcado como não programável, ele e as vCPUs associadas são excluídos do faturamento.

Conforme descrito na página de preços, é possível usar kubectl para ver a capacidade de vCPU (usada para faturamento) de cada um dos clusters de usuário. O comando não considera se o nó é programável ou não. Ele fornece apenas uma contagem de vCPUs por nó.

Para identificar o número de vCPUs por nó do cluster de usuário:

kubectl get nodes \
    --kubeconfig USER_KUBECONFIG \
    -o=jsonpath="{range .items[*]}{.metadata.name}{\"\t\"} \
    {.status.capacity.cpu}{\"\n\"}{end}"

Substitua USER_KUBECONFIG pelo caminho do arquivo kubeconfig do cluster de usuário.