Práticas recomendadas para recursos avançados do agendador no AKS (Serviço de Kubernetes do Azure) usando o agendador de kube

As melhores práticas para os recursos avançados de agendamento do AKS incluem o uso de contaminações e tolerâncias para dedicar nós, seletores de nó e afinidade de nó para controlar o posicionamento de pods, e afinidade/anti-afinidade entre pods para gerenciar a distribuição de cargas de trabalho no cluster. À medida que você gerencia clusters no Serviço de Kubernetes do Azure (AKS), geralmente é necessário isolar equipes e cargas de trabalho. Os recursos avançados fornecidos pelo Agendador do Kubernetes permitem que você controle:

  • Quais pods podem ser agendados em determinados nós.
  • Como os aplicativos multipod podem ser distribuídos adequadamente pelo cluster.

Este artigo sobre práticas recomendadas se concentra em recursos de agendamento de Kubernetes avançados para os operadores do cluster. Neste artigo, você aprenderá como:

  • Use taints e tolerâncias para limitar quais pods podem ser agendados em nós.
  • Dê preferência ao pods para executar em determinados nós com seletores ou afinidade de nó.
  • Separe ou agrupe os pods com ou sem afinidade entre os pods.
  • Restrinja o agendamento de cargas de trabalho que exigem GPUs somente em nós com GPUs programáveis.

Se recursos adicionais ou estruturas de ML forem necessários para agendar e enfileirar cargas de trabalho em lotes, você poderá instalar e configurar o Kueue no AKS para garantir um agendamento eficiente e controlado por políticas em clusters do AKS.

Se forem necessárias configurações detalhadas do agendador para otimizar como pods e jobs priorizam nós específicos, recursos de armazenamento, topologia e muito mais, você pode configurar um agendador no AKS.

Comparação de recursos de agendamento

Feature Caso de uso Comportamento de agendamento Quando escolher
Taints e tolerâncias Dedicar nós para cargas de trabalho específicas (por exemplo, nós de GPU) Restrição grave: pods sem tolerância correspondente não podem agendar em nós contaminados Quando você precisa de isolamento de nó estrito e deseja evitar cargas de trabalho não autorizadas
Seletores de nó Posicionamento simples de pods com base em rótulos Restrição branda: os pods exigem rótulos correspondentes, mas os pods não rotulados ainda podem ser agendados em nós rotulados Quando você precisa de controle básico de agendamento com correspondência simples de rótulos
Afinidade de nó Direcionamento flexível de nós com opções de fallback Configurável: dá suporte a regras de correspondência obrigatórias (duras) e preferenciais (suaves) Quando você precisa de expressões avançadas ou deseja preferências de agendamento com comportamento de contingência
Afinidade/antiafinidade entre pods Colocalizar ou separar pods com base no posicionamento de pods existentes Controla a distribuição de pods em relação a outros pods em nós Quando relacionamentos pod a pod importam (por exemplo, colocalização de aplicativo e cache, ou distribuição de réplicas)

O que são taints e tolerâncias?

Os taints e as tolerâncias são um mecanismo do Kubernetes que permite aos nós repelir pods, a menos que esses pods tolerem explicitamente a mancha do nó, fornecendo isolamento rígido para cargas de trabalho dedicadas.

Prática recomendada: usar taints e tolerâncias para dedicar nós de GPU Limite o acesso a aplicativos com uso intensivo de recursos, como controladores de entrada, a nós específicos. Manter os recursos de nó disponíveis para cargas de trabalho os exigem e não permitir o agendamento de outras cargas de trabalho em nós.

Quando você cria um cluster do AKS, você pode implantar nós com suporte de GPU ou um grande número de CPUs avançadas. Para obter mais informações, confira Usar GPUs no AKS. Você pode usar esses nós para cargas de trabalho de processamento de dados grandes, como ML (aprendizado de máquina) ou IA (inteligência artificial).

