Adicionar um pool de nós do Azure Spot a um cluster do AKS (Serviço de Kubernetes do Azure)

Neste artigo, você adiciona um pool de nós Spot secundário a um cluster existente do AKS (Serviço de Kubernetes do Azure).

Um pool de nós Spot é apoiado por um Conjunto de dimensionamento de Máquinas Virtuais do Azure Spot. Com as VMs Spot no seu cluster do AKS, você pode aproveitar a capacidade do Azure não utilizada com economias de custos significativas. A quantidade de capacidade disponível não utilizada varia com base em muitos fatores, como região, hora do dia e tamanho do nó.

Quando você implanta um pool de nós Spot, o Azure aloca os nós Spot se houver capacidade disponível e implanta um conjunto de dimensionamento Spot que faz o backup do pool de nós Spot em um único domínio padrão. Não há SLA para os nós Spot. Não há garantias de alta disponibilidade. Se o Azure precisar recuperar capacidade, a infraestrutura do Azure desalojará os nós Spot.

Os nós Spot são ótimos para cargas de trabalho que toleram interrupções, encerramentos antecipados ou desalojamentos. Por exemplo, cargas de trabalho como trabalhos de processamento em lote, ambientes de desenvolvimento e teste e grandes cargas de trabalho de computação podem ser boas candidatas para agendamento em um pool de nós Spot.

Antes de começar

  • Este artigo pressupõe uma compreensão básica dos conceitos do Kubernetes e do Azure Load Balancer. Para obter mais informações, confira Principais conceitos do Kubernetes para o AKS (Serviço de Kubernetes do Azure).
  • Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.
  • Ao criar um cluster para usar um pool de nós Spot, o cluster deve usar Conjuntos de Dimensionamento de Máquinas Virtuais do Microsoft Azure para pools de nós e o balanceador de carga de SKU padrão. Você também deve adicionar outro pool de nós depois de criar seu cluster, que é abordado neste tutorial.
  • Este artigo exige a execução da CLI do Azure versão 2.14 ou posterior. Execute az --version para encontrar a versão. Se você precisa instalar ou atualizar, consulte Instalar a CLI do Azure.

Limitações

As seguintes limitações se aplicam ao criar e gerenciar clusters do AKS com um pool de nós Spot:

  • Um pool de nós Spot não pode ser um pool de nós padrão; ele só pode ser usado como pool secundário.
  • Não é possível atualizar o plano de controle e os pools de nós ao mesmo tempo. Você deve atualizá-los separadamente ou remover o pool de nós Spot para atualizar o plano de controle e os pools de nós restantes ao mesmo tempo.
  • Um pool de nós Spot deve usar Conjuntos de Dimensionamento de Máquinas Virtuais do Microsoft Azure.
  • Você não pode alterar ScaleSetPriority ou SpotMaxPrice após a criação.
  • Ao definir SpotMaxPrice, o valor deve ser -1 ou um valor positivo com até cinco casas decimais.
  • Um pool de nós Spot tem o kubernetes.azure.com/scalesetpriority:spot rótulo, o kubernetes.azure.com/scalesetpriority=spot:NoSchedule taint e os pods do sistema têm antiafinidade.
  • Você deve adicionar uma tolerância correspondente e afinidade para agendar cargas de trabalho em um pool de nós Spot.

Adicionar um pool de nós Spot a um cluster do AKS

Ao adicionar um pool de nós Spot a um cluster existente, ele deve ser um cluster com vários pools de nós habilitados. Ao criar um cluster AKS com vários pools de nós habilitados, você cria um pool de nós com um priority de Regular por padrão. Para adicionar um pool de nós Spot, especifique Spot como o valor de priority. Para obter mais detalhes sobre como criar um cluster do AKS com vários pools de nós, consulte usar vários pools de nós.

export SPOT_NODEPOOL="spotnodepool"

az aks nodepool add \
    --resource-group $RESOURCE_GROUP \
    --cluster-name $AKS_CLUSTER \
    --name $SPOT_NODEPOOL \
    --priority Spot \
    --eviction-policy Delete \
    --spot-max-price -1 \
    --enable-cluster-autoscaler \
    --min-count 1 \
    --max-count 3 \
    --no-wait

