Solucionar problemas de clústeres de Autopilot


En esta página se muestra cómo resolver problemas con los clústeres Autopilot de Google Kubernetes Engine (GKE).

Problemas del clúster

No se puede crear un clúster: no hay nodos registrados

El siguiente problema se produce cuando intentas crear un clúster de Autopilot con una cuenta de servicio de gestión de identidades y accesos que está inhabilitada o no tiene los permisos necesarios. No se puede crear el clúster y se muestra el siguiente mensaje de error:

All cluster resources were brought up, but: only 0 nodes out of 2 have registered.

Para solucionar el problema, sigue estos pasos:

  1. Comprueba si la cuenta de servicio predeterminada de Compute Engine o la cuenta de servicio de IAM personalizada que quieres usar están inhabilitadas:

    gcloud iam service-accounts describe SERVICE_ACCOUNT
    

    Sustituye SERVICE_ACCOUNT por la dirección de correo de la cuenta de servicio, como my-iam-account@my-first-project.iam.gserviceaccount.com.

    Si la cuenta de servicio está inhabilitada, el resultado será similar al siguiente:

    disabled: true
    displayName: my-service-account
    email: my-service-account@my-project.iam.gserviceaccount.com
    ...
    
  2. Si la cuenta de servicio está inhabilitada, habilítala:

    gcloud iam service-accounts enable SERVICE_ACCOUNT
    

Si la cuenta de servicio está habilitada y el error persiste, concédele los permisos mínimos necesarios para GKE:

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member "serviceAccount:SERVICE_ACCOUNT" \
    --role roles/container.defaultNodeServiceAccount

El espacio de nombres se queda en el estado Terminating cuando el clúster tiene 0 nodos

El siguiente problema se produce cuando eliminas un espacio de nombres en un clúster después de que el clúster se reduzca a cero nodos. El componente metrics-server no puede aceptar la solicitud de eliminación del espacio de nombres porque tiene cero réplicas.

Para diagnosticar este problema, ejecuta el siguiente comando:

kubectl describe ns/NAMESPACE_NAME

Sustituye NAMESPACE_NAME por el nombre del espacio de nombres.

El resultado es el siguiente:

Discovery failed for some groups, 1 failing: unable to retrieve the complete
list of server APIs: metrics.k8s.io/v1beta1: the server is currently unable to
handle the request

Para solucionar este problema, aumenta la escala de cualquier carga de trabajo para que GKE cree un nuevo nodo. Cuando el nodo esté listo, la solicitud de eliminación del espacio de nombres se completará automáticamente. Una vez que GKE haya eliminado el espacio de nombres, reduce la carga de trabajo.

Problemas de escalado

No se ha podido aumentar la escala del nodo: el pod corre el riesgo de no programarse

El siguiente problema se produce cuando el registro del puerto serie está inhabilitado en tu proyecto deGoogle Cloud . Los clústeres de Autopilot de GKE requieren el registro del puerto serie para depurar de forma eficaz los problemas de los nodos. Si el registro del puerto serie está inhabilitado, Autopilot no podrá aprovisionar nodos para ejecutar tus cargas de trabajo.

El mensaje de error de tu registro de eventos de Kubernetes es similar al siguiente:

LAST SEEN   TYPE      REASON          OBJECT                          MESSAGE
12s         Warning   FailedScaleUp   pod/pod-test-5b97f7c978-h9lvl   Node scale up in zones associated with this pod failed: Internal error. Pod is at risk of not being scheduled

El registro del puerto serie puede inhabilitarse a nivel de organización mediante una política de organización que aplique la restricción compute.disableSerialPortLogging. El registro del puerto serie también se puede inhabilitar a nivel de proyecto o de instancia de máquina virtual (VM).

Para solucionar este problema, sigue estos pasos:

  1. Pide al administrador de políticas de tu organización que elimine la restricción compute.disableSerialPortLogging del proyecto que contiene tu clúster Autopilot. Google Cloud
  2. Si no tienes una política de organización que aplique esta restricción, prueba a habilitar el registro del puerto serie en los metadatos de tu proyecto. Esta acción requiere el permiso de gestión de identidades y accesos compute.projects.setCommonInstanceMetadata.

No se ha podido aumentar la escala del nodo: GCE se ha quedado sin recursos

