Soluciona problemas del entorno de ejecución del contenedor

Los problemas con el entorno de ejecución del contenedor en tus nodos de Google Kubernetes Engine (GKE) pueden causar una variedad de fallas en las cargas de trabajo, lo que impide que tus contenedores se inicien o se ejecuten de manera confiable. Estos problemas suelen deberse a errores como configuraciones incorrectas de la red, problemas de permisos o diferencias entre los tiempos de ejecución de los contenedores.

Usa esta página para solucionar problemas comunes con el entorno de ejecución de contenedores en tus grupos de nodos de GKE. Encuentra soluciones para problemas como errores de rutas de acceso de montaje en Windows, fallas en la extracción de imágenes de registros privados, falta de métricas del sistema de archivos, errores de inicialización de CNI y diferencias de comportamiento en las sondas exec.

Esta información es importante para los administradores y operadores de la plataforma, y para los desarrolladores de aplicaciones que administran e implementan cargas de trabajo en clústeres de GKE. Comprender estos pasos para solucionar problemas puede ayudarte a garantizar que tus contenedores se ejecuten de manera confiable en diferentes imágenes y configuraciones de nodos. Para obtener más información sobre los roles comunes y las tareas de ejemplo a las que hacemos referencia en el contenido deGoogle Cloud , consulta Roles de usuario y tareas comunes de GKE.

Las rutas de activación con letras de unidad simples fallan en los grupos de nodos de Windows con containerd

Este problema se resolvió en la versión 1.6.6 de containerd y posteriores.

Los clústeres de GKE que ejecutan grupos de nodos de Windows Server que usan el entorno de ejecución de containerd anterior a la versión 1.6.6 pueden experimentar errores cuando se inician contenedores como los siguientes:

failed to create containerd task : CreateComputeSystem : The parameter is incorrect : unknown

Para obtener más detalles, consulta el problema #6589 de GitHub.

Solución

Para resolver este problema, actualiza tus grupos de nodos a las últimas versiones de GKE que usan la versión 1.6.6 o superior del entorno de ejecución de containerd.

Las imágenes de contenedor con líneas de comandos de CMD o ENTRYPOINT sin escape previo de arrays fallan en los grupos de nodos de Windows con containerd

Este problema se resolvió en la versión 1.6 de containerd y posteriores.

Los clústeres de GKE que ejecutan grupos de nodos de Windows Server que usan el entorno de ejecución de containerd 1.5.X pueden experimentar errores cuando inician contenedores como los siguientes:

failed to start containerd task : hcs::System::CreateProcess : The system cannot find the file specified.: unknown

Para obtener más detalles, consulta los problemas de GitHub #5067 y #6300.

Solución

Para resolver este problema, actualiza tus grupos de nodos a las últimas versiones de GKE que usan la versión 1.6.6 o superior del entorno de ejecución de containerd.

Los volúmenes de imágenes de contenedor con rutas de acceso no existentes o rutas de acceso similares a Linux (diagonal) fallan en los grupos de nodos de Windows con containerd

Este problema se resolvió en la versión 1.6 de containerd y posteriores.

Los clústeres de GKE que ejecutan grupos de nodos de Windows Server que usan el entorno de ejecución de containerd 1.5.X pueden experimentar errores cuando inician contenedores como los siguientes:

failed to generate spec: failed to stat "<volume_path>": CreateFile : The system cannot find the path specified.

Para obtener más detalles, consulta el problema #5671 de GitHub.

Solución

Para resolver este problema, actualiza tus grupos de nodos a las últimas versiones de GKE que usan la versión 1.6.x o superior del entorno de ejecución de containerd.

/etc/mtab: El archivo o directorio no existe

El entorno de ejecución del contenedor de Docker propaga este symlink dentro del contenedor de forma predeterminada, pero el entorno de ejecución de containerd no lo hace.

Para obtener más detalles, consulta el problema #2419 de GitHub.

Solución

Para resolver este problema, crea manualmente el symlink /etc/mtab durante la compilación de la imagen.