No comando anterior, o priority de Spot torna o pool de nós um pool de nós Spot. O parâmetro eviction-policy está definido como Delete, que é o valor padrão. Quando você define a política de remoção para Delete, os nós no conjunto de dimensionamento subjacente do pool de nós são excluídos quando são removidos.

Você também pode definir a política de despejo como Deallocate, o que significa que os nós no conjunto de escala subjacente são definidos para o estado parado-desalocado após o despejo. Os nós no estado parado-desalocado contam para sua cota de computação e podem causar problemas com o dimensionamento ou atualização do cluster. Os valores priority e eviction-policy só podem ser definidos durante a criação do pool de nós. Esses valores não podem ser atualizados posteriormente.

O comando anterior também habilita o dimensionamento automático de cluster , que recomendamos usar com pools de nós Spot. Com base nas cargas de trabalho em execução no seu cluster, o escalador automático de clusters aumenta e reduz o número de nós. Para pools de nós Spot, o dimensionador automático de cluster aumentará o número de nós após uma remoção, caso mais nós ainda sejam necessários. Se você alterar o número máximo de nós que um pool de nós pode ter, também precisará ajustar o valor maxCount associado ao dimensionador automático do cluster. Se você não usar um autoescalador de cluster, após a remoção, o pool Spot acabará caindo para 0 e exigirá operação manual para receber quaisquer nós Spot adicionais.

Importante

Só agende cargas de trabalho em pools de nós Spot que possam lidar com interrupções, como trabalhos de processamento em lotes e ambientes de teste. Recomendamos que você configure contaminações e tolerâncias no seu pool de nós Spot para garantir que apenas cargas de trabalho que podem lidar com remoções de nós sejam agendadas em um pool de nós Spot. Por exemplo, o comando acima adiciona uma contaminação de kubernetes.azure.com/scalesetpriority=spot:NoSchedule, então somente pods com uma tolerância correspondente são agendados nesse nó.

Verificar o pool de nós Spot

  • Verifique se o pool de nós foi adicionado usando o comando az aks nodepool show e confirmando o scaleSetPriority é Spot.
az aks nodepool show --resource-group $RESOURCE_GROUP --cluster-name $AKS_CLUSTER --name $SPOT_NODEPOOL

Resultados:

{
  "artifactStreamingProfile": null,
  "availabilityZones": null,
  "capacityReservationGroupId": null,
  "count": 3,
  "creationData": null,
  "currentOrchestratorVersion": "1.30.10",
  "eTag": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "enableAutoScaling": true,
  "enableCustomCaTrust": false,
  "enableEncryptionAtHost": false,
  "enableFips": false,
  "enableNodePublicIp": false,
  "enableUltraSsd": false,
  "gatewayProfile": null,
  "gpuInstanceProfile": null,
  "gpuProfile": null,
  "hostGroupId": null,
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/xxxxxxxxxxxxxxxx/providers/Microsoft.ContainerService/managedClusters/xxxxxxxxxxxxxxxx/agentPools/xxxxxxxxxxxx",
  "kubeletConfig": null,
  "kubeletDiskType": "OS",
  "linuxOsConfig": null,
  "maxCount": 3,
  "maxPods": 30,
  "messageOfTheDay": null,
  "minCount": 1,
  "mode": "User",
  "name": "xxxxxxxxxxxx",
  "networkProfile": {
    "allowedHostPorts": null,
    "applicationSecurityGroups": null,
    "nodePublicIpTags": null
  },
  "nodeImageVersion": "AKSUbuntu-2204gen2containerd-xxxxxxxx.xx.x",
  "nodeInitializationTaints": null,
  "nodeLabels": {
    "kubernetes.azure.com/scalesetpriority": "spot"
  },
  "nodePublicIpPrefixId": null,
  "nodeTaints": [
    "kubernetes.azure.com/scalesetpriority=spot:NoSchedule"
  ],
  "orchestratorVersion": "x.xx.xx",
  "osDiskSizeGb": 128,
  "osDiskType": "Managed",
  "osSku": "Ubuntu",
  "osType": "Linux",
  "podIpAllocationMode": null,
  "podSubnetId": null,
  "powerState": {
    "code": "Running"
  },
  "provisioningState": "Creating",
  "proximityPlacementGroupId": null,
  "resourceGroup": "xxxxxxxxxxxxxxxx",
  "scaleDownMode": "Delete",
  "scaleSetEvictionPolicy": "Delete",
  "scaleSetPriority": "Spot",
  "securityProfile": {
    "enableSecureBoot": false,
    "enableVtpm": false,
    "sshAccess": "LocalUser"
  },
  "spotMaxPrice": -1.0,
  "status": null,
  "tags": null,
  "type": "Microsoft.ContainerService/managedClusters/agentPools",
  "typePropertiesType": "VirtualMachineScaleSets",
  "upgradeSettings": {
    "drainTimeoutInMinutes": null,
    "maxSurge": null,
    "maxUnavailable": null,
    "nodeSoakDurationInMinutes": null,
    "undrainableNodeBehavior": null
  },
  "virtualMachineNodesStatus": null,
  "virtualMachinesProfile": null,
  "vmSize": "Standard_DS2_v2",
  "vnetSubnetId": null,
  "windowsProfile": null,
  "workloadRuntime": "OCIContainer"
}

