Solucionar problemas de grupos de nodos de GKE Standard


En esta página se explica cómo resolver problemas con los grupos de nodos del modo Estándar de GKE.

Problemas al crear grupos de nodos

En esta sección se enumeran los problemas que pueden surgir al crear grupos de nodos en clústeres estándar y se ofrecen sugerencias para solucionarlos.

Problema: no se puede crear un grupo de nodos por falta de recursos

El siguiente problema se produce cuando crea un pool de nodos con hardware específico en una zona Google Cloud que no tiene suficiente hardware disponible para cumplir sus requisitos.

Para comprobar que no se ha podido crear el pool de nodos porque una zona no tenía suficientes recursos, consulta los registros para ver si hay mensajes de error relevantes.

  1. Ve a Explorador de registros en la Google Cloud consola:

    Ir a Explorador de registros

  2. En el campo Consulta, especifica la siguiente consulta:

    log_id(cloudaudit.googleapis.com/activity)
    resource.labels.cluster_name="CLUSTER_NAME"
    protoPayload.status.message:("ZONE_RESOURCE_POOL_EXHAUSTED" OR "does not have enough resources available to fulfill the request" OR "resource pool exhausted" OR "does not exist in zone")
    

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

  3. Haz clic en Realizar una consulta.

Es posible que aparezca uno de los siguientes mensajes de error:

  • resource pool exhausted
  • The zone does not have enough resources available to fulfill the request. Try a different zone, or try again later.
  • ZONE_RESOURCE_POOL_EXHAUSTED
  • ZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILS
  • Machine type with name 'MACHINE_NAME' does not exist in zone 'ZONE_NAME'

Para solucionar este problema, prueba las siguientes sugerencias:

  • Asegúrate de que la región o zona seleccionada tenga el hardware específico que necesitas. Google Cloud Consulta la tabla de disponibilidad de Compute Engine para comprobar si determinadas zonas admiten hardware específico. Elige otraGoogle Cloud región o zona para tus nodos que pueda tener una mejor disponibilidad del hardware que necesitas.
  • Crea el grupo de nodos con tipos de máquinas más pequeños. Aumenta el número de nodos del grupo de nodos para que la capacidad de computación total siga siendo la misma.
  • Usa la reserva de capacidad de Compute Engine para reservar los recursos con antelación.
  • Usa el aprovisionamiento con el mejor esfuerzo posible, que se describe en la siguiente sección, para crear correctamente el grupo de nodos si puede aprovisionar al menos el número mínimo de nodos especificado del número solicitado.

Aprovisionamiento con el mejor esfuerzo posible

En el caso de determinado hardware, puedes usar el aprovisionamiento con el mejor esfuerzo posible, que indica a GKE que cree correctamente el grupo de nodos si puede aprovisionar al menos un número mínimo de nodos especificado. GKE sigue intentando aprovisionar los nodos restantes para satisfacer la solicitud original a lo largo del tiempo. Para indicar a GKE que use el aprovisionamiento con el mejor esfuerzo posible, usa el siguiente comando:

gcloud container node-pools create NODE_POOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=CONTROL_PLANE_LOCATION \
    --node-locations=ZONE1,ZONE2,... \
    --machine-type=MACHINE_TYPE
    --best-effort-provision \
    --min-provision-nodes=MINIMUM_NODES

Haz los cambios siguientes:

  • NODE_POOL_NAME: el nombre del nuevo grupo de nodos.
  • CONTROL_PLANE_LOCATION: la ubicación de Compute Engine del plano de control de tu clúster. Proporciona una región para los clústeres regionales o una zona para los clústeres zonales.
  • ZONE1,ZONE2,...: las zonas de Compute Engine de los nodos. Estas zonas deben admitir el hardware seleccionado.
  • MACHINE_TYPE: el tipo de máquina de Compute Engine para los nodos. Por ejemplo, a2-highgpu-1g.
  • MINIMUM_NODES: el número mínimo de nodos que GKE debe aprovisionar para crear correctamente el grupo de nodos. Si se omite, el valor predeterminado es 1.

Por ejemplo, supongamos que necesitas 10 nodos con GPUs NVIDIA A100 de 40 GB conectadas en us-central1-c. Según la tabla de disponibilidad de regiones y zonas de GPU, esta zona admite GPUs A100. Para evitar que se produzca un error al crear un pool de nodos si no hay disponibles 10 máquinas con GPU, usa el aprovisionamiento con el mejor esfuerzo posible.

gcloud container node-pools create a100-nodes \
    --cluster=ml-cluster \
    --location=us-central1 \
    --node-locations=us-central1-c \
    --num-nodes=10 \
    --machine-type=a2-highgpu-1g \
    --accelerator=type=nvidia-tesla-a100,count=1 \
    --best-effort-provision \
    --min-provision-nodes=5

GKE crea el grupo de nodos aunque solo haya cinco GPUs disponibles en us-central1-c. Con el tiempo, GKE intenta aprovisionar más nodos hasta que haya 10 nodos en el grupo de nodos.

Error: la instancia no contiene metadatos de "instance-template"

Es posible que vea el siguiente error en el estado de un grupo de nodos que no se puede actualizar, escalar o reparar automáticamente:

Instance INSTANCE_NAME does not contain 'instance-template' metadata

Este error indica que los metadatos de las instancias de VM asignadas por GKE se han dañado. Esto suele ocurrir cuando una automatización o una secuencia de comandos creadas por el usuario intentan añadir metadatos de instancia nuevos (como block-project-ssh-keys) y, en lugar de añadir o actualizar valores, también eliminan los metadatos que ya había. Puedes consultar información sobre los metadatos de instancias de VM en el artículo Configurar metadatos personalizados.