El problema siguiente se produce cuando tus cargas de trabajo solicitan más recursos de los que hay disponibles en esa región o zona de Compute Engine. Es posible que tus pods permanezcan en el estado Pending.

  • Comprueba los eventos de tu Pod:

    kubectl events --for='pod/POD_NAME' --types=Warning
    

    Sustituye RESOURCE_NAME por el nombre del recurso de Kubernetes pendiente. Por ejemplo, pod/example-pod.

    El resultado debería ser similar al siguiente:

    LAST SEEN         TYPE            REASON                  OBJECT                   Message
    19m               Warning         FailedScheduling        pod/example-pod          gke.io/optimize-utilization-scheduler  0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
    14m               Warning         FailedScheduling        pod/example-pod          gke.io/optimize-utilization-scheduler  0/2 nodes are available: 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.
    12m (x2 over 18m) Warning         FailedScaleUp           cluster-autoscaler       Node scale up in zones us-central1-f associated with this pod failed: GCE out of resources. Pod is at risk of not being scheduled.
    34s (x3 over 17m) Warning         FailedScaleUp           cluster-autoscaler       Node scale up in zones us-central1-b associated with this pod failed: GCE out of resources. Pod is at risk of not being scheduled.
    

Para solucionar este problema, prueba lo siguiente:

  • Despliega el pod en otra región o zona. Si tu pod tiene una restricción zonal, como un selector de topología, elimina la restricción si puedes. Para obtener instrucciones, consulta Colocar pods de GKE en zonas específicas.
  • Crea un clúster en otra región y vuelve a intentar el despliegue.
  • Prueba a usar otra clase de cálculo. Es más probable que las clases de cálculo respaldadas por tipos de máquinas de Compute Engine más pequeños tengan recursos disponibles. Por ejemplo, el tipo de máquina predeterminado de Autopilot tiene la mayor disponibilidad. Para ver una lista de clases de computación y los tipos de máquinas correspondientes, consulta Cuándo usar clases de computación específicas.
  • Si ejecutas cargas de trabajo de GPU, es posible que la GPU solicitada no esté disponible en la ubicación de tu nodo. Prueba a desplegar tu carga de trabajo en otra ubicación o a solicitar otro tipo de GPU.

Para evitar problemas de escalado causados por la disponibilidad de recursos en el futuro, considera las siguientes opciones:

Los nodos no se pueden ampliar: se han superado los recursos zonales de los pods

El siguiente problema se produce cuando Autopilot no aprovisiona nodos nuevos para un pod en una zona específica porque un nodo nuevo infringiría los límites de recursos.