Agende um pod para ser executado no nó Spot

Para agendar um pod para ser executado em um nó Spot, você pode adicionar uma tolerância e afinidade de nó que corresponda à contaminação aplicada ao seu nó Spot.

O exemplo a seguir mostra uma parte de um arquivo YAML que define uma tolerância correspondente ao kubernetes.azure.com/scalesetpriority=spot:NoSchedule taint e uma afinidade de nó correspondente ao kubernetes.azure.com/scalesetpriority=spot rótulo usado na etapa anterior com as regras de afinidade requiredDuringSchedulingIgnoredDuringExecution e preferredDuringSchedulingIgnoredDuringExecution nó:

spec:
  containers:
  - name: spot-example
  tolerations:
  - key: "kubernetes.azure.com/scalesetpriority"
    operator: "Equal"
    value: "spot"
    effect: "NoSchedule"
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: "kubernetes.azure.com/scalesetpriority"
            operator: In
            values:
            - "spot"
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value

Quando você implanta um pod com essa tolerância e afinidade de nó, o Kubernetes agenda com sucesso o pod nos nós com a contaminação e o rótulo aplicados. Neste exemplo, as seguintes regras se aplicam:

  • O nó deve ter um rótulo com a chave kubernetes.azure.com/scalesetpriority, e o valor desse rótulo deve ser spot.
  • O nó de preferência tem um rótulo com a chave another-node-label-key e o valor desse rótulo deve ser another-node-label-value.

Para obter mais informações, consulte Atribuir pods a nós.

Atualizar um pool de nós Spot

Quando você atualiza um pool de nós Spot, o AKS emite internamente um cordão e um aviso de despejo, mas nenhuma drenagem é aplicada. Não há nós de surto disponíveis para atualizações do pool de nós Spot. Fora essas alterações, o comportamento ao atualizar pools de nós Spot é consistente com o de outros tipos de pools de nós.

Para obter mais informações sobre atualização, confira Atualizar um cluster do AKS.

Preço máximo para um pool de Spot

O preço das instâncias spot é variável, dependendo da região e do SKU. Para obter mais informações, confira as informações de preços do Linux e do Windows.

Com preços variáveis, você tem a opção de definir um preço máximo, em dólares americanos (USD), usando até cinco casas decimais. Por exemplo, o valor 0,98765 seria um preço máximo de USD 0,98765 por hora. Se você definir o preço máximo como -1, a instância não será removida com base no preço. Enquanto houver capacidade e cota disponíveis, o preço da instância será o menor entre o preço atual de uma instância Spot e o de uma instância padrão.

Próximas etapas

Neste artigo, você aprendeu a adicionar um pool de nós Spot a um cluster do AKS. Para obter mais informações sobre como controlar pods em pools de nós, veja Melhores práticas para recursos avançados do planejador no AKS.