ln -sf /proc/mounts /etc/mtab

Error de extracción de imagen: no es un directorio

Versiones afectadas de GKE: todas

Cuando compilas una imagen con kaniko, es posible que no se pueda extraer con containerd con el mensaje de error "no es un directorio". Este error ocurre si la imagen se compila de una forma especial: cuando un comando anterior quita un directorio y el siguiente comando vuelve a crear los mismos archivos en ese directorio.

En el siguiente ejemplo de Dockerfile con npm, se ilustra este problema.

RUN npm cache clean --force
RUN npm install

Para obtener más detalles, consulta el problema #4659 de GitHub.

Solución

Para resolver este problema, compila tu imagen con docker build, que no se verá afectada por este problema.

Si docker build no es una opción para ti, combina los comandos en uno. En el siguiente ejemplo de Dockerfile, se combinan RUN npm cache clean --force y RUN npm install:

RUN npm cache clean --force && npm install

Faltan algunas métricas del sistema de archivos y el formato de las métricas es diferente

Versiones afectadas de GKE: todas

El extremo /metrics/cadvisor de Kubelet proporciona métricas de Prometheus, como se documenta en Métricas para los componentes del sistema de Kubernetes. Si instalas un colector de métricas que depende de ese extremo, es posible que veas los siguientes problemas:

  • El formato de las métricas en el nodo de Docker es k8s_<container-name>_<pod-name>_<namespace>_<pod-uid>_<restart-count>, pero el formato en el nodo en container es <container-id>.
  • Faltan algunas métricas del sistema de archivos en el nodo containerd, como se muestra a continuación:

    container_fs_inodes_free
    container_fs_inodes_total
    container_fs_io_current
    container_fs_io_time_seconds_total
    container_fs_io_time_weighted_seconds_total
    container_fs_limit_bytes
    container_fs_read_seconds_total
    container_fs_reads_merged_total
    container_fs_sector_reads_total
    container_fs_sector_writes_total
    container_fs_usage_bytes
    container_fs_write_seconds_total
    container_fs_writes_merged_total
    

Solución

Puedes mitigar este problema a través del uso de cAdvisor como un daemonset independiente.

  1. Busca la versión de cAdvisor más reciente con el patrón de nombre vX.Y.Z-containerd-cri (por ejemplo, v0.42.0-containerd-cri).
  2. Sigue los pasos en cAdvisor Kubernetes Daemonset para crear el daemonset.
  3. Apunta el recopilador de métricas instalado para usar el extremo /metrics de cAdvisor, que proporciona el conjunto completo de métricas de contenedor de Prometheus.

Alternativas

  1. Migra tu solución de supervisión a Cloud Monitoring, que proporciona el conjunto completo de métricas de contenedor.
  2. Recopila métricas de la API de resumen de Kubelet con un extremo de /stats/summary.

Las operaciones basadas en conexiones no funcionan de forma correcta después de que el entorno de ejecución de contenedores se reinicie en GKE Windows.

Versiones de GKE afectadas: 1.21 a 1.21.5-gke.1802, 1.22 a 1.22.3-gke.700

Es posible que los clústeres de GKE que ejecutan grupos de nodos de Windows Server que usan el entorno de ejecución de containerd (versiones 1.5.4 y 1.5.7-gke.0) tengan problemas si el entorno de ejecución del contenedor se reinicia de manera forzada, con operaciones de conexión a contenedores en ejecución existentes que no se pueden volver a vincular a IO. El problema no causará fallas en las llamadas a la API. Sin embargo, los datos no se enviarán ni se recibirán. Esto incluye los datos para adjuntar y registrar las CLI y las API a través del servidor de la API del clúster.

Solución

Para resolver este problema, actualiza a la versión del entorno de ejecución del contenedor (1.5.7-gke.1) con la versión más reciente de GKE.

Los Pods muestran un mensaje de error de failed to allocate for range 0: no IP addresses available in range set

Versiones de GKE afectadas: 1.24.6-gke.1500 o anteriores, 1.23.14-gke.1800 o anteriores, y 1.22.16-gke.2000 o anteriores

