Use VMs preemptivas para executar cargas de trabalho com tolerância a falhas


Esta página mostra como usar VMs preemptíveis no Google Kubernetes Engine (GKE).

Vista geral

As VMs preemptivas são instâncias de VM do Compute Engine com um preço inferior ao das VMs padrão e não oferecem garantia de disponibilidade. As VMs preemptivas oferecem uma funcionalidade semelhante às VMs de instância temporária, mas duram apenas até 24 horas após a criação.

Em alguns casos, uma VM preemptível pode durar mais de 24 horas. Isto pode ocorrer quando a nova instância do Compute Engine é iniciada demasiado rapidamente e o Kubernetes não reconhece que foi criada uma VM do Compute Engine diferente. A instância do Compute Engine subjacente tem uma duração máxima de 24 horas e segue o comportamento esperado da VM preemptível.

Comparação com VMs do Spot

As VMs preemptivas partilham muitas semelhanças com as VMs do Spot, incluindo o seguinte:

Ao contrário das VMs de spot, que não têm um tempo de expiração máximo, as VMs preemptíveis duram apenas até 24 horas após a criação.

Pode ativar as VMs preemptivas em novos clusters e node pools, usar a afinidade de nós ou de nós para controlar o agendamento e usar restrições e tolerâncias para evitar problemas com cargas de trabalho do sistema quando os nós são preemptivos.nodeSelector

Encerramento e encerramento controlado de VMs preemptivas

Quando o Compute Engine precisa de reaver os recursos usados pelas VMs preemptíveis, é enviado um aviso de preemptibilidade para o GKE. As VMs preemptíveis terminam 30 segundos após receberem um aviso de encerramento.

Por predefinição, os clusters usam o graceful node shutdown. O kubelet repara no aviso de rescisão e rescinde graciosamente os pods que estão a ser executados no nó. Se os pods fizerem parte de uma carga de trabalho gerida, como uma implementação, o controlador cria e agenda novos pods para substituir os pods terminados.

Com base no melhor esforço, o kubelet concede um período de encerramento elegante de 15 segundos para os pods não pertencentes ao sistema, após o qual os pods do sistema (com as priorityClasses system-cluster-critical ou system-node-critical) têm 15 segundos para terminar elegantemente. Durante o encerramento elegante de nós, o kubelet atualiza o estado dos pods e atribui uma fase Failed e um motivo Terminated aos pods encerrados.

A VM é encerrada 30 segundos após o envio do aviso de rescisão, mesmo que especifique um valor superior a 15 segundos no campo terminationGracePeriodSeconds do manifesto do agrupamento.

Quando o número de pods terminados atinge um limite de 1000 para clusters com menos de 100 nós ou 5000 para clusters com 100 nós ou mais, a recolha de lixo limpa os pods.

Também pode eliminar manualmente os pods terminados através dos seguintes comandos:

  kubectl get pods --all-namespaces | grep -i NodeShutdown | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n
  kubectl get pods --all-namespaces | grep -i Terminated | awk '{print $1, $2}' | xargs -n2 kubectl delete pod -n

Modificações ao comportamento do Kubernetes

A utilização de VMs preemptivas no GKE modifica as garantias fornecidas pelo Kubernetes PodDisruptionBudgets. A recuperação de VMs preemptíveis é involuntária e não está coberta pelas garantias de PodDisruptionBudgets. Pode ocorrer uma indisponibilidade superior à PodDisruptionBudget configurada.

Limitações

Crie um cluster ou um node pool com VMs preemptíveis

Pode usar a CLI Google Cloud para criar um cluster ou um conjunto de nós com VMs preemptivas.

Para criar um cluster com VMs preemptivas, execute o seguinte comando:

gcloud container clusters create CLUSTER_NAME \
    --preemptible

Substitua CLUSTER_NAME pelo nome do novo cluster.

Para criar um node pool com VMs preemptivas, execute o seguinte comando:

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --preemptible

Substitua POOL_NAME pelo nome do novo conjunto de nós.

Use nodeSelector para agendar pods em VMs preemptivas

O GKE adiciona as etiquetas cloud.google.com/gke-preemptible=true e cloud.google.com/gke-provisioning=preemptible (para nós que executam a versão 1.25.5-gke.2500 ou posterior do GKE) aos nós que usam VMs preemptivas. Pode usar um nodeSelector nas suas implementações para indicar ao GKE que agende pods em VMs preemptivas.

Por exemplo, os seguintes filtros de implementação para VMs preemptíveis que usam a etiqueta cloud.google.com/gke-preemptible:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-app
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-app
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
        resources:
          requests:
            cpu: 200m
      nodeSelector:
        cloud.google.com/gke-preemptible: "true"

Use taints de nós para VMs preemptivas

Pode contaminar nós que usam VMs preemptivas para que o GKE só possa colocar pods com a tolerância correspondente nesses nós.

Para adicionar uma restrição de nó a um node pool que usa VMs preemptivas, use a flag --node-taints quando criar o node pool, semelhante ao seguinte comando:

gcloud container node-pools create POOL2_NAME \
    --cluster=CLUSTER_NAME \
    --node-taints=cloud.google.com/gke-preemptible="true":NoSchedule

Agora, apenas os pods que toleram a rejeição do nó são agendados para o nó.

Para adicionar a tolerância relevante aos seus pods, modifique as implementações e adicione o seguinte à especificação do pod:

tolerations:
- key: cloud.google.com/gke-preemptible
  operator: Equal
  value: "true"
  effect: NoSchedule

Taints de nós para VMs preemptivas de GPU

As VMs preemptíveis suportam a utilização de GPUs. Deve criar, pelo menos, outro conjunto de nós no cluster que não use VMs preemptivas antes de adicionar um conjunto de nós de GPU que use VMs preemptivas. Ter um conjunto de nós padrão garante que o GKE pode colocar em segurança componentes do sistema, como o DNS.

Se criar um novo cluster com pools de nós de GPU que usam VMs preemptivas ou se adicionar um novo pool de nós de GPU que usa VMs preemptivas a um cluster que ainda não tem um pool de nós padrão, o GKE não adiciona automaticamente a restrição nvidia.com/gpu=present:NoSchedule aos nós. O GKE pode agendar pods do sistema nas VMs preemptíveis, o que pode levar a interrupções. Este comportamento também aumenta o consumo de recursos, porque os nós de GPU são mais caros do que os nós sem GPU.

O que se segue?