Como esse hardware de recurso de nó geralmente é caro para implantar, limite as cargas de trabalho que podem ser agendadas nesses nós. Como alternativa, convém dedicar alguns nós do cluster para executar serviços de entrada e impedir outras cargas de trabalho.

Esse suporte para diferentes nós é fornecido usando múltiplos pools de nós. Um cluster AKS suporta um ou mais pools de nós.

O planejador do Kubernetes usa taints e tolerâncias para restringir quais cargas de trabalho podem ser executadas nos nós.

  • Aplique um taint a um nó para indicar que apenas pods específicos podem ser programados nele.
  • Em seguida, aplique uma toleration a um pod, permitindo que ele tolere seu taint.

Quando você implanta um pod em um cluster AKS, o Kubernetes agenda pods somente em nós cuja contaminação se alinha com a tolerância. Taints e tolerâncias trabalham juntos para garantir que os pods não sejam agendados em nós inapropriados. Uma ou mais contaminações são aplicadas a um nó, marcando o nó para que ele não aceite nenhum pod que não tolere as contaminações.

Como implementar taints e tolerâncias no AKS?

Por exemplo, suponha que você adicionou um pool de nós no seu cluster AKS para nós com suporte a GPU. Você define o nome, como gpu, em seguida, um valor para o agendamento. Definir esse valor como NoSchedule restringe o planejador do Kubernetes de agendar pods com tolerância indefinida no nó.

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name taintnp \
    --node-taints sku=gpu:NoSchedule \
    --no-wait

Com uma contaminação aplicada aos nós no pool de nós, você define uma tolerância na especificação do pod que permite o agendamento nos nós. O exemplo a seguir define sku: gpu e effect: NoSchedule para tolerar a contaminação aplicada ao pool de nós na etapa anterior:

kind: Pod
apiVersion: v1
metadata:
  name: app
spec:
  containers:
  - name: app
    image: <your-workload>:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  tolerations:
  - key: "sku"
    operator: "Equal"
    value: "gpu"
    effect: "NoSchedule"

Quando esse pod é implantado usando kubectl apply -f gpu-toleration.yaml, o Kubernetes pode agendá-lo com sucesso nos nós com o taint aplicado. Esse isolamento lógico permite que você controle o acesso a recursos dentro de um cluster.

Dedique pools de nós a várias aplicações

Para dedicar nós separados a diferentes aplicações, crie um pool de nós para cada aplicação com um taint exclusivo e um rótulo correspondente. O taint impede que outros pods sejam agendados no pool de nós, enquanto o rótulo permite que você exija que uma aplicação seja executada apenas no pool de nós dedicado.

O exemplo a seguir cria pools de nós separados para aplicativos de front-end e back-end:

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name frontpool \
    --node-count 1 \
    --labels workload=frontend \
    --node-taints workload=frontend:NoSchedule

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name backpool \
    --node-count 1 \
    --labels workload=backend \
    --node-taints workload=backend:NoSchedule

Crie um arquivo nomeado dedicated-apps.yaml e adicione as definições de pod a seguir. Cada pod tem uma tolerância que corresponde ao taint do pool de nós e uma nodeSelector que exige o rótulo do pool de nós correspondente:

apiVersion: v1
kind: Pod
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  nodeSelector:
    workload: frontend
  tolerations:
  - key: "workload"
    operator: "Equal"
    value: "frontend"
    effect: "NoSchedule"
  containers:
  - name: frontend
    image: mcr.microsoft.com/oss/nginx/nginx:1.25.5
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 250m
        memory: 256Mi
---
apiVersion: v1
kind: Pod
metadata:
  name: backend
  labels:
    app: backend
spec:
  nodeSelector:
    workload: backend
  tolerations:
  - key: "workload"
    operator: "Equal"
    value: "backend"
    effect: "NoSchedule"
  containers:
  - name: backend
    image: mcr.microsoft.com/oss/nginx/nginx:1.25.5
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 250m
        memory: 256Mi