Los clústeres de GKE que ejecutan grupos de nodos que usan containerd podrían experimentar problemas de filtración de IP y agotar todas las direcciones IP de Pods en un nodo. Un Pod programado en un nodo afectado muestra un mensaje de error similar al siguiente:

failed to allocate for range 0: no IP addresses available in range set: 10.48.131.1-10.48.131.62

Para obtener más información sobre el problema, consulta el problema #5438 de GitHub y el problema #5768 de GitHub.

Existe un problema conocido en GKE Dataplane V2 que puede activar este problema. Sin embargo, este problema se puede activar por otras causas, como runc atascado.

Solución

A fin de resolver este problema, sigue las soluciones alternativas que se mencionan en Soluciones para clústeres de GKE estándar para GKE Dataplane V2.

Diferencia en el comportamiento del sondeo de ejecución cuando el sondeo excede el tiempo de espera

Versiones afectadas de GKE: todas

El comportamiento del sondeo de ejecución en las imágenes de Containerd es diferente del comportamiento en las imágenes dockershim. Cuando el sondeo de ejecución, definido para el Pod, excede el umbral declarado de timeoutSeconds de Kubernetes, en imágenes de dockershim, se trata como una falla de sondeo. En las imágenes de containerd, se ignoran los resultados de sondeo que se muestran después del umbral de timeoutSeconds declarado.

Solución

En GKE, el interruptor de función ExecProbeTimeout se establece en false y no se puede cambiar. A fin de resolver este problema, aumenta el umbral de timeoutSeconds para todos los sondeos de ejecución afectados o implementa la funcionalidad de tiempo de espera como parte de la lógica del sondeo.

Soluciona problemas con los registros privados

En esta sección, se proporciona información para solucionar problemas relacionados con la configuración de registros privados en containerd.

La extracción de la imagen falla con el error x509: certificado firmado por autoridad desconocida

Este problema se produce si GKE no pudo encontrar un certificado para un dominio de registro privado específico. Puedes verificar este error en Cloud Logging mediante la siguiente consulta:

  1. Ve a la página del Explorador de registros en la consola de Google Cloud :

    Ir al Explorador de registros

  2. Ejecuta la siguiente consulta:

    ("Internal error pulling certificate" OR
    "Failed to get credentials from metadata server" OR
    "Failed to install certificate")
    

Para resolver este problema, realiza las siguientes acciones:

  1. En GKE Standard, abre el archivo de configuración que existe en la siguiente ruta de acceso:

    /etc/containerd/hosts.d/DOMAIN/config.toml
    

    Reemplaza DOMAIN por el FQDN del registro.

  2. Verifica que tu archivo de configuración contenga el FQDN correcto.

  3. Verifica que la ruta de acceso al certificado en el campo secretURI del archivo de configuración sea correcta.

  4. Verifica que el certificado exista en Secret Manager.

No se encontró el certificado

Este problema se produce si GKE no pudo extraer el certificado de Secret Manager para configurar containerd en tus nodos.

Para resolver este problema, realiza las siguientes acciones:

  1. Asegúrate de que el nodo afectado ejecute Container-Optimized OS. Los nodos de Ubuntu y Windows no son compatibles.
  2. En tu archivo de configuración, asegúrate de que la ruta de acceso al secreto en el campo secretURI sea correcta.
  3. Verifica que la cuenta de servicio de IAM de tu clúster tenga los permisos correctos para acceder al secreto.
  4. Comprueba que el clúster tenga el permiso de acceso cloud-platform. Si deseas obtener instrucciones, consulta Cómo verificar los permisos de acceso.

La opción de registro no seguro no está configurada para la red local (10.0.0.0/8)

Versiones afectadas de GKE: todas

En las imágenes en contenedores, la opción de registro no seguro no está configurada para la red local 10.0.0.0/8. Si usas registros privados no seguros, es posible que veas errores similares a los siguientes:

pulling image: rpc error: code = Unknown desc = failed to pull and unpack image "IMAGE_NAME": failed to do request: Head "IMAGE_NAME": http: server gave HTTP response to HTTPS client

Para resolver este problema, realiza las siguientes acciones:

Configura DaemonSets con privilegios para modificar la configuración de containerd

Para los clústeres estándar, prueba los siguientes pasos. Esta solución alternativa no está disponible en Autopilot porque los contenedores privilegiados son un riesgo de seguridad. Si tu entorno está expuesto a Internet, considera tu tolerancia al riesgo antes de implementar esta solución. En todos los casos, te recomendamos que configures TLS para tu registro privado y que uses la opción de Secret Manager.

  1. Revisa el siguiente manifiesto:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: insecure-registries
      namespace: default
      labels:
        k8s-app: insecure-registries
    spec:
      selector:
        matchLabels:
          name: insecure-registries
      updateStrategy:
        type: RollingUpdate
      template:
        metadata:
          labels:
            name: insecure-registries
        spec:
          nodeSelector:
            cloud.google.com/gke-container-runtime: "containerd"
          hostPID: true
          containers:
            - name: startup-script
              image: gke.gcr.io/startup-script:v2
              imagePullPolicy: Always
              securityContext:
                privileged: true
              env:
              - name: ADDRESS
                value: "REGISTRY_ADDRESS"
              - name: STARTUP_SCRIPT
                value: |
                  set -o errexit
                  set -o pipefail
                  set -o nounset
    
                  if [[ -z "$ADDRESS" || "$ADDRESS" == "REGISTRY_ADDRESS" ]]; then
                    echo "Error: Environment variable ADDRESS is not set in containers.spec.env"
                    exit 1
                  fi
    
                  echo "Allowlisting insecure registries..."
                  containerd_config="/etc/containerd/config.toml"
                  hostpath=$(sed -nr 's;  config_path = "([-/a-z0-9_.]+)";\1;p' "$containerd_config")
                  if [[ -z "$hostpath" ]]; then
                    echo "Node uses CRI config model V1 (deprecated), adding mirror under $containerd_config..."
                    grep -qxF '[plugins."io.containerd.grpc.v1.cri".registry.mirrors."'$ADDRESS'"]' "$containerd_config" || \
                      echo -e '[plugins."io.containerd.grpc.v1.cri".registry.mirrors."'$ADDRESS'"]\n  endpoint = ["http://'$ADDRESS'"]' >> "$containerd_config"
                  else
                    host_config_dir="$hostpath/$ADDRESS"
                    host_config_file="$host_config_dir/hosts.toml"
                    echo "Node uses CRI config model V2, adding mirror under $host_config_file..."
                    if [[ ! -e "$host_config_file" ]]; then
                      mkdir -p "$host_config_dir"
                      echo -e "server = \"https://$ADDRESS\"\n" > "$host_config_file"
                    fi
                    echo -e "[host.\"http://$ADDRESS\"]\n  capabilities = [\"pull\", \"resolve\"]\n" >> "$host_config_file"
                  fi
                  echo "Reloading systemd management configuration"
                  systemctl daemon-reload
                  echo "Restarting containerd..."
                  systemctl restart containerd

    En el campo .spec.containers.env, reemplaza el valor REGISTRY_ADDRESS de la variable ADDRESS por la dirección de tu registro HTTP local en el formato DOMAIN_NAME:PORT. Por ejemplo,

    containers:
    - name: startup-script
      ...
      env:
      - name: ADDRESS
        value: "example.com:5000"
    
  2. Implementa el DaemonSet:

    kubectl apply -f insecure-registry-ds.yaml
    

El DaemonSet agrega tu registro no seguro a la configuración de containerd en cada nodo.

containerd ignora todas las asignaciones de dispositivos para pods con privilegios

Versiones afectadas de GKE: todas

Para los Pods con privilegios, el entorno de ejecución del contenedor ignora las asignaciones de dispositivos que volumeDevices.devicePath le pasa y, en su lugar, hace que todos los dispositivos del host estén disponibles para el contenedor en /dev.

Los procesos de corrección de compatibilidad con containerd filtran los nodos cuando están bajo presión de E/S

Versiones de GKE afectadas: 1.25.0 a 1.25.15-gke.1040000, 1.26.0 a 1.26.10-gke.1030000, 1.27.0 a 1.27.6-gke.1513000 y 1.28.0 a 1.28.3-gke.1061000

Cuando un nodo de GKE está bajo presión de E/S, es posible que containerd no pueda borrar los procesos de containerd-shim-runc-v2 cuando se borra un Pod, lo que genera fugas de procesos. Cuando se produzca una pérdida en un nodo, verás más procesos containerd-shim-runc-v2 en el nodo que la cantidad de Pods en ese nodo. También es posible que notes un aumento en el uso de CPU y memoria, junto con PIDs adicionales. Para obtener más detalles, consulta el problema de GitHub Fix leaked shim caused by high IO pressure.

Para resolver este problema, actualiza tus nodos a las siguientes versiones o posteriores:

  • 1.25.15-gke.1040000
  • 1.26.10-gke.1030000
  • 1.27.6-gke.1513000
  • 1.28.3-gke.1061000

La familia de direcciones IPv6 está habilitada en pods que ejecutan containerd

Versiones afectadas de GKE: 1.18, 1.19, 1.20.0 a 1.20.9

La familia de imágenes IPv6 está habilitada para los pods que se ejecutan con Containerd. La imagen dockershim inhabilita IPv6 en todos los Pods, mientras que la imagen de containerd no. Por ejemplo, localhost se resuelve primero en la dirección IPv6 ::1. Por lo general, esto no es un problema, pero podría causar un comportamiento inesperado en ciertos casos.

Solución

A fin de resolver este problema, usa una dirección IPv4 como 127.0.0.1 de manera explícita o configura una aplicación que se ejecute en el Pod para que funcione en ambas familias de direcciones.

El aprovisionamiento automático de nodos solo aprovisiona Container-Optimized OS con los grupos de nodos de Docker

Versiones de GKE afectadas: 1.18, 1.19, 1.20.0 a 1.20.6-gke.1800

El aprovisionamiento automático de nodos permite el ajuste de escala automático de los grupos de nodos con cualquier tipo de imagen compatible, pero solo puede crear grupos de nodos nuevos por medio del tipo de imagen Container-Optimized OS con Docker.

Solución

Para resolver este problema, actualiza tus clústeres de GKE a la versión 1.20.6-gke.1800 o una posterior. En estas versiones de GKE, el tipo de imagen predeterminado se puede configurar para el clúster.

Conflicto con el rango de direcciones IP 172.17/16

Versiones afectadas de GKE: 1.18.0 a 1.18.14

El rango de direcciones IP 172.17/16 está ocupado por la interfaz docker0 en la VM de nodo con containerd habilitado. Es posible que el tráfico que se envía a ese rango o proveniente de él no se enrute de forma correcta (por ejemplo, es posible que un Pod no pueda conectarse a un host conectado a una VPN con una dirección IP dentro de 172.17/16).

No se recopilan las métricas de GPU

Versiones afectadas de GKE: 1.18.0 a 1.18.18

Las métricas de uso de GPU no se recopilan cuando se usa containerd como entorno de ejecución en las versiones de GKE anteriores a 1.18.18.

Solución

Para resolver este problema, actualiza tus clústeres a las versiones 1.18.18 o posteriores de GKE.

Las imágenes con config.mediaType configurado como application/octet-stream no se pueden usar en containerd.

Versiones afectadas de GKE: todas

Las imágenes con config.mediaType configurado como "application/octet-stream" no se pueden usar en containerd. Para obtener más información, consulta problema #4756 de GitHub. Estas imágenes no son compatibles con la especificación de Open Container Initiative y se consideran incorrectas. Estas imágenes funcionan con Docker para proporcionar retrocompatibilidad, mientras que en containerd estas imágenes no son compatibles.

Síntoma y diagnóstico

Ejemplo de error en los registros de nodos:

Error syncing pod <pod-uid> ("<pod-name>_<namespace>(<pod-uid>)"), skipping: failed to "StartContainer" for "<container-name>" with CreateContainerError: "failed to create containerd container: error unpacking image: failed to extract layer sha256:<some id>: failed to get reader from content store: content digest sha256:<some id>: not found"

Por lo general, el manifiesto de la imagen se puede encontrar en el registro donde se aloja. Una vez que tengas el manifiesto, verifica config.mediaType para determinar si tienes este problema:

"mediaType": "application/octet-stream",

Solución

Dado que la comunidad de containerd decidió no admitir esas imágenes, todas las versiones de containerd se verán afectadas y no habrá solución. La imagen del contenedor se debe volver a compilar con la versión 1.11 de Docker o una posterior, y debes asegurarte de que el campo config.mediaType no esté configurado como "application/octet-stream".

CNI no inicializado

Versiones afectadas de GKE: todas

Si ves un error similar al siguiente, la configuración de la interfaz de red de contenedor (CNI) no está lista:

Error: "network is not ready: container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized".

Este error se produce por dos motivos principales:

  • El CNI no terminó de instalarse
  • El webhook está mal configurado

Asegúrate de que la CNI haya terminado la instalación

Es posible que veas este error en tus archivos de registro durante el arranque de nodos mientras GKE instala la configuración de CNI. Si ves este error, pero GKE crea todos los nodos correctamente, puedes ignorarlo sin problemas.

Esta situación puede ocurrir porque el CNI proporciona a los Pods su conectividad de red, por lo que los Pods necesitan que el CNI funcione. Sin embargo, Kubernetes usa taints para marcar los nodos que no están listos, y los Pods del sistema pueden tolerar estos taints. Esto significa que los Pods del sistema pueden iniciarse en un nodo nuevo antes de que la red esté lista, lo que genera el error.

Para resolver este problema, espera a que GKE termine de instalar la configuración de CNI. Una vez que CNI termina de configurar la red, los Pods del sistema se inician correctamente sin necesidad de intervención.

Cómo corregir los webhooks mal configurados

Si persiste el error de CNI no inicializado y observas que GKE no puede crear nodos durante una actualización, un cambio de tamaño o alguna otra acción, es posible que tengas un webhook mal configurado.

Si tienes un webhook personalizado que intercepta el comando del controlador DaemonSet para crear un Pod y ese webhook está mal configurado, es posible que veas el error como un estado de error de nodo en la consola de Google Cloud . Esta configuración incorrecta impide que GKE cree un Pod netd o calico-node. Si los Pods netd o calico-node se iniciaron de forma correcta mientras persiste el error, comunícate con Atención al cliente.

Para corregir los webhooks mal configurados, completa los siguientes pasos:

  1. Identifica los webhooks mal configurados.

    Si usas un clúster con la aplicación de la política de red de Dataplane V1 habilitada, también puedes verificar el estado del Pod calico-typha para obtener información sobre los webhooks que causan este error:

    kubectl describe pod -n kube-system -l k8s-app=calico-typha
    

    Si el Pod tiene un error, el resultado es similar al siguiente:

    Events:
    Type     Reason        Age                     From                   Message
    ----     ------        ----                    ----                   -------
    Warning  FailedCreate  9m15s (x303 over 3d7h)  replicaset-controller  Error creating: admission webhook WEBHOOK_NAME denied the request [...]
    

    En este resultado, WEBHOOK_NAME es el nombre de un webhook con errores. Es posible que tu resultado incluya información sobre un tipo de error diferente.

  2. Si deseas conservar los webhooks mal configurados, soluciona los problemas. Si no son necesarios, bórralos con los siguientes comandos:

    kubectl delete mutatingwebhookconfigurations WEBHOOK_NAME
    kubectl delete validatingwebhookconfigurations WEBHOOK_NAME
    

    Reemplaza WEBHOOK_NAME por el nombre del webhook mal configurado que deseas quitar.

  3. Configura tus webhooks para ignorar los Pods del sistema.

¿Qué sigue?