Obtén información sobre los pasos de la solución de problemas que pueden servirte si tienes dificultades con Google Kubernetes Engine (GKE).
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
Instala el objeto binario
kubectl
mediante la ejecución del siguiente comando:sudo gcloud components update kubectl
Responde “sí” cuando el instalador te solicite modificar la variable de entorno
$PATH
. Si modificas esta variable, podrás usar los comandoskubectl
sin necesidad que escribir la ruta de archivo completa.Como alternativa, agrega la siguiente línea 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/
Ejecuta el siguiente comando para cargar el archivo
.bashrc
(o.bash_profile
) actualizado:source ~/.bashrc
Los comandos kubectl
muestran el error “conexión rechazada”
Establece el contexto del clúster con el siguiente comando:
gcloud container clusters get-credentials cluster-name
Si tienes dudas sobre qué ingresar para cluster-name, usa el siguiente comando para hacer una lista de tus clústeres:
gcloud container clusters list
Los comandos kubectl
muestran el error “no se pudo negociar una versión de 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
dejan de responder
Estos comandos dependen que el plano de control del clúster (instancia principal) pueda comunicarse con los nodos en el clúster. Sin embargo, debido a que el plano de control no está en la misma red de Compute Engine que los 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 claves SSH a fin de agregarlos a la lista de usuarios autorizados de la VM. GKE también agrega una regla de firewall a la red de Compute Engine, lo que permite el acceso SSH desde la dirección IP del plano de control a cada nodo en el clúster.
Si alguno de los comandos kubectl
anteriores no se ejecuta, es probable que el servidor de la API no pueda abrir los túneles SSH con los nodos. Verifica las siguientes causas posibles:
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.
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. Los nodos viejos se quitan del plano de control y se reemplazan por los nodos nuevos.
Las reglas de firewall de la red no permiten el acceso de SSH al plano de control.
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, mediante la solicitud de una clave privada válida). GKE también inserta una regla SSH para cada clúster público con el formatogke-cluster-name-random-characters-ssh
que permite el acceso SSH de forma específica desde el plano de control del clúster hacia los nodos del clúster. Si no existe ninguna de estas reglas, el plano de control no podrá abrir los túneles SSH.Para solucionar esto, vuelve a agregar una regla de firewall que permita el acceso a las VM con las etiquetas que se encuentran en todos los nodos del clúster desde la dirección IP del plano de control.
La entrada de los metadatos comunes del proyecto para las “ssh-keys” está llena.
Si la entrada de metadatos del proyecto llamada "ssh-keys" está cerca del límite de tamaño máximo, GKE no puede agregar su propia clave SSH a fin de habilitarla para abrir túneles SSH. Para ver los metadatos del proyecto, ejecuta el siguiente comando:
gcloud compute project-info describe [--project=PROJECT]
Luego, verifica la longitud de la lista de llaves SSH.
Para arreglarlo, borra algunas de las llaves SSH que ya no sean necesarias.
Estableciste un campo de metadatos con la clave “ssh-keys” en las VM del clúster.
El agente de nodo en las VM prefiere claves SSH por instancia en vez de claves SSH por proyecto completo, por lo que, si estableciste claves SSH de forma específica en los nodos del clúster, los nodos no respetaran la clave SSH del plano de control en los metadatos del proyecto. Para verificarlo, ejecuta
gcloud compute instances describe <VM-name>
y busca un campo que diga “claves 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.
La versión del nodo no es compatible con la versión del plano de control
Verifica qué versión de Kubernetes ejecuta el plano de control de tu clúster y, luego, verifica la versión de Kubernetes que ejecutan los grupos de nodos de tu clúster. Si alguno de los grupos de nodos del clúster tiene más de dos versiones secundarias anteriores al plano de control, es posible que esto genere problemas con tu clúster.
El equipo de GKE realiza actualizaciones periódicas del plano de control del clúster en tu nombre de forma periódica. Los planos de control se actualizan a las versiones estables más nuevas de Kubernetes. De forma predeterminada, los nodos de un clúster tienen habilitada la actualización automática y se recomienda no inhabilitarla.
Si la actualización automática está inhabilitada para los nodos de un clúster y no actualizas manualmente la versión del grupo de nodos a una versión compatible con el plano de control, tu control con el tiempo, el plano de control no será compatible con tus nodos, ya que el plano de control se actualiza automáticamente con el tiempo. La incompatibilidad entre el plano de control y los nodos de tu clúster puede causar problemas inesperados.
La política de compatibilidad de versiones y del sesgo de versiones de Kubernetes garantiza que los planos de control sean compatibles con nodos de hasta dos versiones secundarias inferiores a la del plano de control. Por ejemplo, los planos de control de Kubernetes 1.19 son compatibles con los nodos de Kubernetes 1.19, 1.18 y 1.17. Para resolver este problema, actualiza manualmente la versión del grupo de nodos a una versión compatible con el plano de control.
Si te preocupa el proceso de actualización, lo que genera interrupciones en las cargas de trabajo que se ejecutan en los nodos afectados, sigue los pasos en la sección Migrar las cargas de trabajo de laMigra cargas de trabajo a diferentes tipos de máquina. Estos pasos te permiten migrar con facilidad mediante la creación de un nuevo grupo de nodos y, luego, acordar y purgar el grupo de nodos anterior.
Las métricas del clúster no aparecen en Cloud Monitoring
Asegúrate de haber activado la API de Cloud Monitoring y la API de Cloud Logging en el proyecto y de que lo puedes ver en Cloud Monitoring.
Si el problema persiste, verifica alguna de las posibles causas siguientes:
Asegúrate de que habilitaste la supervisión en tu clúster.
Monitoring está habilitado de forma predeterminada para los clústeres creados desde Google Cloud Console y desde la herramienta de línea de comandos de
gcloud
; pero puedes verificarlo si ejecutas el siguiente comando o haces clic en los detalles del clúster en Cloud Console:gcloud container clusters describe cluster-name
El resultado de este comando debe indicar que “monitoringService” es “monitoring.googleapis.com” y Cloud Monitoring debe estar habilitado en Cloud Console.
Si la supervisión no está habilitada, ejecuta el siguiente comando para habilitarla:
gcloud container clusters update cluster-name --monitoring-service=monitoring.googleapis.com
¿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 de un clúster nuevo comiencen a aparecer Cloud Monitoring.
¿Hay un
heapster
ogke-metrics-agent
(el colector de OpenTelemetry) ejecutándose en el clúster en el espacio de nombres “kube-system”?Es posible que este pod no pueda programar cargas de trabajo porque el clúster se está quedando sin recursos. Para comprobar si OpenTelemetry o Heapster están en ejecución, puedes llamar a
kubectl get pods --namespace=kube-system
y verificar los Pods conheapster
ogke-metrics-agent
en el nombre.¿El plano de control del clúster puede comunicarse con los nodos?
Cloud Monitoring depende de eso. Para verificar si este es el caso, ejecuta el siguiente comando:
kubectl logs pod-name
Si este comando muestra un error, es posible que los túneles SSH causen el problema. Consulta esta sección para obtener más información.
Si tienes un problema relacionado con el agente de Cloud Logging, consulta su documentación de solución de problemas.
Para obtener más información, consulta la documentación de Logging.
Error 404: Recurso “no encontrado” cuando se llama a los comandos gcloud container
Vuelve a autenticarte en 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 predeterminada de Compute Engine o la cuenta de servicio asociada con GKE se borró o editó de forma manual.
Cuando habilitas la API de Compute Engine o la API de Kubernetes Engine, se crea una cuenta de servicio y se le otorgan permisos de edición en el proyecto. Si en algún momento editas los permisos, quitas la función “Agente de servicio de Kubernetes Engine” y la cuenta por completo o inhabilitas la API, la creación de clústeres y la funcionalidad de administración completa fallarán.
El nombre de tu cuenta de servicio de Google Kubernetes Engine es el siguiente, en el que project-number es el número de proyecto:
service-project-number@container-engine-robot.iam.gserviceaccount.com
Para resolver el problema, si quitaste la función Agente de servicios de Kubernetes Engine de la cuenta de servicio de Google Kubernetes Engine, vuelve a agregarla. De lo contrario, debes volver a habilitar la API de Kubernetes Engine, así, se restablecerán las cuentas de servicio y permisos de forma correcta. Puedes hacerlo en la herramienta de gcloud
o en Cloud Console.
Console
Visita API y servicios en Cloud Console.
Selecciona tu proyecto.
Haga clic en Habilitar API y servicios.
Busca Kubernetes y, luego, selecciona la API de los resultados de la búsqueda.
Haz clic en Habilitar. Si habilitaste la API antes, primero debes inhabilitarla y, luego, habilitarla de nuevo. La habilitación de la API y los servicios relacionados puede tomar varios minutos.
gcloud
Ejecuta el siguiente comando en la herramienta de gcloud
:
gcloud services enable container.googleapis.com
Replica las reglas de firewall automáticas 1.8.x (y versiones anteriores) en 1.9.x y versiones 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:
Encuentra la red del clúster:
gcloud container clusters describe cluster-name --format=get"(network)"
Obtén el CIDR IPv4 del clúster que se usa para los contenedores:
gcloud container clusters describe cluster-name --format=get"(clusterIpv4Cidr)"
Crea una regla de firewall para la red, con el CIDR como el rango de origen, y permite todos los protocolos:
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 el proyecto de GCP
La cuenta de servicio predeterminada de GKE, container-engine-robot
, se puede desvincular de un proyecto por accidente. El agente de servicio de GKE es una función de administración de identidades y accesos (IAM) que 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.
Puedes verificar si la cuenta de servicio se quitó del proyecto con la herramienta de gcloud
o Cloud Console.
gcloud
Ejecuta el siguiente comando:
gcloud projects get-iam-policy project-id
Reemplaza project-id con el ID del proyecto.
Console
Visita la página IAM y administración en Cloud Console.
Si en el comando o el panel no se muestra container-engine-robot
entre las 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 siguientes comandos 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ó, usa lo siguiente:
gcloud projects get-iam-policy $PROJECT_ID
Si ves el nombre de la cuenta de servicio junto con la función container.serviceAgent
, 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.
Pods que quedaron en estado pendiente después de habilitar la asignación de nodos
Si tienes un problema con los pods que quedaron en estado pendiente después de habilitar la asignación de nodos, ten en cuenta lo siguiente:
A partir de la versión 1.7.6, GKE reserva CPU y memoria para la sobrecarga de Kubernetes, incluidos Docker y el sistema operativo. Consulta Arquitectura del clúster para obtener información sobre la cantidad de cada tipo de máquina que los pods pueden programar.
Si los pods están pendientes después de una actualización, sugerimos realizar lo siguiente:
Asegúrate de que las solicitudes de CPU y memoria para los pods no excedan su uso máximo. Cuando GKE reserva CPU y memoria para la sobrecarga, los pods no pueden solicitar estos recursos. Los pods que solicitan más CPU o memoria de la que usan evitan que otros pods soliciten estos recursos y es posible que dejen el clúster con poco uso. Para obtener más información, consulta Cómo se programan los pods con solicitudes de recursos.
Considera cambiar el tamaño del clúster. Para obtener instrucciones, consulta Cambia el tamaño de un clúster.
Si deseas revertir este cambio, cambia a una versión inferior del clúster. Para obtener instrucciones, consulta Actualiza un clúster o grupo de nodos de forma manual.
Nodos de clúster privado que se crearon, pero no se unieron al clúster
A menudo, cuando se usan rutas personalizadas y dispositivos de red de terceros en la VPC que usa el clúster privado, la ruta predeterminada (0.0.0.0/0) se redirecciona al dispositivo, en lugar de a la puerta de enlace de Internet predeterminada. Además de la conectividad del plano de control, debes asegurarte de que sea posible acceder a los siguientes destinos:
- *.googleapis.com
- *.gcr.io
- gcr.io
Configura el Acceso privado a Google en los tres dominios. Con esta práctica recomendada, se permite que los nodos nuevos se inicien y se unan al clúster, y se mantiene restringido el tráfico vinculado a Internet.
Soluciona problemas de cargas de trabajo implementadas
GKE muestra un error si existen problemas con los pods de una carga de trabajo.
Puedes verificar el estado de un pod con la herramienta de línea de comandos de kubectl
o Cloud 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, ejecuta el siguiente comando:
kubectl describe pod pod-name
Reemplaza pod-name con el nombre del pod que desees.
Console
Completa los pasos siguientes:
Visita el panel Cargas de trabajo de GKE en Cloud Console.
Selecciona la carga de trabajo deseada. La pestaña Descripción general muestra el estado de la carga de trabajo.
En la sección Pods administrados, haz clic en el mensaje de estado de error.
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 reiniciarse. Un contenedor puede fallar por varias razones y verificar los registros de un pod puede ayudar a solucionar la causa del problema.
De forma predeterminada, los contenedores que fallan se reinician con una demora exponencial limitada a cinco minutos. Puedes cambiar este comportamiento si configuras el campo restartPolicy
de la especificación del pod de la implementación como spec: restartPolicy
. El valor predeterminado del campo es Always
.
Puedes averiguar por qué el contenedor de tu pod falla mediante la herramienta de línea de comandos de kubectl
o Cloud 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 el siguiente comando:
kubectl logs pod-name
Reemplaza pod-name con el nombre del pod problemático.
También puedes pasar la marca -p
para obtener los registros de la instancia anterior del contenedor de un pod, si existe.
Console
Completa los pasos siguientes:
Visita el panel Cargas de trabajo de GKE en Cloud Console.
Selecciona la carga de trabajo deseada. La pestaña Descripción general muestra el estado de la carga de trabajo.
En la sección Pods administrados, haz clic en el pod problemático.
En el menú de pods, haz clic en la pestaña Registros.
Verifica el “Código de salida” del contenedor que falla
Para encontrar el código de salida, realiza las siguientes tareas:
Ejecuta el siguiente comando:
kubectl describe pod pod-name
Reemplaza pod-name con el nombre del pod.
Revisa el valor 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 se detienen cuando el proceso principal de la aplicación se detiene. Si la app finaliza la ejecución con mucha rapidez, es posible que el contenedor continúe con el proceso de reinicio.
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 imágenes.
Puedes verificar este problema mediante Cloud Console o 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
Completa los pasos siguientes:
Visita el panel Cargas de trabajo de GKE en Cloud Console.
Selecciona la carga de trabajo deseada. La pestaña Descripción general muestra el estado de la carga de trabajo.
En la sección Pods administrados, haz clic en el pod problemático.
En el menú de pod, haz clic en la pestaña Eventos.
Si no se encuentra la imagen
Si tu imagen no se encuentra:
- Verifica que el nombre de la imagen sea correcto.
- Verifica que la etiqueta de la imagen sea correcta. (Intenta extraer la última imagen con
:latest
o sin etiqueta). - 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.
Prueba extraer la imagen de Docker de manera manual:
Establece una conexión SSH al nodo:
Por ejemplo, establece una conexión SSH a
example-instance
en la zonaus-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, puede que necesite claves para leer imágenes.
Si la imagen está alojada en Container Registry, la cuenta de servicio asociada con tu grupo de nodos necesita acceso de lectura al depósito de Cloud Storage que contiene la imagen. Consulta la documentación de Container Registry para obtener más detalles.
PodUnschedulable
PodUnschedulable
indica que tu pod no se puede programar debido a que los recursos son insuficientes o que hay 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 del pod.
Para verificar esto, revisa las etiquetas que se especifican en el campo nodeSelector
de la especificación del pod, debajo de 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
Reemplaza lo siguiente:
- node-name con el nodo deseado
- label-key con la clave de la etiqueta
- label-value con el valor de la etiqueta
Para obtener más información, consulta asigna Pods a nodos.
PodToleratesNodeTaints
PodToleratesNodeTaints
indica que el pod no se puede programar en ningún nodo porque, por el momento, ningún nodo tolera su taint de nodo.
Para verificar que este sea 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, para quitar un taint NoSchedule, ejecuta el siguiente comando:
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 hostPort
de la especificación del pod 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 pods nuevos. Puedes verificar el estado de un nodo con Cloud Console o la herramienta de línea de comandos de kubectl
.
kubectl
Para obtener los estados de los nodos, ejecuta el siguiente comando:
kubectl get nodes
Para habilitar la programación en el nodo, ejecuta lo siguiente:
kubectl uncordon node-name
Console
Completa los pasos siguientes:
Visita el panel Cargas de trabajo de GKE en Cloud Console.
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:
En la lista, haz clic en el nodo deseado.
En Detalles del nodo, haz clic en el botón Desvincular.
Desvincula PersistentVolumeClaims
Unbound PersistentVolumeClaims
indica que el pod hace referencia a una PersistentVolumeClaim que no está vinculada. Este error puede ocurrir si no se pudo aprovisionar el PersistentVolume. Puedes verificar que el aprovisionamiento falló, si obtienes los eventos de la PersistentVolumeClaim y los examinas en busca de errores.
Para obtener los eventos, ejecuta el siguiente comando:
kubectl describe pvc statefulset-name-pvc-name-0
Reemplaza lo siguiente:
- statefulset-name con el nombre del objeto StatefulSet
- pvc-name con el nombre del objeto PersistentVolumeClaim
Esto también puede ocurrir si hubo un error de configuración durante el aprovisionamiento previo manual de un PersistentVolume y su vinculación a una PersistentVolumeClaim. Puedes intentar aprovisionar el volumen de nuevo.
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
para 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 la MTU del la red de VPC del clúster.
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 intermitentes se generan debido al agotamiento de conntrack, es recomendable 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
Se informa un mensaje que dice “vincular: la dirección ya está en uso” para un contenedor
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 Cloud Logging, se muestra lo siguiente:
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 proceso nuevo, 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, haz lo siguiente:
Necesitas el UUID del pod en el 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
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 usar el comando grep para buscar el UUID del pod en el resultado
ps
. Usa también el comando grep para analizar la línea anterior, de modo que obtengas los procesosdocker-containerd-shim
que tienen el ID del contenedor 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 de contenedor, que también deben estar visibles en
docker ps
.En este caso, ocurre lo siguiente:
docker-containerd-shim 276e173b0846e24b704d4
para pausardocker-containerd-shim ab4c7762f5abf40951770
para SH con sleep (sleep-ctr)docker-containerd-shim 44e76e50e5ef4156fd5d3
para nginx (echoserver-ctr)
Verifica aquellos en el resultado de
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 endocker ps
. Si hay uno que no ves, es un contenedor inactivo, y es probable que veas un proceso secundario del procesodocker-containerd-shim process
a la escucha 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 NOdocker-containerd-shim
) del pod.En el ejemplo anterior, se incluye lo siguiente:
- 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
medianteip netns
, pero necesitas vincular el espacio de nombres de red del proceso de forma manual, ya que Docker no realiza la vinculación:# 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 con el método descrito antes y finalizar los procesos mediante el comando kill [PID]
.
La mitigación a largo plazo implica identificar por qué Docker falla y solucionar el problema. 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