El mensaje de error de tus registros es similar al siguiente:

    "napFailureReasons": [
            {
              "messageId": "no.scale.up.nap.pod.zonal.resources.exceeded",
              ...

Este error hace referencia a un evento noScaleUp en el que el aprovisionamiento automático de nodos no aprovisionó ningún grupo de nodos para el pod en la zona.

Si aparece este error, confirma lo siguiente:

Problemas con las cargas de trabajo

Cargas de trabajo bloqueadas con un error de almacenamiento efímero

GKE no creará pods si las solicitudes de almacenamiento efímero de los pods superan el máximo de 10 GiB de Autopilot en la versión 1.28.6-gke.1317000 de GKE y versiones posteriores.

Para diagnosticar este problema, describe el controlador de carga de trabajo, como la implementación o el trabajo:

kubectl describe CONTROLLER_TYPE/CONTROLLER_NAME

Haz los cambios siguientes:

  • CONTROLLER_TYPE: el tipo de controlador de carga de trabajo, como replicaset o daemonset. Para ver una lista de los tipos de controladores, consulta Gestión de cargas de trabajo.
  • CONTROLLER_NAME: el nombre de la carga de trabajo bloqueada.

Si el pod no se crea porque la solicitud de almacenamiento efímero supera el máximo, el resultado será similar al siguiente:

# lines omitted for clarity

Events:

{"[denied by autogke-pod-limit-constraints]":["Max ephemeral-storage requested by init containers for workload '' is higher than the Autopilot maximum of '10Gi'.","Total ephemeral-storage requested by containers for workload '' is higher than the Autopilot maximum of '10Gi'."]}

Para solucionar este problema, actualice sus solicitudes de almacenamiento efímero de forma que el almacenamiento efímero total solicitado por los contenedores de cargas de trabajo y por los contenedores que insertan webhooks sea inferior o igual al máximo permitido. Para obtener más información sobre el máximo, consulta Solicitudes de recursos en Autopilot para la configuración de la carga de trabajo.

Los pods se quedan en estado Pending

Un pod puede quedarse atascado en el estado Pending si seleccionas un nodo específico para que lo use, pero la suma de las solicitudes de recursos del pod y de los DaemonSets que deben ejecutarse en el nodo supera la capacidad máxima asignable del nodo. Esto puede provocar que tu Pod tenga el estado Pending y siga sin programar.

Para evitar este problema, evalúa los tamaños de tus cargas de trabajo implementadas para asegurarte de que se encuentran dentro de los máximos de solicitudes de recursos admitidos para Autopilot.

También puedes probar a programar tus DaemonSets antes de programar tus pods de carga de trabajo habituales.

Rendimiento de carga de trabajo poco fiable en un nodo específico

En la versión 1.24 de GKE y posteriores, si tus cargas de trabajo en un nodo específico sufren interrupciones, fallos u otros comportamientos poco fiables de forma constante, puedes informar a GKE sobre el nodo problemático acordonándolo con el siguiente comando:

kubectl drain NODE_NAME --ignore-daemonsets

Sustituye NODE_NAME por el nombre del nodo que da problemas. Puedes encontrar el nombre del nodo ejecutando kubectl get nodes.

GKE hace lo siguiente:

  • Expulsa las cargas de trabajo del nodo y detiene la programación de cargas de trabajo en ese nodo.
  • Vuelve a crear automáticamente en otros nodos las cargas de trabajo desalojadas que estén gestionadas por un controlador, como un Deployment o un StatefulSet.
  • Finaliza las cargas de trabajo que queden en el nodo y lo repara o lo vuelve a crear con el tiempo.
  • Si usas Autopilot, GKE cierra y sustituye el nodo inmediatamente, e ignora cualquier PodDisruptionBudget configurado.

Los pods tardan más de lo esperado en programarse en clústeres vacíos

Este evento se produce cuando despliega una carga de trabajo en un clúster de Autopilot que no tiene otras cargas de trabajo. Los clústeres de Autopilot empiezan con cero nodos utilizables y se escalan a cero nodos si el clúster está vacío para evitar que haya recursos de computación sin utilizar en el clúster. Si despliegas una carga de trabajo en un clúster que tiene cero nodos, se activará un evento de escalado vertical.

Si esto ocurre, Autopilot funciona correctamente y no es necesario que hagas nada. Tu carga de trabajo se implementará correctamente después de que se inicien los nuevos nodos.

Comprueba si tus pods están esperando nuevos nodos:

  1. Describe el Pod pendiente:

    kubectl describe pod POD_NAME
    

    Sustituye POD_NAME por el nombre del pod pendiente.

  2. Consulta la sección Events del resultado. Si el pod está esperando nuevos nodos, el resultado será similar al siguiente:

    Events:
      Type     Reason            Age   From                                   Message
      ----     ------            ----  ----                                   -------
      Warning  FailedScheduling  11s   gke.io/optimize-utilization-scheduler  no nodes available to schedule pods
      Normal   TriggeredScaleUp  4s    cluster-autoscaler                     pod triggered scale-up: [{https://www.googleapis.com/compute/v1/projects/example-project/zones/example-zone/instanceGroups/gk3-example-cluster-pool-2-9293c6db-grp 0->1 (max: 1000)} {https://www.googleapis.com/compute/v1/projects/example-project/zones/example-zone/instanceGroups/gk3-example-cluster-pool-2-d99371e7-grp 0->1 (max: 1000)}]
    

    El evento TriggeredScaleUp muestra que tu clúster está escalando de cero nodos a tantos nodos como sean necesarios para ejecutar tu carga de trabajo implementada.

Los pods del sistema no se pueden programar en clústeres vacíos

Este evento se produce cuando no se ejecuta ninguna de tus cargas de trabajo en un clúster, lo que provoca que el clúster se reduzca a cero nodos. Los clústeres de Autopilot empiezan con cero nodos utilizables y se reducen a cero nodos si no ejecutas ninguna de tus cargas de trabajo en el clúster. De esta forma, se minimizan los recursos de computación desperdiciados en el clúster.

Cuando un clúster se reduce a cero nodos, las cargas de trabajo del sistema de GKE no se programarán y permanecerán en el estado Pending. Este es el comportamiento esperado y no es necesario que hagas nada. La próxima vez que despliegues una carga de trabajo en el clúster, GKE aumentará la escala del clúster y los pods del sistema pendientes se ejecutarán en esos nodos.

Para comprobar si los pods del sistema están pendientes debido a que el clúster está vacío, haz lo siguiente:

  1. Comprueba si tu clúster tiene algún nodo:

    kubectl get nodes
    

    El resultado es el siguiente, que indica que el clúster tiene cero nodos:

    No resources found
    
  2. Comprueba el estado de los pods del sistema:

    kubectl get pods --namespace=kube-system
    

    El resultado debería ser similar al siguiente:

    NAME                                                       READY   STATUS    RESTARTS   AGE
    antrea-controller-horizontal-autoscaler-6d97f7cf7c-ngfd2   0/1     Pending   0          9d
    egress-nat-controller-84bc985778-6jcwl                     0/1     Pending   0          9d
    event-exporter-gke-5c5b457d58-7njv7                        0/2     Pending   0          3d5h
    event-exporter-gke-6cd5c599c6-bn665                        0/2     Pending   0          9d
    konnectivity-agent-694b68fb7f-gws8j                        0/2     Pending   0          3d5h
    konnectivity-agent-7d659bf64d-lp4kt                        0/2     Pending   0          9d
    konnectivity-agent-7d659bf64d-rkrw2                        0/2     Pending   0          9d
    konnectivity-agent-autoscaler-5b6ff64fcd-wn7fw             0/1     Pending   0          9d
    konnectivity-agent-autoscaler-cc5bd5684-tgtwp              0/1     Pending   0          3d5h
    kube-dns-65ccc769cc-5q5q7                                  0/5     Pending   0          3d5h
    kube-dns-7f7cdb9b75-qkq4l                                  0/5     Pending   0          9d
    kube-dns-7f7cdb9b75-skrx4                                  0/5     Pending   0          9d
    kube-dns-autoscaler-6ffdbff798-vhvkg                       0/1     Pending   0          9d
    kube-dns-autoscaler-8b7698c76-mgcx8                        0/1     Pending   0          3d5h
    l7-default-backend-87b58b54c-x5q7f                         0/1     Pending   0          9d
    metrics-server-v1.31.0-769c5b4896-t5jjr                    0/1     Pending   0          9d
    
  3. Comprueba por qué los pods del sistema tienen el estado Pending:

    kubectl describe pod --namespace=kube-system SYSTEM_POD_NAME
    

    Sustituye SYSTEM_POD_NAME por el nombre de cualquier Pod del sistema de la salida del comando anterior.

    El resultado debería ser similar al siguiente:

    ...
    Events:
    Type     Reason            Age                       From               Message
    ----     ------            ----                      ----               -------
    Warning  FailedScheduling  4m35s (x27935 over 3d5h)  default-scheduler  no nodes available to schedule pods
    ...
    

    En la salida, el valor no nodes available to schedule pods del campo Message del evento FailedScheduling indica que el pod del sistema no se ha programado porque el clúster está vacío.

El acceso a los nodos subyacentes está prohibido en un clúster de GKE Autopilot. Por lo tanto, es necesario ejecutar la utilidad tcpdump desde un pod y, a continuación, copiarla con el comando kubectl cp. Si sueles ejecutar la utilidad tcpdump desde un pod de un clúster de Autopilot de GKE, puede que veas el siguiente error:

    tcpdump: eth0: You don't have permission to perform this capture on that device
    (socket: Operation not permitted)

Esto ocurre porque Autopilot de GKE aplica de forma predeterminada un contexto de seguridad a todos los pods que elimina la función NET_RAW para mitigar posibles vulnerabilidades. Por ejemplo:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: tcpdump
  name: tcpdump
spec:
  containers:
  - image: nginx
    name: nginx
    resources:
      limits:
        cpu: 500m
        ephemeral-storage: 1Gi
        memory: 2Gi
      requests:
        cpu: 500m
        ephemeral-storage: 1Gi
        memory: 2Gi
    securityContext:
      capabilities:
        # This section drops NET_RAW to mitigate security vulnerabilities
        drop:
        - NET_RAW

Como solución, si tu carga de trabajo requiere la función NET_RAW, puedes volver a habilitarla:

  1. Añade la función NET_RAW a la sección securityContext de la especificación YAML de tu pod:

    securityContext:
      capabilities:
        add:
        - NET_RAW
    
  2. Ejecutar tcpdump desde un pod:

    tcpdump port 53 -w packetcap.pcap
    tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
    
  3. Usa el comando kubectl cp para copiarlo en tu máquina local y analizarlo más a fondo:

    kubectl cp POD_NAME:/PATH_TO_FILE/FILE_NAME/PATH_TO_FILE/FILE_NAME
    
  4. Usa kubectl exec para ejecutar el comando tcpdump para realizar la captura de paquetes de red y redirigir la salida:

    kubectl exec -it POD_NAME -- bash -c "tcpdump port 53 -w -" > packet-new.pcap
    

Siguientes pasos