Node Hardening (preview) in Azure Kubernetes Service (AKS)

Node Hardening é uma funcionalidade opt-in para pools de nós Linux que protege a estabilidade dos nós quando cargas de trabalho colocam os nós sob pressão da CPU, memória ou disco. Ao ativar o Node Hardening num cluster, o AKS altera a forma como cada nó reserva e aplica recursos para os componentes Kubernetes e serviços de hospedeiro, e como o Kubelet expulsa pods quando os recursos ficam esgotados.

Este artigo explica o que o Node Hardening altera, compara as predefinições reforçadas com as predefinições padrão do AKS e mostra-te como ativar, verificar, personalizar e desativar a funcionalidade.

Importante

As funcionalidades de pré-visualização do AKS estão disponíveis num regime de autosserviço e de adesão voluntária. As visualizações prévias são fornecidas "como estão" e "conforme disponíveis" e são excluídas dos contratos de nível de serviço e da garantia limitada. As versões de pré-visualização do AKS são apenas parcialmente abrangidas pelo suporte ao cliente, na medida do possível. Assim sendo, estas funcionalidades não se destinam ao uso em produção. Para obter mais informações, consulte os seguintes artigos de suporte:

Benefícios do hardening de nodes

Em nós ocupados ou com picos de carga, as cargas de trabalho podem consumir recursos que o kubelet, o tempo de execução do contentor e os serviços do host necessitam. Quando isso acontece, os nós podem ficar sem resposta, reportar um status NotReady ou terminar pods abruptamente. O endurecimento de nós reduz estes riscos das seguintes formas:

  • Reservas impostas: Por defeito, o AKS usa valores kube-reserved apenas para calcular quanta capacidade o escalonador pode alocar aos pods. Ao utilizar Node Hardening, o kubelet também aplica a capacidade kube-reserved e system-reserved através de grupos de controlo Linux (cgroups). O kubelet e o containerd correm num cgroup dedicado kubereserved.slice , por isso mantêm a partilha de CPU e memória reservadas mesmo quando os pods saturam o nó.
  • Capacidade dedicada para serviços do anfitrião: O Node Hardening adiciona uma alocação reservada pelo sistema para serviços do sistema operativo anfitrião, que são executados em system.slice.
  • Mais margem de memória: O limiar de expulsão rígida para memória disponível escala com a memória do nó, por isso o kubelet expulsa pods antes que o nó fique criticamente com pouca memória.
  • Expulsão graciosa: Limiares suaves de expulsão permitem ao kubelet expulsar pods de forma graciosa, com um período de carência de terminação, quando a memória ou o espaço em disco se esgotam. A eviction rígida, que termina os pods imediatamente, funciona como último recurso.
  • Reservas que escalam com a densidade de pods: O cálculo da memória reservada por kube é ajustado em função do número máximo de pods por nó, o que tem em conta a sobrecarga do kubelet e do containerd associada à execução de mais pods.

O que muda quando ativas o Endurecimento do Node

As tabelas seguintes comparam os valores padrão para nós Linux a correr Kubernetes 1.29 ou posterior com os valores que o AKS aplica quando o Endurecimento de Nó está ativado.

Reservas de recursos

Setting Sem hardening de Node Com reforço do Node
CPU reservada para o Kube Com base no número de núcleos de CPU. Para mais informações, consulte as reservas de CPU. Inalterado
Memória reservada para Kube min(20 × maxPods + 50, 25% of node memory) MiB min(35 × maxPods + max(250, 2% of node memory), 25% of node memory) MiB
IDs de processo reservados por Kube (PIDs) 1000 Não reservado
CPU reservada pelo sistema None 100m
Memória reservada pelo sistema None 200 MiB, mais 100 MiB para cada 32 GiB completos de memória de nó, mais 100 MiB para clusters que usam Azure CNI
Armazenamento efémero reservado pelo sistema None 1Gi

Limiares de expulsão

