Usar máquinas virtuales interrumpibles para ejecutar cargas de trabajo tolerantes a fallos

En esta página se muestra cómo usar máquinas virtuales de instancia efímera en Google Kubernetes Engine (GKE).

Información general

Las máquinas virtuales interrumpibles son instancias de máquina virtual de Compute Engine que tienen un precio más bajo que las máquinas virtuales estándar y no ofrecen ninguna garantía de disponibilidad. Las VMs preemptibles ofrecen una funcionalidad similar a las VMs de instancia esporádica, pero solo duran hasta 24 horas después de su creación.

En algunos casos, una máquina virtual interrumpible puede durar más de 24 horas. Esto puede ocurrir cuando la nueva instancia de Compute Engine se inicia demasiado rápido y Kubernetes no reconoce que se ha creado otra VM de Compute Engine. La instancia de Compute Engine subyacente tendrá una duración máxima de 24 horas y seguirá el comportamiento esperado de las VMs interrumpibles.

Comparación con las máquinas virtuales de acceso puntual

Las máquinas virtuales interrumpibles tienen muchas similitudes con las máquinas virtuales de acceso puntual, entre las que se incluyen las siguientes:

  • Finaliza cuando Compute Engine necesita los recursos para ejecutar VMs estándar.
  • Útil para ejecutar cargas de trabajo sin estado, por lotes o tolerantes a fallos.
  • Precios más bajos que los de las máquinas virtuales estándar.
  • En los clústeres que ejecutan la versión 1.20 de GKE o una posterior, la opción Cierre de nodos controlado está habilitada de forma predeterminada.
  • Funciona con el autoescalador de clústeres y el aprovisionamiento automático de nodos.

A diferencia de las VMs de acceso puntual, que no tienen un tiempo de caducidad máximo, las VMs interrumpibles solo duran hasta 24 horas después de su creación.

Puedes habilitar las máquinas virtuales interrumpibles en clústeres y grupos de nodos nuevos, usar nodeSelector o la afinidad de nodos para controlar la programación, y usar intolerancias y tolerancias para evitar problemas con las cargas de trabajo del sistema cuando se interrumpan los nodos.

Finalización y cierre ordenado de VMs interrumpibles

Cuando Compute Engine necesita recuperar los recursos utilizados por las VMs de instancia efímera, se envía un aviso de desalojo a GKE. Las VMs preemptivas se terminan 30 segundos después de recibir un aviso de finalización.

De forma predeterminada, los clústeres usan el apagado suave de nodos. El kubelet detecta el aviso de finalización y finaliza correctamente los pods que se están ejecutando en el nodo. Si los pods forman parte de una carga de trabajo gestionada, como un deployment, el controlador crea y programa nuevos pods para sustituir los pods finalizados.

De la mejor forma posible, el kubelet concede un periodo de finalización gradual de 15 segundos para los pods que no son del sistema, tras lo cual los pods del sistema (con las clases de prioridad system-cluster-critical o system-node-critical) tienen 15 segundos para finalizar gradualmente. Durante la finalización correcta de un nodo, el kubelet actualiza el estado de los pods y les asigna una fase Failed y un motivo Terminated a los pods finalizados.

La VM se apaga 30 segundos después de que se envíe la notificación de finalización, aunque especifiques un valor superior a 15 segundos en el campo terminationGracePeriodSeconds del manifiesto de tu pod.

Cuando el número de pods finalizados alcanza un umbral de 1000 en clústeres con menos de 100 nodos o de 5000 en clústeres con 100 nodos o más, la recogida de elementos no utilizados limpia los pods.

También puedes eliminar los pods finalizados manualmente con los siguientes 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

Modificaciones en el comportamiento de Kubernetes

Si usas máquinas virtuales interrumpibles en GKE, se modifican las garantías que proporciona Kubernetes PodDisruptionBudgets. La recuperación de las máquinas virtuales interrumpibles es involuntaria y no está cubierta por las garantías de PodDisruptionBudgets. Es posible que la indisponibilidad sea mayor que la que hayas configurado en PodDisruptionBudget.

Limitaciones

  • La función de cierre suave de nodos de kubelet solo está habilitada en clústeres que ejecutan GKE 1.20 y versiones posteriores. En las versiones de GKE anteriores a la 1.20, puedes usar el gestor de eventos de finalización de nodos de Kubernetes en GCP para finalizar correctamente tus pods cuando se finalicen las VMs no garantizadas.
  • Las máquinas virtuales interrumpibles no admiten grupos de nodos de Windows Server.
  • En GKE, no puedes cambiar la duración del periodo de gracia para el cierre de nodos. Los campos de configuración shutdownGracePeriod y shutdownGracePeriodCriticalPods de kubelet son inmutables.

Crear un clúster o un grupo de nodos con VMs no garantizadas

Puedes usar la CLI de Google Cloud para crear un clúster o un grupo de nodos con VMs preemptivas.

Si deseas crear un clúster con máquinas virtuales no garantizadas, ejecuta el siguiente comando:

gcloud container clusters create CLUSTER_NAME \
    --preemptible

Sustituye CLUSTER_NAME por el nombre de tu nuevo clúster.

Para crear un grupo de nodos con VMs interrumpibles, ejecuta el siguiente comando:

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

Sustituye POOL_NAME por el nombre del nuevo grupo de nodos.

Usar nodeSelector para programar pods en máquinas virtuales interrumpibles

GKE añade las etiquetas cloud.google.com/gke-preemptible=true y cloud.google.com/gke-provisioning=preemptible (para los nodos que ejecutan la versión 1.25.5-gke.2500 de GKE o una posterior) a los nodos que usan VMs preemptivas. Puedes usar un nodeSelector en tus implementaciones para indicar a GKE que programe pods en máquinas virtuales interrumpibles.

Por ejemplo, los siguientes filtros de implementaciones de máquinas virtuales interrumpibles usan la 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"

Usar taints de nodos para máquinas virtuales interrumpibles

Puedes contaminar los nodos que usen máquinas virtuales interrumpibles para que GKE solo pueda colocar pods con la tolerancia correspondiente en esos nodos.

Para añadir un taint de nodo a un grupo de nodos que utilice máquinas virtuales interrumpibles, usa la marca --node-taints al crear el grupo de nodos, como en el siguiente comando:

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

De esta manera, solo los pods que toleran la intolerancia de nodo se programan en el nodo.

Para añadir la tolerancia pertinente a tus pods, modifica tus implementaciones y añade lo siguiente a la especificación de tu pod:

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

Taints de nodos para máquinas virtuales interrumpibles con GPU

Las VMs interrumpibles admiten el uso de GPUs. Debes crear al menos otro grupo de nodos en tu clúster que no use máquinas virtuales interrumpibles antes de añadir un grupo de nodos con GPU que sí las use. Tener un grupo de nodos estándar asegura que GKE pueda colocar de forma segura componentes del sistema, como DNS.

Si creas un clúster con grupos de nodos de GPU que usen VMs interrumpibles o si añades un grupo de nodos de GPU que use VMs interrumpibles a un clúster que aún no tenga un grupo de nodos estándar, GKE no añadirá automáticamente el taint nvidia.com/gpu=present:NoSchedule a los nodos. GKE puede programar pods del sistema en las máquinas virtuales interrumpibles, lo que puede provocar interrupciones. Este comportamiento también aumenta el consumo de recursos, ya que los nodos de GPU son más caros que los nodos que no tienen GPU.

Siguientes pasos