Aplique o manifesto:

kubectl apply -f dedicated-apps.yaml

Verifique se cada pod está sendo executado em um nó com o rótulo de carga de trabalho esperado:

kubectl get pods -o wide
kubectl get nodes -L workload

O pod frontend foi agendado em um nó com o rótulo workload=frontend, e o pod backend foi agendado em um nó com o rótulo workload=backend. Uma tolerância por si só permite que um pod use um nó afetado, mas não exige posicionamento nesse nó. O nodeSelector fornece esse requisito.

Exclua os recursos de exemplo quando você não precisar mais deles:

kubectl delete -f dedicated-apps.yaml

az aks nodepool delete \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name frontpool

az aks nodepool delete \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name backpool

Ao aplicar taints, trabalhe com os desenvolvedores e proprietários do aplicativo para permitir que eles definam as tolerâncias necessárias em suas implantações.

Para obter mais informações sobre como usar diversos pools de nós no AKS, confira Criar vários pools de nós para um cluster no AKS.

Comportamento de taints e tolerations no AKS

Quando você atualiza um pool de nós no AKS, os taints e tolerations seguem um padrão definido à medida que são aplicados a novos nós:

Clusters padrão que usam os Conjuntos de Dimensionamento de Máquinas Virtuais do Azure

Você pode aplicar um taint a um pool de nós por meio da API do AKS para que os nós escalados horizontalmente recebam os taints do nó especificado da API.

Imagine o seguinte cenário:

  1. Você começa com um cluster de dois nós: nó1 e nó2.
  2. Você atualiza o pool de nós.
  3. Dois outros nós são criados: nó3 e nó4.
  4. As contaminações são transmitidas respectivamente.
  5. O node1 e o node2 originais são excluídos.

Clusters sem suporte aos Conjuntos de Dimensionamento de Máquinas Virtuais

Novamente, imagine o cenário:

  1. Você tem um cluster de dois nós: nó1 e nó2.
  2. Você atualiza o pool de nós.
  3. Um nó adicional é criado: nó3.
  4. Os taints do nó1 são aplicados ao nó3.
  5. node1 é excluído.
  6. Um novo nó1 é criado para substituir o nó1 original.
  7. Os taints do nó2 são aplicados ao novo nó1.
  8. node2 é excluído.

Basicamente, o nó1 se torna o nó3e o nó2 se torna o novo nó1.

Ao dimensionar um pool de nós no AKS, as contaminações e tolerâncias não são transferidas por design.

O que são seletores de nós e afinidade de nós?

Seletores de nó e afinidade de nós são recursos do Kubernetes que permitem que os pods especifiquem preferências sobre em quais nós devem ser executados, com base nos rótulos dos nós.

Prática recomendada: usar seletores de nó e afinidade para controlar o posicionamento do pod por tipo de hardware Controle o agendamento de pods em nós usando seletores de nó, afinidade de nó ou afinidade entre pods. Essas configurações permitem que o agendador do Kubernetes isole logicamente as cargas de trabalho, por exemplo, por hardware no nó.

Os taints e as tolerations isolam logicamente os recursos com uma separação rígida. Se o pod não tolerar o taint de um nó, ele não será agendado no nó.

Como alternativa, você pode usar seletores de nó. Por exemplo, você rotula os nós para indicar o armazenamento SSD anexado localmente ou uma grande quantidade de memória e, em seguida, define na especificação de pod um seletor de nós. O Kubernetes agenda os pods em um nó correspondente.

Ao contrário de tolerations, pods sem um seletor de nó correspondente ainda podem ser agendados em nós rotulados. Esse comportamento permite que recursos não utilizados nos nós sejam consumidos, mas prioriza os pods que definem o seletor de nó correspondente.