Setting Sem Node Hardening Com hardening de Node
Despejo forçado: memory.available 100Mi 250Mi para nós com 8 GiB de memória ou menos, 375Mi para nós com mais de 8 GiB e menos de 32 GiB, e 512Mi para nós com 32 GiB ou mais
Despejo forçado: nodefs.available e nodefs.inodesFree 10% e 5% Inalterado
Despejo forçado: pid.available 2000 Não definido
Remoção lógica: memory.available None 500Mi, 750Mi, ou 1Gi, usando os mesmos níveis de memória de nós que a expulsão forçada, com um período de carência de 30 segundos
Evicção suave: nodefs.available e nodefs.inodesFree None 12% e 7%, cada um com um período de carência de 2 minutos
Período máximo de tolerância antes da terminação do pod durante despejo suave Não definido 60 segundos

Imposição de cgroup

Setting Sem Node Hardening Com hardening de Node
Alocação do nó imposta pods pods, kube-reservede system-reserved
Kubelet e containerd cgroup system.slice, sem limites kubereserved.slice, com memória limitada à memória kube-reserved e uma partilha de CPU proporcional à CPU kube-reserved
Cgroup de serviços do host system.slice, sem limites system.slice, com memória limitada à memória reservada pelo sistema e uma partilha de CPU proporcional à CPU reservada pelo sistema

Como o endurecimento de nós reserva mais capacidade, os nós reportam menos capacidade alocável para pods. Por exemplo, num nó com 4 vCPUs e 16 GiB de memória que utiliza o Azure CNI, ativar o endurecimento de nó reduz a capacidade alocável da seguinte forma:

  • Com o máximo padrão de 250 pods por nó, em cerca de 570 MiB de memória, 100 milicores de CPU e 1 GiB de armazenamento efémero.
  • Com um máximo de 30 pods por nó, limitado por cerca de 1,3 GiB de memória, 100 millicores de CPU e 1 GiB de armazenamento efémero.

Os limiares de soft eviction não reduzem a capacidade alocável. Só mudam quando o kubelet começa a expulsar pods.

Considerations

Tenha em mente as seguintes considerações antes de ativar o Node Hardening:

  • Ativas o reforço de nó ao nível do cluster, e aplica-se a todos os pools de nós Linux no cluster. Não se pode ativar para pools individuais de nós, e não afeta os pools de nós do Windows.
  • Os nós reportam menos capacidade alocável, por isso pods que cabem num nó antes de ativar o reforço de nó podem não caber depois. Revê os pedidos de recursos dos teus pods e os tamanhos do pool de nós.
  • Os serviços host em system.slice partilham um limite de memória rígida igual à memória reservada pelo sistema. Se executares os teus próprios agentes em nós como serviços systemd, como agentes de segurança, monitorização ou log-forwarding, esses agentes contam para esse limite. Valida a utilização da memória deles e a estabilidade antes de usares Node Hardening em produção.
  • Os valores que defines na configuração personalizada de kubelet de um pool de nós sobrepõem-se aos respetivos padrões de endurecimento de nós. Para mais informações, consulte Personalizar definições de endurecimento de nós.
  • Se desativares o Hardening de nós mais tarde, os pools de nós existentes mantêm as definições de soft eviction reforçadas, mesmo depois de os seus nós serem reimaginados. Para remover estas definições, precisas de criar novos pools de nós. Para mais informações, consulte Desativar o reforço dos nós.
  • Os valores padrão podem mudar enquanto a funcionalidade está em pré-visualização. Comece com um cluster não produtivo e valide as suas cargas de trabalho sob condições representativas de pressão de nós.

Prerequisites

  • Uma assinatura do Azure. Se não tiver uma, crie uma conta gratuita.
  • Um cluster AKS com pools de nós Linux, ou permissões para criar um.
  • A aks-preview extensão CLI do Azure e a CustomNodeConfigPreview feature flag, conforme descrito nas secções seguintes.

Instala a extensão aks-preview CLI do Azure

  1. Instala a aks-preview extensão usando o az extension add comando.

    az extension add --name aks-preview
    
  2. Atualize para a versão mais recente da extensão usando o az extension update comando.

    az extension update --name aks-preview
    

Registar o sinalizador de funcionalidade CustomNodeConfigPreview

  1. Regista o CustomNodeConfigPreview sinalizador de funcionalidade utilizando o comando az feature register.

    az feature register --namespace "Microsoft.ContainerService" --name "CustomNodeConfigPreview"
    

    Leva alguns minutos para que o status mostre Registrado.

  2. Verifique o estado do registo usando o az feature show comando.

    az feature show --namespace "Microsoft.ContainerService" --name "CustomNodeConfigPreview"
    
  3. Quando o estado apresentar Registado, atualize o registo do fornecedor de recursos Microsoft.ContainerService utilizando o comando az provider register.

    az provider register --namespace "Microsoft.ContainerService"
    

Ativar Reforço dos nós

Durante a pré-visualização, o Node Hardening não está ativado por defeito.

Ativar o fortalecimento do nó num novo cluster

Crie um cluster com o Endurecimento de Nó ativado usando o az aks create comando com o --enable-node-hardening parâmetro.

Este comando requer a aks-preview extensão e a CustomNodeConfigPreview feature flag. Para obter mais informações, consulte Pré-requisitos.

az aks create \
    --resource-group <resource-group-name> \
    --name <cluster-name> \
    --enable-node-hardening \
    --generate-ssh-keys

Para confirmar a alteração, veja Definições de reforço dos nós.

Ativar a proteção reforçada do Node num cluster existente

Ative o reforço de nó num cluster existente usando o az aks update comando com o --enable-node-hardening parâmetro.

Este comando requer a aks-preview extensão e a CustomNodeConfigPreview feature flag. Para obter mais informações, consulte Pré-requisitos.

az aks update \
    --resource-group <resource-group-name> \
    --name <cluster-name> \
    --enable-node-hardening

Para confirmar a alteração, veja Verificar definições de endurecimento de nós.

Verificar as definições de reforço de segurança de nós

  1. Obtenha as credenciais do seu cluster usando o az aks get-credentials comando.

    az aks get-credentials --resource-group <resource-group-name> --name <cluster-name>
    
  2. Revise as definições efetivas de reserva e expulsão do kubelet num nó, consultando o endpoint de configuração do kubelet.

    kubectl get --raw "/api/v1/nodes/<node-name>/proxy/configz" | jq '.kubeletconfig | {kubeReserved, systemReserved, evictionHard, evictionSoft, evictionSoftGracePeriod, evictionMaxPodGracePeriod, enforceNodeAllocatable}'
    

    Num nó reforçado, systemReserved e evictionSoft contêm valores, e enforceNodeAllocatable inclui kube-reserved e system-reserved.

  3. Compare a capacidade do nó com os seus recursos alocáveis.

    kubectl get node <node-name> -o jsonpath='{.status.capacity}{"\n"}{.status.allocatable}{"\n"}'
    

    Num nó endurecido, a CPU, a memória e o armazenamento efémero alocáveis são inferiores à capacidade. A diferença é igual aos valores kube-reserved e system-reserved em Reservas de recursos, mais os limiares rígidos de expulsão em Limiares de expulsão. Por exemplo, num nó com 4 vCPUs e 16 GiB de memória que utiliza Azure CNI, a CPU alocável é 240 milicores inferior à capacidade: 140 milicores de CPU reservado ao kube e 100 milicores de CPU reservado ao sistema.

Personalizar definições de endurecimento do Node

Podes sobrescrever os valores predefinidos de kube-reserved e eviction para um pool de nós Linux usando uma configuração personalizada de kubelet. Estas definições requerem a CustomNodeConfigPreview feature flag. Podes usá-los independentemente de o Node Hardening estar ou não ativado no cluster. O AKS gere valores reservados no sistema e a imposição de cgroups, e não podes personalizá-los.

