Solucionar problemas del entorno de ejecución del contenedor


En este documento se describen los pasos para solucionar problemas habituales que pueden surgir con el tiempo de ejecución del contenedor en los nodos de Google Kubernetes Engine (GKE).

Los montajes de rutas con letras de unidad sencillas fallan en grupos de nodos de Windows con containerd

Este problema se ha resuelto en la versión 1.6.6 de containerd y en versiones posteriores.

Los clústeres de GKE que ejecutan grupos de nodos de Windows Server que usan el tiempo de ejecución de contenedores anterior a la versión 1.6.6 pueden experimentar errores al iniciar contenedores, como los siguientes:

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

Para obtener más información, consulta el problema de GitHub #6589.

Solución

Para solucionar este problema, actualiza tus grupos de nodos a las versiones más recientes de GKE que usen la versión 1.6.6 o una posterior del entorno de ejecución de containerd.

Las imágenes de contenedor con líneas de comandos CMD o ENTRYPOINT preescapadas que no sean de matriz fallan en los grupos de nodos de Windows con containerd

Este problema se ha resuelto en containerd 1.6 y versiones posteriores.

Los clústeres de GKE que ejecutan grupos de nodos de Windows Server que usan el runtime de contenedores 1.5.X pueden experimentar errores al iniciar contenedores, como los siguientes:

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

Para obtener más información, consulta el problema de GitHub #5067 y el problema de GitHub #6300.

Solución

Para solucionar este problema, actualiza tus grupos de nodos a las versiones más recientes de GKE que usen la versión 1.6.6 o una posterior del entorno de ejecución de containerd.

Los volúmenes de imágenes de contenedor con rutas que no existen o rutas de tipo Linux (con barra inclinada) fallan en grupos de nodos de Windows con containerd

Este problema se ha resuelto en containerd 1.6 y versiones posteriores.

Los clústeres de GKE que ejecutan grupos de nodos de Windows Server que usan el runtime de contenedores 1.5.X pueden experimentar errores al iniciar 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 información, consulta el problema de GitHub #5671.

Solución

Para solucionar este problema, actualice sus grupos de nodos a las versiones más recientes de GKE que usen la versión 1.6.x o una posterior del tiempo de ejecución de containerd.

/etc/mtab: No existe el archivo o el directorio

El entorno de ejecución del contenedor Docker rellena este enlace simbólico dentro del contenedor de forma predeterminada, pero el entorno de ejecución de containerd no lo hace.

Para obtener más información, consulta el problema de GitHub #2419.

Solución

Para solucionar este problema, crea manualmente el enlace simbólico /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 de GKE afectadas: todas

Cuando creas una imagen con kaniko, es posible que no se pueda extraer con containerd y se muestre el mensaje de error "not a directory" (no es un directorio). Este error se produce si la imagen se crea de una forma especial: cuando un comando anterior elimina 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 información, consulta el problema #4659 de GitHub.

Solución

Para solucionar este problema, cree la imagen con docker build, que no se ve afectada por él.

Si no puedes usar docker build, combina los comandos en uno solo. 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 de GKE afectadas: todas

El endpoint /metrics/cadvisor de Kubelet proporciona métricas de Prometheus, tal como se describe en el artículo Métricas de los componentes del sistema de Kubernetes. Si instalas un recolector de métricas que depende de ese endpoint, es posible que se produzcan los siguientes problemas:

  • El formato de las métricas del nodo de Docker es k8s_<container-name>_<pod-name>_<namespace>_<pod-uid>_<restart-count>, mientras que el del nodo de containerd es <container-id>.
  • Faltan algunas métricas del sistema de archivos en el nodo de containerd, como las siguientes:

    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 usando cAdvisor como un daemonset independiente.

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

Alternativas

  1. Migra tu solución de monitorización a Cloud Monitoring, que proporciona el conjunto completo de métricas de contenedores.
  2. Recoge métricas de la API de resumen de Kubelet con un endpoint de /stats/summary.

Las operaciones basadas en adjuntos no funcionan correctamente después de reiniciar el tiempo de ejecución del contenedor en GKE Windows

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

Los clústeres de GKE que ejecutan grupos de nodos de Windows Server que usan el tiempo de ejecución de containerd (versiones 1.5.4 y 1.5.7-gke.0) pueden experimentar problemas si el tiempo de ejecución del contenedor se reinicia de forma forzada y las operaciones de adjuntar a los contenedores en ejecución no pueden volver a enlazar la E/S. El problema no provocará errores en las llamadas a la API, pero no se enviarán ni recibirán datos. Esto incluye datos de las APIs y CLIs de adjuntos y registros a través del servidor de la API de clúster.

Solución

Para resolver este problema, actualice a la versión del tiempo de ejecución del contenedor con el parche (1.5.7-gke.1) con versiones más recientes de GKE.

Los pods muestran el mensaje de error 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 pueden experimentar problemas de fugas de IP y agotar todas las IPs de los pods de 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 las incidencias de GitHub #5438 y #5768 de containerd.

Hay un problema conocido en GKE Dataplane V2 que puede provocar este problema. Sin embargo, este problema puede deberse a otros motivos, como ejecuciones bloqueadas.

Solución

Para solucionar este problema, sigue las soluciones alternativas que se mencionan en la sección Soluciones alternativas para clústeres de GKE estándar de GKE Dataplane V2.

Diferencia en el comportamiento de la sonda de ejecución cuando supera el tiempo de espera

Versiones de GKE afectadas: todas

El comportamiento de la sonda de ejecución en imágenes de containerd es diferente al de las imágenes de dockershim. Cuando una sonda de ejecución definida para el pod supera el umbral declarado de Kubernetes timeoutSeconds en las imágenes de dockershim, se trata como un error de la sonda. En las imágenes de containerd, los resultados de la prueba devueltos después del umbral timeoutSeconds declarado se ignoran.

Solución

En GKE, el feature gate ExecProbeTimeout está definido como false y no se puede cambiar. Para solucionar este problema, aumenta el umbral de timeoutSeconds de todas las sondas de ejecución afectadas o implementa la función de tiempo de espera como parte de la lógica de la sonda.

Solucionar problemas con registros privados

En esta sección se proporciona información para solucionar problemas de configuraciones de registros privados en containerd.

No se puede extraer la imagen y se muestra el error x509: certificate signed by unknown authority

Este problema se produce si GKE no ha encontrado un certificado para un dominio de registro privado específico. Puedes comprobar si se ha producido este error en Cloud Logging con la siguiente consulta:

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

    Ir a 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 solucionar este problema, prueba lo siguiente:

  1. En GKE Standard, abra el archivo de configuración en la siguiente ruta:

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

    Sustituye DOMAIN por el FQDN del registro.

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

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

  4. Comprueba que el certificado esté en Secret Manager.

No se ha proporcionado ningún certificado

Este problema se produce si GKE no ha podido extraer el certificado de Secret Manager para configurar containerd en sus nodos.

Para solucionar este problema, prueba lo siguiente:

  1. Asegúrate de que el nodo afectado ejecute Container-Optimized OS. No se admiten nodos de Ubuntu ni de Windows.
  2. En el archivo de configuración, comprueba que la ruta del secreto en el campo secretURI sea correcta.
  3. Comprueba que la cuenta de servicio de gestión de identidades y accesos de tu clúster tenga los permisos correctos para acceder al secreto.
  4. Comprueba que el clúster tenga el ámbito de acceso cloud-platform. Para obtener instrucciones, consulta Comprobar los ámbitos de acceso.

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

Versiones de GKE afectadas: todas

En las imágenes de containerd, 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 solucionar este problema, prueba lo siguiente:

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

En el caso de los clústeres estándar, prueba los pasos que se indican a continuación. Esta solución alternativa no está disponible en Autopilot porque los contenedores con privilegios suponen un riesgo para la seguridad. Si tu entorno está expuesto a Internet, ten en cuenta 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 Secret Manager.

  1. Revisa el siguiente archivo de 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: registry.k8s.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, sustituye el valor REGISTRY_ADDRESS de la variable ADDRESS por la dirección de tu registro HTTP local con el formato DOMAIN_NAME:PORT. Por ejemplo,

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

    kubectl apply -f insecure-registry-ds.yaml
    

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

containerd ignora las asignaciones de dispositivos de los pods con privilegios

Versiones de GKE afectadas: todas

En el caso de los pods de Kubernetes con privilegios, el tiempo de ejecución del contenedor ignora cualquier asignación de dispositivos que se le volumeDevices.devicePath transfiera y, en su lugar, hace que todos los dispositivos del host estén disponibles para el contenedor en /dev.

containerd pierde procesos shim cuando los nodos están sometidos a presión de E/S

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

Cuando un nodo de GKE está sometido a una presión de E/S, es posible que containerd no pueda eliminar los procesos containerd-shim-runc-v2 cuando se elimina un pod, lo que provoca fugas de procesos. Cuando se produce una fuga en un nodo, verás más procesos containerd-shim-runc-v2 en el nodo que el número de pods en ese nodo. También puede observar un aumento del uso de la memoria y la CPU, así como PIDs adicionales. Para obtener más información, consulta el problema de GitHub Fix leaked shim caused by high IO pressure (Corregir el shim filtrado causado por la alta presión de E/S).

