Melhores práticas para funcionalidades avançadas do agendador no Azure Kubernetes Service (AKS)

À medida que gere clusters no Azure Kubernetes Service (AKS), muitas vezes tem de isolar equipas e cargas de trabalho. As funcionalidades avançadas fornecidas pelo agendador do Kubernetes permitem-lhe controlar:

  • Que pods podem ser agendados em determinados nós.
  • Como as aplicações multi pod podem ser distribuídas adequadamente pelo cluster.

Este artigo de melhores práticas centra-se nas funcionalidades avançadas de agendamento do Kubernetes para operadores de cluster. Neste artigo, vai aprender a:

  • Utilize taints e tolerâncias para limitar os pods que podem ser agendados em nós.
  • Dê preferência aos pods para serem executados em determinados nós com seletores de nós ou afinidade de nó.
  • Divida ou agrupe pods com afinidade entre pods ou anti-afinidade.
  • Restringir o agendamento de cargas de trabalho que requerem GPUs apenas em nós com GPUs agendados.

Indicar os nós dedicados com rejeições e tolerâncias

Orientação de melhores práticas:

Limitar o acesso a aplicações com utilização intensiva de recursos, como controladores de entrada, a nós específicos. Mantenha os recursos de nós disponíveis para cargas de trabalho que os exijam e não permita o agendamento de outras cargas de trabalho nos nós.

Quando cria o cluster do AKS, pode implementar nós com suporte de GPU ou um grande número de CPUs avançadas. Para obter mais informações, veja Utilizar GPUs no AKS. Pode utilizar estes nós para cargas de trabalho de processamento de dados grandes, como machine learning (ML) ou inteligência artificial (IA).

Uma vez que este hardware de recursos de nó é normalmente caro de implementar, limite as cargas de trabalho que podem ser agendadas nestes nós. Em vez disso, dedique alguns nós no cluster para executar serviços de entrada e impedir outras cargas de trabalho.

Este suporte para nós diferentes é fornecido através de vários conjuntos de nós. Um cluster do AKS suporta um ou mais conjuntos de nós.

O agendador do Kubernetes utiliza taints e tolerâncias para restringir as cargas de trabalho que podem ser executadas em nós.

  • Aplique um taint a um nó para indicar que apenas pods específicos podem ser agendados nos mesmos.
  • Em seguida, aplique uma tolerância a um pod, permitindo-lhes tolerar o taint de um nó.

Quando implementa um pod num cluster do AKS, o Kubernetes apenas agenda pods em nós cujo taint está alinhado com a tolerância. Taints e tolerâncias trabalham em conjunto para garantir que os pods não são agendados para nós inapropriados. Uma ou mais taints são aplicadas a um nó, marcando o nó para que não aceite pods que não toleram as taints.

Por exemplo, suponha que adicionou um conjunto de nós no cluster do AKS para nós com suporte de GPU. Define o nome, como gpu e, em seguida, um valor para agendamento. Definir este valor como NoSchedule restringe o agendador 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 taint aplicada aos nós no conjunto de nós, define uma tolerância na especificação do pod que permite o agendamento nos nós. O exemplo seguinte define o sku: gpu e effect: NoSchedule para tolerar o taint aplicado ao conjunto de nós no passo anterior:

kind: Pod
apiVersion: v1
metadata:
  name: tf-mnist
spec:
  containers:
  - name: tf-mnist
    image: mcr.microsoft.com/azuredocs/samples-tf-mnist-demo:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  tolerations:
  - key: "sku"
    operator: "Equal"
    value: "gpu"
    effect: "NoSchedule"

Quando este pod é implementado com kubectl apply -f gpu-toleration.yamlo , o Kubernetes pode agendar com êxito o pod nos nós com o taint aplicado. Este isolamento lógico permite-lhe controlar o acesso aos recursos num cluster.

Quando aplicar taints, trabalhe com os seus programadores e proprietários de aplicações para permitir que definam as tolerâncias necessárias nas respetivas implementações.

Para obter mais informações sobre como utilizar múltiplos conjuntos de nós no AKS, veja Criar múltiplos conjuntos de nós para um cluster no AKS.

Comportamento de taints e tolerâncias no AKS

Quando atualiza um conjunto de nós no AKS, as taints e as tolerâncias seguem um padrão definido à medida que são aplicados a novos nós:

Clusters predefinidos que utilizam o Azure Conjuntos de Dimensionamento de Máquinas Virtuais

Pode manchar um conjunto de nós da API do AKS para que os nós recém-aumentados recebam taints de nó especificados pela API.

Vamos supor:

  1. Começa com um cluster de dois nós: nó1 e nó2.
  2. Atualize o conjunto de nós.
  3. São criados dois outros nós: node3 e node4.
  4. Os taints são transmitidos, respectivamente.
  5. O nó original1 e o nó2 são eliminados.

Clusters sem suporte Conjuntos de Dimensionamento de Máquinas Virtuais

Mais uma vez, vamos supor:

  1. Tem um cluster de dois nós: nó1 e nó2.
  2. Atualize o conjunto de nós.
  3. É criado um nó adicional: node3.
  4. Os taints do nó1 são aplicados ao nó3.
  5. o nó1 foi eliminado.
  6. É criado um novo nó1 para substituir no nó original1.
  7. Os taints do nó2 são aplicados ao novo nó1.
  8. o nó2 é eliminado.

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