Si se elimina alguno de los valores de metadatos críticos (entre otros, instance-template, kube-labels, kubelet-config, kubeconfig, cluster-name, configure-sh y cluster-uid), el nodo o todo el grupo de nodos podría quedar en un estado inestable, ya que estos valores son cruciales para las operaciones de GKE.

Si los metadatos de la instancia se han dañado, te recomendamos que los recuperes volviendo a crear el grupo de nodos que contiene las instancias de VM dañadas. Deberás añadir un grupo de nodos a tu clúster y aumentar el número de nodos del nuevo grupo de nodos, mientras acordonas y eliminas nodos de otro. Consulta las instrucciones para migrar cargas de trabajo entre grupos de nodos.

Para saber quién y cuándo se editaron los metadatos de la instancia, puedes consultar la información de registro de auditoría de Compute Engine o buscar registros con el Explorador de registros mediante una consulta de búsqueda similar a la siguiente:

resource.type="gce_instance_group_manager"
protoPayload.methodName="v1.compute.instanceGroupManagers.setInstanceTemplate"

En los registros, puedes encontrar la dirección IP y el user-agent del origen de la solicitud. Por ejemplo:

requestMetadata: {
  callerIp: "REDACTED"
  callerSuppliedUserAgent: "google-api-go-client/0.5 GoogleContainerEngine/v1"
}

Migrar cargas de trabajo entre grupos de nodos

Sigue estas instrucciones para migrar cargas de trabajo de un grupo de nodos a otro. Si quieres cambiar los atributos de la máquina de los nodos de tu grupo de nodos, consulta Escalar verticalmente cambiando los atributos de la máquina de los nodos.

Información sobre cómo migrar pods a un nuevo grupo de nodos

Para migrar pods a un nuevo grupo de nodos, debes hacer lo siguiente:

  1. Aísla los nodos del grupo de nodos: esta operación marca los nodos del grupo de nodos como no programables. Kubernetes dejará de programar nuevos pods en estos nodos cuando los marques como no programables.

  2. Drena los nodos del grupo de nodos: esta operación expulsa las cargas de trabajo que se ejecutan en los nodos del grupo de nodos de forma correcta.

Estos pasos, que se realizan de forma individual en cada nodo, provocan que los pods que se ejecutan en tu grupo de nodos se cierren correctamente. Kubernetes los vuelve a programar en otros nodos disponibles.

Para asegurarte de que Kubernetes finaliza tus aplicaciones correctamente, tus contenedores deben gestionar la señal SIGTERM. Usa este método para cerrar las conexiones activas con los clientes y confirmar o revertir las transacciones de la base de datos de forma correcta. En el archivo de manifiesto de tu pod, puedes usar el campo spec.terminationGracePeriodSeconds para especificar cuánto tiempo debe esperar Kubernetes antes de detener los contenedores del pod. El tiempo predeterminado es de 30 segundos. Puedes consultar más información sobre la finalización de pods en la documentación de Kubernetes.

Puedes acordonar y drenar nodos con los comandos kubectl cordon y kubectl drain.

Crear un grupo de nodos y migrar cargas de trabajo

Para migrar tus cargas de trabajo a un nuevo grupo de nodos, crea el grupo de nodos y, a continuación, aísla y vacía los nodos del grupo de nodos actual:

  1. Añade un grupo de nodos a tu clúster.

    Para comprobar que se ha creado el nuevo grupo de nodos, ejecuta el siguiente comando:

    gcloud container node-pools list --cluster CLUSTER_NAME
    
    .
  2. Para inhabilitar el autoescalado en el grupo de nodos, si está habilitado, ejecuta el siguiente comando:

    gcloud container clusters update CLUSTER_NAME
        --location=CONTROL_PLANE_LOCATION \
        --no-enable-autoscaling \
        --node-pool=EXISTING_NODE_POOL_NAME
    

    Sustituye CONTROL_PLANE_LOCATION por la ubicación de Compute Engine del plano de control de tu clúster. Proporciona una región para los clústeres regionales o una zona para los clústeres zonales.

  3. Ejecuta el siguiente comando para ver en qué nodo se están ejecutando los pods (consulta la columna NODE):

    kubectl get pods -o=wide
    
  4. Obtén una lista de los nodos del grupo de nodos, sustituyendo EXISTING_NODE_POOL_NAME por el nombre:

    kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME
    
  5. Ejecuta el comando kubectl cordon NODE (sustituye NODE por los nombres del comando anterior). El siguiente comando de shell itera cada nodo del grupo de nodos actual y los marca como no programables:

    for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do
      kubectl cordon "$node";
    done
    
  6. Opcionalmente, actualiza las cargas de trabajo que se ejecutan en el grupo de nodos para añadir un nodeSelector para la etiqueta cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME, donde NEW_NODE_POOL_NAME es el nombre del nuevo grupo de nodos. De esta forma, GKE colocará esas cargas de trabajo en los nodos del nuevo grupo de nodos.

  7. Drena cada nodo desalojando todos los pods con un periodo de finalización gradual asignado de 10 segundos:

    for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do
      kubectl drain --force --ignore-daemonsets --delete-emptydir-data --grace-period=GRACEFUL_TERMINATION_SECONDS  "$node";
    done
    

    Sustituye GRACEFUL_TERMINATION_PERIOD_SECONDS por el tiempo necesario para la finalización correcta.

  8. Confirma que los nodos del grupo de nodos tienen el estado SchedulingDisabled en la lista de nodos ejecutando el siguiente comando:

    kubectl get nodes
    

    Además, deberías ver que los pods ahora se ejecutan en los nodos del nuevo grupo de nodos:

    kubectl get pods -o=wide
    
  9. Elimina el grupo de nodos si no lo necesitas:

    gcloud container node-pools delete default-pool --cluster CLUSTER_NAME
    

Siguientes pasos