Para solucionar este problema, actualiza tus nodos a las siguientes versiones o a otras 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 los pods que ejecutan containerd

Versiones de GKE afectadas: 1.18, 1.19 y de la 1.20.0 a la 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 lo hace. Por ejemplo, localhost se resuelve primero en la dirección IPv6 ::1. Por lo general, esto no supone ningún problema, pero en algunos casos puede provocar un comportamiento inesperado.

Solución

Para resolver este problema, usa una dirección IPv4 como 127.0.0.1 explícitamente 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 grupos de nodos de Container-Optimized OS con Docker

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

El aprovisionamiento automático de nodos permite adaptar dinámicamente los grupos de nodos con cualquier tipo de imagen compatible, pero solo puede crear nuevos grupos de nodos con el tipo de imagen Container-Optimized OS con Docker.

Solución

Para solucionar 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 definir para el clúster.

Conflicto con el intervalo de direcciones IP 172.17/16

Versiones de GKE afectadas: de la 1.18.0 a la 1.18.14

El intervalo 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íe a ese intervalo o que proceda de él no se enrute correctamente (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 recogen métricas de GPU

Versiones de GKE afectadas: de la 1.18.0 a la 1.18.18

Las métricas de uso de la GPU no se recogen cuando se usa containerd como tiempo de ejecución en versiones de GKE anteriores a la 1.18.18.

Solución

Para solucionar este problema, actualiza tus clústeres a la versión 1.18.18 de GKE o a una posterior.

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

Versiones de GKE afectadas: todas

Las imágenes con config.mediaType definido como "application/octet-stream" no se pueden usar en containerd. Para obtener más información, consulta el problema de GitHub #4756. 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 ofrecer compatibilidad con versiones anteriores, mientras que en containerd no se admiten.

Síntomas 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"

El manifiesto de la imagen suele encontrarse en el registro en el que está alojada. Una vez que tengas el archivo de manifiesto, consulta config.mediaType para determinar si tienes este problema:

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

Solución

Como la comunidad de containerd ha decidido no admitir este tipo de imágenes, todas las versiones de containerd se ven afectadas y no hay ninguna solución. La imagen del contenedor debe volver a compilarse con la versión 1.11 de Docker o una posterior, y debes asegurarte de que el campo config.mediaType no esté definido como "application/octet-stream".

CNI no inicializado

Versiones de GKE afectadas: todas

Si aparece un error similar al siguiente, significa que la configuración de la interfaz de red de contenedores (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 ha terminado de instalarse
  • El webhook está mal configurado

Asegúrate de que el CNI ha finalizado la instalación

Puede que veas este error en tus archivos de registro durante el arranque del nodo mientras GKE instala la configuración de CNI. Si ves este error, pero GKE está creando todos los nodos correctamente, puedes ignorarlo sin problemas.

Esto puede ocurrir porque el CNI proporciona a los pods su conectividad de red, por lo que los pods necesitan el CNI para funcionar. Sin embargo, Kubernetes usa intolerancias para marcar los nodos que no están listos y los pods del sistema pueden tolerar estas intolerancias. Esto significa que los pods del sistema pueden iniciarse en un nuevo nodo antes de que la red esté lista, lo que provoca el error.

Para solucionar este problema, espere a que GKE termine de instalar la configuración de CNI. Una vez que CNI haya terminado de configurar la red, los pods del sistema se iniciarán correctamente sin necesidad de intervención.

Corregir webhooks mal configurados

Si el error de CNI no inicializado persiste y observas que GKE no puede crear nodos durante una actualización, un cambio de tamaño u 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 Google Cloud consola. Esta configuración incorrecta impide que GKE cree un pod netd o calico-node. Si los netd o calico-node Pods se han iniciado correctamente mientras el error persiste, ponte en contacto con el servicio de atención al cliente.

Para corregir los webhooks mal configurados, sigue estos pasos:

  1. Identificar webhooks mal configurados.

    Si usas un clúster con la opción de cumplimiento de la política de red de Dataplane V1 habilitada, también puedes consultar el estado del pod calico-typha para obtener información sobre los webhooks que están causando este error:

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

    Si el pod tiene un error, el resultado será 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 que ha fallado. Es posible que la salida incluya información sobre otro tipo de error.

  2. Si quieres conservar los webhooks mal configurados, soluciona los problemas. Si no son necesarios, elimínalos ejecutando los siguientes comandos:

    kubectl delete mutatingwebhookconfigurations WEBHOOK_NAME
    kubectl delete validatingwebhookconfigurations WEBHOOK_NAME
    

    Sustituye WEBHOOK_NAME por el nombre del webhook mal configurado que quieras eliminar.

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

Siguientes pasos