Vejamos um exemplo de nós com uma grande quantidade de memória. Esses nós priorizam pods que requerem uma grande quantidade de memória. Para garantir que os recursos não fiquem ociosos, eles também permitem que outros pods sejam executados. O comando de exemplo a seguir adiciona um pool de nós com o rótulo hardware=highmem ao myAKSCluster no myResourceGroup. Todos os nós nesse pool de nós têm esse rótulo.

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name labelnp \
    --node-count 1 \
    --labels hardware=highmem \
    --no-wait

Uma especificação de pod adiciona a propriedade nodeSelector para definir um seletor de nó que corresponde ao rótulo definido em um nó:

kind: Pod
apiVersion: v1
metadata:
  name: app
spec:
  containers:
  - name: app
    image: <your-workload>:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  nodeSelector:
      hardware: highmem

Ao usar essas opções do agendador, trabalhe com os desenvolvedores e proprietários do aplicativo para permitir que eles definam corretamente as especificações do pod.

Para obter mais informações sobre o uso de seletores de nós, veja Atribuição de pods a nós.

O que é afinidade de nó?

Um seletor de nó é uma solução básica para atribuir pods a determinado nó. A afinidade do nó oferece mais flexibilidade, permitindo que você defina o que acontece se o pod não puder ser correspondido a um nó. Você pode:

  • Exigir que o agendador do Kubernetes associe um pod a um host com rótulo. Ou,
  • Prefira uma correspondência, mas permita que o pod seja agendado em um host diferente caso nenhuma correspondência esteja disponível.

O exemplo a seguir define a afinidade do nó como requiredDuringSchedulingIgnoredDuringExecution. Essa afinidade exige que o cronograma do Kubernetes use um nó com um rótulo correspondente. Se nenhum nó estiver disponível, o pod terá que aguardar o agendamento para continuar. Para permitir que o pod seja agendado em um nó diferente, em vez disso, você pode definir o valor preferredDuringSchedulingIgnoreDuringExecution:

kind: Pod
apiVersion: v1
metadata:
  name: app
spec:
  containers:
  - name: app
    image: <your-workload>:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: hardware
            operator: In
            values:
            - highmem

A parte IgnoredDuringExecution da configuração indica que o pod não deve ser removido do nó se os rótulos do nó mudarem. O agendador do Kubernetes usa apenas os rótulos de nós atualizados para novos pods que estão sendo agendados, não pods já agendados nos nós.

Para obter mais informações, consulte Afinidade e antiafinidade.

O que são afinidade e antiafinidade entre pods?

Uma abordagem final para o planejador do Kubernetes isolar logicamente as cargas de trabalho é usar afinidade ou antiafinidade entre pods. Essas configurações definem que os pods não devem ou devem ser agendados em um nó que tem um pod correspondente existente. Por padrão, o agendador do Kubernetes tenta agendar vários pods em um conjunto de réplicas entre nós. Você pode definir regras mais específicas alternativas para esse comportamento.

Por exemplo, você tem um aplicativo Web que também usa um recurso redis gerenciado do Azure.

  • Use regras de antiafinidade de pod para solicitar que o planejador do Kubernetes distribua réplicas entre os nós.
  • Use regras de afinidade para garantir que cada componente do aplicativo da web seja alocado no mesmo host que o cache correspondente.

A distribuição de pods entre os nós se parece com o exemplo a seguir:

Nó 1 Nó 2 Nó 3
webapp-1 webapp-2 webapp-3
cache-1 cache-2 cache-3

A antiafinidade e a afinidade entre pods fornecem uma implantação mais complexa do que os seletores de nó ou a afinidade de nó. Com a implantação, você isola logicamente os recursos e controla como o Kubernetes agenda pods em nós.

Para um exemplo completo desta aplicação web com o Azure Managed Redis, consulte Colocalizar pods no mesmo nó.

Próximas etapas

Este artigo se concentra nos recursos avançados de agendador Kubernetes. Para obter mais informações sobre operações de cluster no AKS, consulte as seguintes práticas recomendadas: