Soluciona problemas

Obtén información sobre los pasos para la solución de problemas que puedes encontrar en Google Kubernetes Engine.

Depura los recursos de Kubernetes

Si tienes un problema con el clúster, consulta Soluciona problemas de clústeres en la documentación de Kubernetes.

Si tienes un problema con tu aplicación, sus Pods o tu objeto de controlador, consulta Soluciona problemas de aplicaciones.

No se encuentra el comando kubectl

Primero, instala el binario kubectl mediante la ejecución del comando siguiente:

sudo gcloud components update kubectl

Responde “sí” cuando el instalador te solicite que modifiques el entorno variable $PATH. La modificación de estas variables te habilita a usar los comandos kubectl sin escribir la ruta de archivo completa.

De manera alternativa, agrega la línea siguiente a ~/.bashrc (o ~/.bash_profile en macOS, o donde tu shell almacene las variables de entorno):

export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/

Al final, ejecuta el comando siguiente para cargar el archivo actualizado .bashrc (o .bash_profile):

source ~/.bashrc

Los comandos kubectl muestran el error “conexión rechazada”

Establece el contexto del clúster con el comando siguiente:

gcloud container clusters get-credentials [CLUSTER_NAME]

Si no estás seguro de qué ingresar para CLUSTER_NAME, usa el comando siguiente a fin de hacer una lista de clústeres:

gcloud container clusters list

Los comandos kubectl muestran el error “no se pudo negociar una versión de la api”

Asegúrate de que kubectl tenga credenciales de autenticación:

gcloud auth application-default login

Los comandos kubectl logs, attach, exec y port-forward se interrumpen

Estos comandos dependen de que la instancia principal del clúster pueda comunicarse con los nodos en el clúster. Sin embargo, debido a que la instancia principal no se encuentra en la misma red de Compute Engine que tus nodos del clúster, dependemos de los túneles de SSH para habilitar una comunicación segura.

GKE guarda un archivo de clave pública SSH en los metadatos del proyecto de Compute Engine. Todas las VM de Compute Engine que usan imágenes proporcionadas por Google verifican con regularidad los metadatos comunes del proyecto y los metadatos de la instancia para las Llaves SSH a fin de agregarlos a la lista de VM de usuarios autorizados. GKE también agrega una regla de firewall a la red de Compute Engine que permite el acceso a SSH desde la dirección IP de la instancia principal a cada nodo en el clúster.

Si alguno de los comandos anteriores kubectl no se ejecuta, es posible que la instancia principal no pueda abrir los túneles de SSH con los nodos. Verifica las posibles causas siguientes:

  1. El clúster no tiene nodos.

    Si reduces la cantidad de nodos en tu clúster a cero, los túneles de SSH no funcionarán.

    A fin de arreglarlo, cambia el tamaño del clúster para tener al menos un nodo.

  2. Los pods en el clúster se detuvieron en un estado de finalización y evitaron que los nodos que ya no existen se puedan quitar del clúster.

    Este problema debería afectar solo a la versión 1.1 de Kubernetes, pero también se puede generar por un cambio de tamaño del clúster reiterado.

    Para arreglarlo, borra los pods que estén en un estado de finalización por más de unos minutos. De esa manera, los nodos antiguos se quitan de la API de la instancia principal y se reemplazan por los nodos nuevos.

  3. Las reglas de firewall de tu red no permiten el acceso de SSH a la instancia principal.

    Todas las redes de Compute Engine se crean con una regla de firewall llamada “default-allow-ssh” que permite el acceso SSH desde todas las direcciones IP (por supuesto, requiere una clave privada válida). GKE también inserta una regla SSH para cada clúster del tipo gke-<cluster_name>-<random-characters>-ssh que permite el acceso SSH de manera específica desde la instancia principal IP del clúster a los nodos del clúster. Si no existe ninguna de estas reglas, la instancia principal no puede abrir los túneles SSH.

    Para arreglarlo, vuelve a agregar una regla de firewall que permita el acceso a las VM con el etiquetado que se encuentra en todos los nodos del clúster de la dirección IP de la instancia principal.

  4. La entrada de los metadatos comunes del proyecto para las “llaves SSH” está llena.

    Si la entrada de los metadatos del proyecto llamada “Llaves de SSH” está cerca del límite de tamaño 32 KiB, GKE no puede agregar su propia Llave SSH a fin de permitir que abra los túneles SSH. Puedes ver los metadatos del proyecto si ejecutas gcloud compute project-info describe [--project=PROJECT] y, luego, verificas la longitud de la lista de Llaves SSH.

    Para arreglarlo, borra algunas de las Llaves SSH que ya no sean necesarias.

  5. Estableciste un campo de metadatos con la clave “Llave SSH” en las VM del clúster.

    El agente de nodo en las VM prefiere llaves SSH por instancia en vez de Llaves SSH por proyecto completo, por lo que, si estableciste cualquier Llave SSH en los nodos del clúster, los nodos no respetarán la Llave SSH de la instancia principal en los metadatos del proyecto. Para verificar, ejecuta gcloud compute instances describe <VM-name> y busca un campo “llave SSH” en los metadatos.

    Para arreglarlo, borra las Llaves SSH por instancia de los metadatos de la instancia.

Ten en cuenta que estas características no se requieren para el funcionamiento correcto del clúster. Si prefieres mantener el acceso exterior bloqueado para la red del clúster, ten en cuenta que las características como estas no funcionarán.

Las métricas de tu clúster no se muestran en Stackdriver

Asegúrate de haber activado la API de Stackdriver Monitoring y la API de Stackdriver Logging en tu proyecto, y de que puedas ver tu proyecto en Stackdriver Monitoring.

Si el problema persiste, verifica alguna de las posibles causas siguientes:

  1. Asegúrate de que habilitaste la supervisión en tu clúster.

    La supervisión está habilitada de manera predeterminada para los clústeres creados desde Developers Console y con la herramienta de línea de comandos de gcloud, pero lo puedes verificar si ejecutas el siguiente comando o si haces clic en los detalles del clúster en Developers Console:

    gcloud container clusters describe cluster-name

    La salida de la herramienta de línea de comandos de gcloud debe indicar que el "servicio de supervisión" es "monitoring.googleapis.com", y la Cloud Monitoring debe estar habilitada en la Developers Console.

    Si la supervisión no está habilitada, ejecuta el comando siguiente para habilitarla:

    gcloud container clusters update cluster-name --monitoring-service=monitoring.googleapis.com
  2. ¿Cuánto tiempo pasó desde que se creó el clúster o se habilitó la supervisión?

    Puede tomar hasta una hora para que las métricas del clúster nuevo comiencen a aparecer en Stackdriver Monitoring.

  3. ¿Hay un heapster que se ejecuta en tu clúster en el espacio de nombres de “kube-system”?

    Es posible que este pod no pueda programar cargas de trabajo porque tu clúster se está quedando sin recursos. Para comprobar si heapster se está ejecutando, puedes llamar a kubectl get pods --namespace=kube-system y buscar pods con heapster en el nombre.

  4. ¿La instancia principal del clúster puede comunicarse con los nodos?

    Stackdriver Monitoring depende de eso. Puedes ejecutar kubectl logs [POD-NAME] para verificar si eso es lo que sucede. Si el comando muestra un error, puede que los túneles SSH sean los que causan el problema. Consulta esta sección.

Si tienes un problema relacionado con el agente de Stackdriver Logging, consulta la documentación del solucionador de problemas.

Para obtener más información, consulta la documentación de Stackdriver Monitoring.

Error 404: Recurso “no encontrado” cuando se llama a los comandos gcloud container

Vuelve a autenticarte a la herramienta de línea de comandos de gcloud:

gcloud auth login

Error 400/403: Faltan permisos de edición en una cuenta

La cuenta de servicio de Compute Engine o Kubernetes Engine se borró o se editó.

Cuando habilitas la API de Compute Engine o Kubernetes Engine, se crea una cuenta de servicio y se le otorga permisos de edición en tu proyecto. Si en algún momento editas los permisos, quitas la cuenta por completo o inhabilitas la API, fallarán la creación de clúster y todas las funcionalidades de administración.

El nombre de tu cuenta de servicio de Google Kubernetes Engine es el siguiente:

service-[PROJECT_NUMBER]@container-engine-robot.iam.gserviceaccount.com

donde [PROJECT_NUMBER] es tu número del proyecto.

Para resolver este problema, debes volver a habilitar la API de Kubernetes Engine, eso restablecerá tus cuentas de servicio y tus permisos.

  1. Visita la página de API y servicios.
  2. Selecciona tu proyecto.
  3. Haz clic en __Habilitar API y servicios__.
  4. Busca Kubernetes y, luego, selecciona la API de los resultados de la búsqueda.
  5. Haz clic en __Habilitar__. Si habilitaste la API antes, primero debes inhabilitarla y habilitarla de nuevo. Puede tomar varios minutos para que la API y los servicios relacionados se habiliten.

De manera alternativa, usa la herramienta de línea de comandos de gcloud siguiente:

gcloud services enable container.googleapis.com

Replica las reglas de firewall automáticas 1.8.x (y anteriores) en 1.9.x y posteriores

Si tu clúster se ejecuta en la versión 1.9.x de Kubernetes, las reglas de firewall automáticas cambiaron a fin de no permitir que cargas de trabajo en un clúster de GKE inicien comunicación con otras VM de Compute Engine que se encuentran fuera del clúster, pero en la misma red.

Puedes replicar el comportamiento de las reglas de firewall automáticas de un clúster 1.8.x (y anterior) si realizas los pasos siguientes:

Primero, encuentra la red del clúster:

gcloud container clusters describe [CLUSTER_NAME] --format=get"(network)"

Luego obtiene el CIDR IPv4 del clúster usado por los contenedores siguientes:

gcloud container clusters describe [CLUSTER_NAME] --format=get"(clusterIpv4Cidr)"

Por último, crea una regla de firewall para la red con el CIDR como el rango de origen y permite todos los protocolos siguientes:

gcloud compute firewall-rules create "[CLUSTER_NAME]-to-all-vms-on-network" --network="[NETWORK]" --source-ranges="[CLUSTER_IPV4_CIDR]" --allow=tcp,udp,icmp,esp,ah,sctp

Restablece la cuenta de servicio predeterminada en tu proyecto de GCP

La cuenta de servicio predeterminada de GKE, container-engine-robot, se puede desvincular de un proyecto por accidente. Agente de servicio de GKE es una función de IAM que le otorga a la cuenta de servicio los permisos para administrar los recursos del clúster. Si quitas esta vinculación de función de la cuenta de servicio, la cuenta de servicio predeterminada se desvincula del proyecto, lo que puede evitar que se implementen aplicaciones y que se realicen otras operaciones de clúster.

Para verificar si la cuenta de servicio se quitó de tu proyecto, puedes ejecutar gcloud projects get-iam-policy [PROJECT_ID] o visitar el menú de IAM y administración en Google Cloud Platform Console. Si el comando o el panel no muestran container-engine-robot entre tus cuentas de servicio, la cuenta de servicio se desvinculó.

Si quitas la vinculación de función de agente de servicio de GKE, ejecuta los comandos siguientes para restablecer la vinculación de función:

PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format "value(projectNumber)")
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member "serviceAccount:service-${PROJECT_NUMBER}@container-engine-robot.iam.gserviceaccount.com" \
  --role roles/container.serviceAgent

Para confirmar que la vinculación de función se otorgó:

gcloud projects get-iam-policy $PROJECT_ID

Si puedes ver el nombre de la cuenta de servicio junto con la función container.serviceAgent, es debido a que se otorgó la vinculación de función. Por ejemplo:

- members:
  - serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
  role: roles/container.serviceAgent

La clave de Cloud KMS está inhabilitada.

La cuenta de servicio predeterminada de GKE no puede usar una clave de Cloud KMS inhabilitada para la encriptación de secretos a nivel de la aplicación.

Para volver a habilitar una clave inhabilitada, consulta Habilita una versión de clave inhabilitada.

Soluciona problemas para cargas de trabajo implementadas

GKE muestra un error si existen problemas con Pods de una carga de trabajo. Puedes verificar el estado de un Pod con la herramienta de línea de comandos kubectl o Google Cloud Platform Console.

kubectl

Para ver todos los Pods en ejecución en tu clúster, ejecuta el comando siguiente:

kubectl get pods

Resultado:

NAME            READY   STATUS              RESTARTS    AGE
[POD_NAME]      0/1     CrashLoopBackOff    23          8d

Para obtener más información sobre un Pod específico:

kubectl describe pod [POD_NAME]

Console

Realiza los pasos siguientes:

  1. Visita el panel de cargas de trabajo de GKE en GCP Console.

    Visitar el panel de cargas de trabajo de GKE

  2. Selecciona la carga de trabajo deseada. La pestaña Descripción general muestra el estado de la carga de trabajo.

  3. Desde la sección Pods administrados, haz clic en el mensaje de error de estado.

En las secciones siguientes se explican algunos errores comunes que muestran las cargas de trabajo y cómo resolverlos.

CrashLoopBackOff

CrashLoopBackOff indica que un contenedor falla repetidas veces después de reiniciar. Un contenedor puede fallar por varias razones y verificar los registros de un pod puede ayudar a solucionar la causa del problema.

Por configuración predeterminada, los contenedores que fallan se reinician con un retraso exponencial limitado a cinco minutos. Puedes cambiar este comportamiento si configuras el campo restartPolicy de la especificación del Pod de implementación como spec: restartPolicy. El valor predeterminado del campo es Always.

Puedes averiguar por qué el contenedor de pod falla mediante la herramienta de línea de comandos kubectl o GCP Console.

kubectl

Para ver todos los Pods en ejecución en tu clúster, ejecuta el comando siguiente:

kubectl get pods

Busca el pod con el error CrashLoopBackOff.

Para obtener los registros del Pod, ejecuta lo siguiente:

kubectl logs [POD_NAME]

en el que [POD_NAME] es el nombre del pod problemático.

También puedes pasar el marcador -p a fin de obtener los registros para la instancia anterior de un contenedor de Pod, si existe uno.

Console

Realiza los pasos siguientes:

  1. Visita el panel de cargas de trabajo de GKE en GCP Console.

    Visitar el panel de cargas de trabajo de GKE

  2. Selecciona la carga de trabajo deseada. La pestaña Descripción general muestra el estado de la carga de trabajo.

  3. En la sección Pods administrados, haz clic en el pod problemático.

  4. En el menú de pods, haz clic en la pestaña Registros.

Verifica el “Código de salida” del contenedor que falla

Puedes encontrarlo en el resultado de kubectl describe pod [POD_NAME] en el campo containers: [CONTAINER_NAME]: last state: exit code.

  • Si el código de salida es 1, el contenedor falló debido a que la aplicación falló.
  • Si el código de salida es 0, verifica por cuánto tiempo se ejecutó la app. Los contenedores salen cuando el proceso principal de la aplicación sale. Si la app finaliza la ejecución muy rápido, el contendor se puede reiniciar.

Conéctate a un contenedor en ejecución

Abre una shell al pod:

kubectl exec -it [POD_NAME] -- /bin/bash

Si hay más de un contenedor en tu pod, agrega -c [CONTAINER_NAME].

Ahora, puedes ejecutar comandos bash desde el contenedor: puedes probar la red o verificar si tienes acceso a los archivos o a las bases de datos que usa tu aplicación.

ImagePullBackOff y ErrImagePull

ImagePullBackOff y ErrImagePull indican que la imagen que usa un contenedor no se puede cargar desde el registro de imagen.

Puedes verificar este problema con GCP Console o con la herramienta de línea de comandos de kubectl.

kubectl

Para obtener más información sobre una imagen de contenedor de un Pod, ejecuta el comando siguiente:

kubectl describe pod [POD_NAME]

Console

Realiza los pasos siguientes:

  1. Visita el panel de cargas de trabajo de GKE en GCP Console.

    Visitar el panel de cargas de trabajo de GKE

  2. Selecciona la carga de trabajo deseada. La pestaña Descripción general muestra el estado de la carga de trabajo.

  3. En la sección Pods administrados, haz clic en el pod problemático.

  4. En el menú de pod, haz clic en la pestaña Eventos.

Si no se encuentra la imagen

Si tu imagen no se encuentra:

  1. Verifica que el nombre de la imagen sea correcto.
  2. Verifica que la etiqueta de la imagen sea correcta. (Prueba con la etiqueta :latest o sin etiqueta para extraer la imagen más reciente).
  3. Si la imagen tiene una ruta de registro completa, verifica que exista en el registro Docker que usas. Si proporcionas solo el nombre de la imagen, verifica el registro de Docker Hub.
  4. Prueba extraer la imagen de Docker de manera manual:

    • Implementa SSH en el nodo:
      Por ejemplo, establecer una conexión mediante SSH en example-instance en la zona us-central1-a:

      gcloud compute ssh example-instance --zone us-central1-a
    • Ejecuta docker pull [IMAGE_NAME].
      Si esa opción funciona, necesitarás especificar ImagePullSecrets en un Pod. Los pods solo pueden hacer referencia a los secretos de extracción de imagen en su propio espacio de nombres, por lo que este proceso puede realizarse una vez por espacio de nombres.

Si encuentras el error “permiso denegado” o “sin acceso de extracción”, verifica que accediste o tienes acceso a la imagen.

Si usas un registro privado, es posible que necesites claves para leer imágenes.

PodUnschedulable

PodUnschedulable indica que tu pod no se puede programar debido a recursos insuficientes o a algún error de configuración.

Recursos insuficientes

Puedes encontrar un error que indique una falta de CPU, memoria o algún otro recurso. Por ejemplo: “No hay nodos disponibles que coincidan con todos los predicados: CPU insuficiente (2)”, que indica que no hay CPU suficiente disponible en dos nodos para cumplir con las solicitudes de un pod.

La solicitud de CPU predeterminada es de 100m o el 10% de una CPU (o un núcleo). Si deseas solicitar más o menos recursos, detalla el valor en la especificación del pod en spec: containers: resources: requests.

MatchNodeSelector

MatchNodeSelector indica que no hay nodos que coincidan con el selector de etiquetas de pods.

Para verificar esto, registra las etiquetas especificadas en el campo de la especificación de Pod nodeSelector, en spec: nodeSelector.

Para ver cómo están etiquetados los nodos en tu clúster, ejecuta el siguiente comando:

kubectl get nodes --show-labels

Para adjuntar una etiqueta a un nodo, ejecuta el siguiente comando:

kubectl label nodes [NODE_NAME] [LABEL_KEY]=[LABEL_VALUE]

Para obtener más información, consulta cómo asignar pods a nodos.

PodToleratesNodeTaints

PodToleratesNodeTaints indica que el pod no se puede programar en ningún nodo debido a que ningún nodo tolera, en la actualidad, su taint de nodo.

Para verificar que este es el caso, ejecuta el comando siguiente:

kubectl describe nodes [NODE_NAME]

En el resultado, verifica el campo Taints, que enumera pares clave-valor y efectos de programación.

Si el efecto enumerado es NoSchedule, entonces no se puede programar ningún Pod en ese nodo, a menos que tenga una tolerancia coincidente.

Una manera de resolver este problema es quitar el taint. Por ejemplo, quitar un taint NoSchedule:

kubectl taint nodes [NODE_NAME] key:NoSchedule-

PodFitsHostPorts

PodFitsHostPorts indica que un puerto que un nodo quiere usar ya está en uso.

Para resolver este problema, verifica el valor de la especificación de Pod hostPort en spec: containers: ports: hostPort. Es posible que debas cambiar este valor para otro puerto.

No tiene disponibilidad mínima

Si un nodo tiene recursos adecuados, pero todavía ves el mensaje Does not have minimum availability, comprueba el estado del pod. Si el estado es SchedulingDisabled o Cordoned, el nodo no puede programar nuevos pods. Para verificar el estado de un nodo, sigue estos pasos:

kubectl

Para obtener los estados de los nodos, ejecuta el comando siguiente:

kubectl get nodes

Para habilitar la programación en el nodo, ejecuta lo siguiente:

kubectl uncordon [NODE_NAME]

Console

Realiza los pasos siguientes:

  1. Visita el panel de cargas de trabajo de GKE en GCP Console.

    Visitar el panel de clústeres de GKE

  2. Selecciona el clúster que desees. La pestaña Nodos muestra los nodos y su estado.

Para habilitar la programación en el nodo, realiza los pasos siguientes:

  1. En la lista, haz clic en el nodo deseado.

  2. En Detalles del nodo, haz clic en el botón Desacordonar.

Problemas de conectividad

Como se mencionó en el debate de Descripción general de la red, es importante comprender cómo los pods están conectados desde sus espacios de nombres de red con el espacio de nombres raíz en el nodo para solucionar problemas de manera efectiva. En el siguiente debate, supone que el clúster usa el CNI nativo de GKE en lugar del de Calico, a menos que se indique lo contrario. Es decir, no se aplicó ninguna política de red.

Los pods en nodos seleccionados no tienen disponibilidad

Si los pods en nodos seleccionados no tienen conectividad de red, asegúrate de que el puente de Linux esté activo:

ip address show cbr0

En caso contrario, actívalo:

sudo ip link set cbr0 up

Asegúrate de que el nodo esté aprendiendo las direcciones MAC de pod adjuntas en cbr0:

arp -an

Los pods en los nodos seleccionados tienen conectividad mínima

Si los pods en los nodos seleccionados tienen una conectividad mínima, primero debes confirmar si hay paquetes perdidos. Para ello, ejecuta tcpdump en el contenedor de la caja de herramientas:

sudo toolbox bash

Instala tcpdump en la caja de herramientas si aún no lo hiciste:

apt install -y tcpdump

Ejecuta tcpdump en cbr0:

tcpdump -ni cbr0 host [HOSTNAME] and port [PORT_NUMBER] and [tcp|udp|icmp]

Si parece que los paquetes grandes se descartan más adelante en el puente (por ejemplo, el protocolo de enlace TCP se completa, pero no se reciben saludos SSL), asegúrate de que la MTU del puente de Linux esté configurada correctamente en 1460 o menos:

ip address show cbr0

Cuando se utilizan superposiciones (por ejemplo, Weave o Flannel), esta MTU debe reducirse aún más para acomodar la sobrecarga de encapsulación en la superposición.

Conexiones fallidas intermitentes

iptables reenvía las conexiones hacia y desde los pods. Los flujos se registran como entradas en la tabla conntrack y, cuando hay muchas cargas de trabajo por nodo, el agotamiento de la tabla de conntrack puede manifestarse como un error. Estos se pueden registrar en la consola en serie del nodo, por ejemplo:

nf_conntrack: table full, dropping packet

Si puedes determinar que los problemas de intermitencia son producto del agotamiento, puedes aumentar el tamaño del clúster (y así reducir la cantidad de cargas de trabajo y flujos por nodo) o aumentar nf_conntrack_max:

new_ct_max=$(awk '$1 == "MemTotal:" { printf "%d\n", $2/32; exit; }' /proc/meminfo)
sysctl -w net.netfilter.nf_conntrack_max="${new_ct_max:?}" \
  && echo "net.netfilter.nf_conntrack_max=${new_ct_max:?}" >> /etc/sysctl.conf

Puedes evitar esto por completo con un clúster nativo de la VPC que no sea NAT.

El contenedor informa un mensaje de “vincular: la dirección ya está en uso”

Un contenedor en un pod no puede iniciarse porque, de acuerdo con los registros del contenedor, el puerto al que la aplicación intenta vincularse ya está reservado. El contenedor entra en una falla de repetición. Por ejemplo, en Stackdriver Logging:

resource.type="container"
textPayload:"bind: Address already in use"
resource.labels.container_name="redis"

2018-10-16 07:06:47.000 CEST 16 Oct 05:06:47.533 # Creating Server TCP listening socket *:60250: bind: Address already in use
2018-10-16 07:07:35.000 CEST 16 Oct 05:07:35.753 # Creating Server TCP listening socket *:60250: bind: Address already in use

Cuando Docker falla, a veces un contenedor en ejecución se retrasa y queda inactivo. El proceso todavía se está ejecutando en el espacio de nombres de red asignado para el pod, y está escuchando en su puerto. Debido a que Docker y el kubelet no saben sobre el contenedor inactivo, intentan iniciar un nuevo contenedor con un nuevo proceso, que no puede vincularse en el puerto, ya que se agrega al espacio de nombres de red ya asociado con el pod.

Para diagnosticar este problema, necesitas el UUID del pod, campo .metadata.uuid:

kubectl get pod -o custom-columns="name:.metadata.name,UUID:.metadata.uid" ubuntu-6948dd5657-4gsgg

name                      UUID
ubuntu-6948dd5657-4gsgg   db9ed086-edba-11e8-bdd6-42010a800164

También obtén el resultado de los siguientes comandos del nodo:

  • docker ps -a
  • ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep [Pod UUID]

Verifica los procesos en ejecución de este Pod. Debido a que el UUID de los espacios de nombres de cgroup contiene el UUID del pod, puedes ejecutar grep para obtener el UUID del pod en el resultado ps. También puedes ejecutar grep para obtener la línea anterior, por lo que tendrás los procesos docker-containerd-shim con el ID del contenedor también en el argumento. Corta el resto de la columna cgroup para obtener un resultado más simple:

# ps -eo pid,ppid,stat,wchan:20,netns,comm,args:50,cgroup --cumulative -H | grep -B 1 db9ed086-edba-11e8-bdd6-42010a800164 | sed s/'blkio:.*'/''/
1283089     959 Sl   futex_wait_queue_me  4026531993       docker-co       docker-containerd-shim 276e173b0846e24b704d4 12:
1283107 1283089 Ss   sys_pause            4026532393         pause           /pause                                     12:
1283150     959 Sl   futex_wait_queue_me  4026531993       docker-co       docker-containerd-shim ab4c7762f5abf40951770 12:
1283169 1283150 Ss   do_wait              4026532393         sh              /bin/sh -c echo hello && sleep 6000000     12:
1283185 1283169 S    hrtimer_nanosleep    4026532393           sleep           sleep 6000000                            12:
1283244     959 Sl   futex_wait_queue_me  4026531993       docker-co       docker-containerd-shim 44e76e50e5ef4156fd5d3 12:
1283263 1283244 Ss   sigsuspend           4026532393         nginx           nginx: master process nginx -g daemon off; 12:
1283282 1283263 S    ep_poll              4026532393           nginx           nginx: worker process

En esta lista, puedes ver los ID del contenedor, que también deben estar visibles en docker ps.

En este caso:

  • docker-containerd-shim 276e173b0846e24b704d4 para pause
  • docker-containerd-shim ab4c7762f5abf40951770 para sh con sleep (sleep-ctr)
  • docker-containerd-shim 44e76e50e5ef4156fd5d3 para nginx (echoserver-ctr)

Verifica los que están en el resultado docker ps:

# docker ps --no-trunc | egrep '276e173b0846e24b704d4|ab4c7762f5abf40951770|44e76e50e5ef4156fd5d3'
44e76e50e5ef4156fd5d383744fa6a5f14460582d0b16855177cbed89a3cbd1f   gcr.io/google_containers/echoserver@sha256:3e7b182372b398d97b747bbe6cb7595e5ffaaae9a62506c725656966d36643cc                   "nginx -g 'daemon off;'"                                                                                                                                                                                                                                                                                                                                                                     14 hours ago        Up 14 hours                             k8s_echoserver-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0
ab4c7762f5abf40951770d3e247fa2559a2d1f8c8834e5412bdcec7df37f8475   ubuntu@sha256:acd85db6e4b18aafa7fcde5480872909bd8e6d5fbd4e5e790ecc09acc06a8b78                                                "/bin/sh -c 'echo hello && sleep 6000000'"                                                                                                                                                                                                                                                                                                                                                   14 hours ago        Up 14 hours                             k8s_sleep-cnt_ubuntu-6948dd5657-4gsgg_default_db9ed086-edba-11e8-bdd6-42010a800164_0
276e173b0846e24b704d41cf4fbb950bfa5d0f59c304827349f4cf5091be3327   k8s.gcr.io/pause-amd64:3.1

En casos normales, verás todos los ID de contenedor de ps que aparecen en docker ps. Si hay uno que no ves, es un contenedor inactivo y, probablemente, verás un proceso secundario del proceso docker-containerd-shim process escuchando en el puerto TCP que informa que ya está en uso.

Para verificar esto, ejecuta netstat en el espacio de nombres de red del contenedor. Obtén el pid de cualquier proceso de contenedor (así que NO docker-containerd-shim) del pod.

En el ejemplo anterior:

  • 1283107 - pause
  • 1283169 - sh
  • 1283185 - sleep
  • 1283263 - nginx master
  • 1283282 - nginx worker
# nsenter -t 1283107 --net netstat -anp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1283263/nginx: mast
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  3      [ ]         STREAM     CONNECTED     3097406  1283263/nginx: mast
unix  3      [ ]         STREAM     CONNECTED     3097405  1283263/nginx: mast

gke-zonal-110-default-pool-fe00befa-n2hx ~ # nsenter -t 1283169 --net netstat -anp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1283263/nginx: mast
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  3      [ ]         STREAM     CONNECTED     3097406  1283263/nginx: mast
unix  3      [ ]         STREAM     CONNECTED     3097405  1283263/nginx: mast

También puedes ejecutar netstat mediante ip netns, pero necesitarás vincular el espacio de nombres de red del proceso de manera manual, ya que Docker no está haciendo el enlace:

# ln -s /proc/1283169/ns/net /var/run/netns/1283169
gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns list
1283169 (id: 2)
gke-zonal-110-default-pool-fe00befa-n2hx ~ # ip netns exec 1283169 netstat -anp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1283263/nginx: mast
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  3      [ ]         STREAM     CONNECTED     3097406  1283263/nginx: mast
unix  3      [ ]         STREAM     CONNECTED     3097405  1283263/nginx: mast
gke-zonal-110-default-pool-fe00befa-n2hx ~ # rm /var/run/netns/1283169

Mitigación:

La mitigación a corto plazo consiste en identificar procesos inactivos mediante el método descrito anteriormente y eliminarlos mediante kill [PID].

La mitigación a largo plazo implica identificar por qué Docker falla y solucionarlo. Algunos motivos posibles son los siguientes:

  • Los procesos zombie se acumulan, por lo que no hay espacios de nombres PID
  • Error en Docker
  • Presión de recursos / OOM
¿Te sirvió esta página? Envíanos tu opinión:

Enviar comentarios sobre…

Documentación de Kubernetes Engine