Cada configuração substitui uma linha nas tabelas Resource reservations ou Eviction thresholds. As linhas reservadas por Kube correspondem às kubeReserved definições. As filas de remoção forçada correspondem às definições hardEvictionThreshold. As linhas de despejo suave correspondem às definições softEvictionThreshold e softEvictionGracePeriod. O período máximo de graça para terminação de pod corresponde a evictionMaxPodGracePeriodInSeconds.

Pode configurar as seguintes definições:

Setting Overrides Description
kubeReserved.cpuMillicores CPU reservada para o Kube CPU reservado para daemons do sistema Kubernetes, em millicores.
kubeReserved.memoryMB Memória reservada para o Kube Memória reservada para os demónios do sistema Kubernetes, em MiB.
hardEvictionThreshold.memoryAvailable Despejo forçado: memory.available Limiar de eliminação rígido para a memória disponível.
hardEvictionThreshold.nodeFsAvailable Despejo forçado: nodefs.available Limiar rígido de expulsão para o espaço disponível no sistema de ficheiros dos nós.
hardEvictionThreshold.nodeFsInodesFree Despejo forçado: nodefs.inodesFree Limiar de expulsão rígido para inodes livres do sistema de ficheiros do nó.
softEvictionThreshold.memoryAvailable Expulsão ligeira: memory.available Limiar de eliminação flexível para memória disponível.
softEvictionThreshold.nodeFsAvailable Soft eviction: nodefs.available Limiar de expulsão suave para o espaço disponível no sistema de ficheiros dos nós.
softEvictionThreshold.nodeFsInodesFree Expulsão suave: nodefs.inodesFree Limiar de expulsão suave para inodes do sistema de ficheiros livre do nó.
softEvictionGracePeriod.memoryAvailable Desalojamento suave: memory.available período de carência Quanto tempo a memória disponível deve permanecer abaixo do seu limiar suave antes de o kubelet expulsar os pods.
softEvictionGracePeriod.nodeFsAvailable Remoção gradual: nodefs.available período de carência Durante quanto tempo o espaço disponível do sistema de ficheiros dos nós deve manter-se abaixo do seu limite flexível antes de o kubelet expulsar os pods.
softEvictionGracePeriod.nodeFsInodesFree Expulsão suave: nodefs.inodesFree período de carência Durante quanto tempo os inodes livres do sistema de ficheiros do nó devem permanecer abaixo do seu limiar suave antes de o kubelet expulsar pods.
evictionMaxPodGracePeriodInSeconds Período máximo de carência para terminação do pod durante remoção branda Número máximo de segundos que o kubelet permite que os pods terminem durante uma evicção suave.
  • Para valores permitidos, mínimos e regras de validação para cada definição, veja Parâmetros de configuração personalizados de nós para AKS.
  • Para cada sinal de eliminação, defina tanto o limiar de eliminação suave como o seu período de carência correspondente, e certifique-se de que cada limiar de eliminação suave é superior ao limiar de eliminação rígido para o mesmo sinal.
  1. Cria um ficheiro de configuração kubelet, como nodehardening-kubelet.json, com as definições que queres personalizar. O exemplo seguinte define todos os valores configuráveis. Define kube-reserved para 200 milicores de CPU e 1.024 MiB de memória. Define-se limiares de expulsão rígidos de 512Mi de memória disponível, 10% de espaço disponível no sistema de ficheiros e 5% de inodes livres. Define limiares suaves de despejo de 1Gi, 12%, e 7% com períodos de carência de 30 segundos, 2 minutos e 2 minutos. Também define um período máximo de tolerância de 60 segundos para a terminação do pod.

    {
      "kubeReserved": {
        "cpuMillicores": 200,
        "memoryMB": 1024
      },
      "hardEvictionThreshold": {
        "memoryAvailable": "512Mi",
        "nodeFsAvailable": "10%",
        "nodeFsInodesFree": "5%"
      },
      "softEvictionThreshold": {
        "memoryAvailable": "1Gi",
        "nodeFsAvailable": "12%",
        "nodeFsInodesFree": "7%"
      },
      "softEvictionGracePeriod": {
        "memoryAvailable": "30s",
        "nodeFsAvailable": "2m",
        "nodeFsInodesFree": "2m"
      },
      "evictionMaxPodGracePeriodInSeconds": 60
    }
    
  2. Criar um pool de nós Linux que use o ficheiro de configuração usando o comando az aks nodepool add com o parâmetro --kubelet-config.

    az aks nodepool add \
        --resource-group <resource-group-name> \
        --cluster-name <cluster-name> \
        --name <node-pool-name> \
        --kubelet-config ./nodehardening-kubelet.json
    

    Também pode usar o --kubelet-config parâmetro com o az aks create comando para aplicar a configuração ao pool inicial de nós do cluster.

Desativar o endurecimento do Node

Desative o endurecimento de nó usando o az aks update comando com o --disable-node-hardening parâmetro.

Este comando requer a aks-preview extensão e a CustomNodeConfigPreview feature flag. Para obter mais informações, consulte Pré-requisitos.

az aks update \
    --resource-group <resource-group-name> \
    --name <cluster-name> \
    --disable-node-hardening

Desativar o Node Hardening desativa a definição ao nível do cluster, mas não altera imediatamente os nós existentes. Os nós existentes mantêm todas as definições reforçadas até serem recriados a partir da imagem, por exemplo, durante uma atualização da imagem do nó. Após a reimagem de um nó, aplicam-se as seguintes alterações:

  • Reposto para as predefinições padrão do AKS: recursos reservados para o Kube e recursos reservados para o sistema, limiares rigorosos de expulsão e aplicação de cgroups. A capacidade alocável do nó aumenta em conformidade com isso.
  • Mantido: Os limiares de expulsão suave, os períodos de carência para expulsão suave e o período máximo de carência para terminação do pod durante a expulsão suave.

Só podes definir uma configuração personalizada de kubelet quando crias um cluster ou pool de nós, por isso não podes remover as definições de soft eviction retidas de um pool de nós existente. Para os remover, cria um novo pool de nós que os desdefina explicitamente, move as cargas de trabalho para o novo pool de nós e depois elimina o pool de nós antigo.

  1. Crie um ficheiro de configuração kubelet, como remove-soft-eviction.json. O exemplo seguinte define cada limiar e período de carência de remoção suave para uma cadeia vazia, o que desliga a remoção suave para esse sinal. Também define o período máximo de carência de terminação do pod para 0, que é o padrão padrão do AKS.

    {
      "softEvictionThreshold": {
        "memoryAvailable": "",
        "nodeFsAvailable": "",
        "nodeFsInodesFree": ""
      },
      "softEvictionGracePeriod": {
        "memoryAvailable": "",
        "nodeFsAvailable": "",
        "nodeFsInodesFree": ""
      },
      "evictionMaxPodGracePeriodInSeconds": 0
    }
    
  2. Criar um pool de nós Linux que use o ficheiro de configuração usando o comando az aks nodepool add com o parâmetro --kubelet-config.

    az aks nodepool add \
        --resource-group <resource-group-name> \
        --cluster-name <cluster-name> \
        --name <node-pool-name> \
        --kubelet-config ./remove-soft-eviction.json
    
  3. Mude as tuas cargas de trabalho para o novo pool de nós e depois elimina o pool antigo. Para mais informações, consulte Redimensionar pools de nós no AKS.

Para confirmar as definições de um nó, consulte Verificar definições de endurecimento do nó. Nos nós do novo conjunto de nós, evictionSoft está vazio.