Quando dimensiona um conjunto de nós no AKS, as taints e as tolerâncias não transitam por predefinição.

Controlar o agendamento de pods com seletores de nós e afinidade

Orientação sobre melhores práticas

Controle o agendamento de pods em nós com seletores de nós, afinidade de nó ou afinidade entre pods. Estas definições permitem ao agendador do Kubernetes isolar logicamente cargas de trabalho, como por hardware no nó.

Taints e tolerâncias isolam logicamente os recursos com um corte difícil. Se o pod não tolerar o taint de um nó, não está agendado no nó.

Em alternativa, pode utilizar seletores de nós. Por exemplo, vai etiquetar nós para indicar o armazenamento SSD ligado localmente ou uma grande quantidade de memória e, em seguida, definir na especificação do pod um seletor de nós. O Kubernetes agenda esses pods num nó correspondente.

Ao contrário das tolerâncias, os pods sem um seletor de nós correspondente ainda podem ser agendados em nós etiquetados. Este comportamento permite que os recursos não utilizados nos nós consumam, mas prioriza pods que definem o seletor de nós correspondente.

Vejamos um exemplo de nós com uma elevada quantidade de memória. Estes nós priorizam pods que pedem uma elevada quantidade de memória. Para garantir que os recursos não ficam inativos, também permitem a execução de outros pods. O seguinte comando de exemplo adiciona um conjunto de nós com a etiqueta hardware=highmem ao myAKSCluster no myResourceGroup. Todos os nós nesse conjunto de nós têm esta etiqueta.

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

Em seguida, uma especificação de pod adiciona a nodeSelector propriedade para definir um seletor de nós que corresponda à etiqueta definida num nó:

kind: Pod
apiVersion: v1
metadata:
  name: tf-mnist
spec:
  containers:
  - name: tf-mnist
    image: mcr.microsoft.com/azuredocs/samples-tf-mnist-demo:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  nodeSelector:
      hardware: highmem

Quando utilizar estas opções de programador, trabalhe com os programadores e proprietários da sua aplicação para permitir que definam corretamente as respetivas especificações de pods.

Para obter mais informações sobre como utilizar seletores de nós, veja Atribuir Pods a Nós.

Afinidade de nó

Um seletor de nós é uma solução básica para atribuir pods a um determinado nó. A afinidade de nó proporciona mais flexibilidade, permitindo-lhe definir o que acontece se o pod não puder ser correspondido com um nó. Pode:

  • Exigir que o agendador do Kubernetes corresponda a um pod com um anfitrião etiquetado. Ou,
  • Preferir uma correspondência, mas permitir que o pod seja agendado num anfitrião diferente se não existir correspondência disponível.

O exemplo seguinte define a afinidade do nó como requiredDuringSchedulingIgnoredDuringExecution. Esta afinidade requer que a agenda do Kubernetes utilize um nó com uma etiqueta correspondente. Se nenhum nó estiver disponível, o pod tem de aguardar que o agendamento continue. Para permitir que o pod seja agendado num nó diferente, pode, em vez disso, definir o valor como DuringSchedulingIgnoreDuringExecution preferencial:

kind: Pod
apiVersion: v1
metadata:
  name: tf-mnist
spec:
  containers:
  - name: tf-mnist
    image: mcr.microsoft.com/azuredocs/samples-tf-mnist-demo: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 definição indica que o pod não deve ser expulso do nó se as etiquetas dos nós forem alteradas. O agendador do Kubernetes utiliza apenas as etiquetas de nó atualizadas para novos pods agendados e não pods já agendados nos nós.

Para obter mais informações, veja Afinidade e anti-afinidade.

Afinidade e anti-afinidade entre pods

Uma abordagem final para o agendador do Kubernetes isolar logicamente as cargas de trabalho é utilizar a afinidade entre pods ou anti-afinidade. Estas definições definem que os pods não devem ou devem ser agendados num nó que tenha um pod correspondente existente. Por predefinição, o agendador do Kubernetes tenta agendar vários pods numa réplica definida entre nós. Pode definir regras mais específicas em torno deste comportamento.

Por exemplo, tem uma aplicação Web que também utiliza um Cache do Azure para Redis.

  • Pode utilizar regras anti-afinidade do pod para pedir que o agendador do Kubernetes distribua réplicas pelos nós.
  • Utilize regras de afinidade para garantir que cada componente da aplicação Web está agendado no mesmo anfitrião que uma cache correspondente.

A distribuição de pods entre nós tem o seguinte exemplo:

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

A afinidade entre pods e a anti-afinidade proporcionam uma implementação mais complexa do que os seletores de nós ou afinidade de nó. Com a implementação, isola logicamente os recursos e controla a forma como o Kubernetes agenda pods em nós.

Para obter um exemplo completo desta aplicação Web com Cache do Azure para Redis exemplo, veja Co-localizar pods no mesmo nó.

Passos seguintes

Este artigo focou-se nas funcionalidades avançadas do agendador do Kubernetes. Para obter mais informações sobre as operações de cluster no AKS, veja as seguintes melhores práticas: