Solución de problemas: ¿Por qué mi Pod de Kubernetes está atascado en Pending o CrashLoopBackOff?
Los Pods de Kubernetes atascados en `Pending` o `CrashLoopBackOff` pueden detener los despliegues. Esta guía completa desmitifica estos estados comunes, ofreciendo pasos prácticos y detallados para solucionar problemas. Aprende a diagnosticar problemas como restricciones de recursos, errores de extracción de imágenes, fallos de aplicación y configuraciones incorrectas de sondas usando comandos `kubectl`. Poténciate con información práctica y mejores prácticas para resolver rápidamente problemas de Pods y mantener un entorno Kubernetes robusto y confiable, asegurando que tus aplicaciones estén siempre en funcionamiento.
Solución de problemas: ¿Por qué mi Pod de Kubernetes está atascado en Pending o CrashLoopBackOff?
Pending y CrashLoopBackOff se ven similares cuando esperas un despliegue, pero significan cosas muy diferentes. Pending generalmente significa que Kubernetes no ha podido colocar o preparar el pod. CrashLoopBackOff significa que el contenedor se inició, luego salió, y Kubernetes está retrasando el próximo reinicio.
Esa diferencia importa. Un pod pendiente suele ser un problema del scheduler, de la imagen o de almacenamiento. Un pod que falla suele ser un problema de la aplicación, comando, sonda, permisos o memoria. Comienza con esa división y el camino de solución de problemas se acorta mucho.
Entendiendo los Estados de los Pods: Pending vs. CrashLoopBackOff
Antes de sumergirte en la solución de problemas, es esencial entender qué significan estos dos estados.
Estado del Pod: Pending
Un Pod en estado Pending significa que Kubernetes ha aceptado el objeto Pod, pero no se ha movido completamente a un estado de contenedor en ejecución. A veces no se ha programado en un nodo. A veces tiene un nodo asignado, pero la extracción de la imagen, el montaje del volumen o la configuración del sandbox no se han completado.
Estado del Pod: CrashLoopBackOff
Un Pod en estado CrashLoopBackOff significa que un contenedor dentro del Pod se está iniciando, fallando y reiniciando repetidamente. Kubernetes implementa un retraso de retroceso exponencial entre reinicios para evitar abrumar al nodo. Este estado casi siempre apunta a un problema con la aplicación que se ejecuta dentro del contenedor o su entorno inmediato.
Un caso sutil: un contenedor puede salir con código 0 y aún así entrar en un bucle de reinicio si la carga de trabajo se supone que es un servidor de larga duración. Eso sucede a menudo cuando un Deployment ejecuta un comando único por error, como un script de migración o un comando de shell que finaliza inmediatamente.
Solución de Problemas de Pods en Estado Pending
Cuando un Pod está Pending, el primer lugar para mirar es el scheduler y el nodo al que está intentando llegar. Aquí están las causas comunes y los pasos de diagnóstico.
1. Recursos Insuficientes en los Nodos
Una de las razones más frecuentes para que un Pod esté Pending es que ningún nodo en el clúster tiene suficientes recursos disponibles (CPU, memoria) para satisfacer las requests del Pod. El scheduler no puede encontrar un nodo adecuado.
Pasos de Diagnóstico:
Describe el Pod: El comando
kubectl describe podes tu mejor amigo aquí. A menudo mostrará eventos detallando por qué el Pod no puede ser programado.kubectl describe pod <nombre-del-pod> -n <namespace>Busca eventos como "
FailedScheduling" y mensajes como "0/3 nodes are available: 3 Insufficient cpu" o "memory".Verifica los Recursos del Nodo: Mira el uso actual de recursos y la capacidad de tus nodos.
kubectl get nodes kubectl top nodes # (requiere metrics-server)
Solución:
- Aumenta la Capacidad del Clúster: Agrega más nodos a tu clúster de Kubernetes.
- Ajusta las Solicitudes de Recursos del Pod: Reduce las
requestsde CPU y memoria en el manifiesto de tu Pod si están configuradas demasiado altas.resources: requests: memory: "128Mi" cpu: "250m" - Desaloja Otros Pods: Desaloja manualmente Pods de menor prioridad de los nodos para liberar recursos (úsalo con precaución).
2. Errores de Extracción de Imagen
Si Kubernetes puede programar el Pod en un nodo, pero el nodo falla al extraer la imagen del contenedor, el Pod permanecerá Pending.
Causas Comunes:
- Nombre/Etiqueta de Imagen Incorrectos: Errores tipográficos en el nombre de la imagen o uso de una etiqueta inexistente.
- Autenticación de Registro Privado: Faltan o son incorrectos los
ImagePullSecretspara registros privados. - Problemas de Red: El nodo no puede alcanzar el registro de imágenes.
Pasos de Diagnóstico:
Describe el Pod: Nuevamente,
kubectl describe podes clave. Busca eventos como "Failed" o "ErrImagePull" o "ImagePullBackOff".kubectl describe pod <nombre-del-pod> -n <namespace>Ejemplo de evento de salida:
Failed to pull image "my-private-registry/my-app:v1.0": rpc error: code = Unknown desc = Error response from daemon: pull access denied for my-private-registry/my-app, repository does not exist or may require 'docker login'Verifica ImagePullSecrets: Asegúrate de que
imagePullSecretsestén configurados correctamente en tu Pod o ServiceAccount.kubectl get secret <tu-secreto-de-extraccion-de-imagen> -o yaml -n <namespace>
Solución:
- Corrige el Nombre/Etiqueta de la Imagen: Vuelve a verificar el nombre y la etiqueta de la imagen en tu manifiesto de despliegue.
- Configura ImagePullSecrets: Asegúrate de haber creado un secreto
docker-registryy lo hayas vinculado a tu Pod o ServiceAccount.
Luego, agrégalo a la especificación de tu Pod:kubectl create secret docker-registry my-registry-secret \n --docker-server=tu-registro.com \n --docker-username=tu-usuario \n --docker-password=tu-contraseña \n --docker-email=tu-email -n <namespace>spec: imagePullSecrets: - name: my-registry-secret containers: ... - Conectividad de Red: Verifica la conectividad de red desde el nodo al registro de imágenes.
Si estás usando un registro privado, verifica también la ServiceAccount. Muchos equipos adjuntan imagePullSecrets a la ServiceAccount predeterminada del namespace en lugar de a cada Deployment:
kubectl get serviceaccount default -n <namespace> -o yaml
Si el secreto existe pero la extracción aún falla, confirma que el nombre de host del registro en el secreto coincida exactamente con el nombre de host en la referencia de la imagen. registry.example.com/app:v1 y https://registry.example.com/app:v1 no son la misma referencia.
3. Problemas Relacionados con Volúmenes
Si tu Pod requiere un PersistentVolumeClaim (PVC) y el PersistentVolume (PV) correspondiente no se puede aprovisionar o vincular, el Pod permanecerá Pending.
Pasos de Diagnóstico:
Describe el Pod: Busca eventos relacionados con volúmenes.
kubectl describe pod <nombre-del-pod> -n <namespace>Los eventos podrían mostrar
FailedAttachVolume,FailedMounto mensajes similares.Verifica el Estado del PVC y PV: Inspecciona el estado del PVC y PV.
kubectl get pvc <nombre-del-pvc> -n <namespace> kubectl get pvBusca PVCs atascados en
Pendingo PVs no vinculados.
Solución:
- Asegura StorageClass: Asegúrate de que un
StorageClassesté definido y disponible, especialmente si se usa aprovisionamiento dinámico. - Verifica la Disponibilidad del PV: Si se usa aprovisionamiento estático, asegúrate de que el PV exista y coincida con los criterios del PVC.
- Verifica los Modos de Acceso: Asegúrate de que los modos de acceso (por ejemplo,
ReadWriteOnce,ReadWriteMany) sean compatibles.
También verifica si el pod está programado en una zona donde el volumen se pueda adjuntar. En clústeres en la nube, un disco creado en una zona de disponibilidad puede no adjuntarse a un nodo en otra. El evento generalmente menciona la afinidad del nodo del volumen o un error de adjuntar. En ese caso, la solución puede ser restricciones de programación, un StorageClass diferente o recrear el volumen en la zona correcta.
4. Taints, Tolerations y Node Selectors
Un pod puede permanecer Pending incluso cuando el clúster tiene mucha CPU y memoria. El scheduler también debe respetar las reglas de colocación.
Ejemplos comunes:
- El pod tiene un
nodeSelectorque no coincide con ningún nodo. - El pod requiere una afinidad de nodo demasiado estricta.
- Los únicos nodos que coinciden tienen taints, y el pod no tiene toleration coincidente.
- El namespace tiene una cuota que bloquea los recursos solicitados.
Primero verifica los eventos de programación:
kubectl describe pod <nombre-del-pod> -n <namespace>
Luego compara las reglas de colocación del pod con las etiquetas del nodo:
kubectl get pod <nombre-del-pod> -n <namespace> -o yaml
kubectl get nodes --show-labels
kubectl describe node <nombre-del-nodo>
Si el evento dice que un taint no fue tolerado, programa el pod en otro lugar o agrega una toleration solo si esa carga de trabajo realmente pertenece a esos nodos. No toleres ciegamente cada taint. Los taints a menudo protegen nodos especiales, nodos GPU, nodos de infraestructura o nodos bajo presión.
Solución de Problemas de Pods en Estado CrashLoopBackOff
Un estado CrashLoopBackOff indica un problema a nivel de aplicación. El contenedor se inició con éxito pero luego salió con un error, lo que provoca que Kubernetes lo reinicie repetidamente.
1. Errores de Aplicación
La causa más común es que la aplicación en sí misma no pueda iniciarse o encuentre un error fatal poco después de iniciarse.
Causas Comunes:
- Faltan Dependencias/Configuración: La aplicación no puede encontrar archivos de configuración críticos, variables de entorno o servicios externos de los que depende.
- Comando/Argumentos Incorrectos: El
commandoargsespecificados en la especificación del contenedor son incorrectos o llevan a una salida inmediata. - Errores de Lógica de la Aplicación: Errores en el código de la aplicación que causan que falle al iniciar.
Pasos de Diagnóstico:
Ver los Logs del Pod: Este es el paso más crítico. Los logs a menudo mostrarán el mensaje de error exacto que causó que la aplicación fallara.
kubectl logs <nombre-del-pod> -n <namespace>Si el Pod está fallando repetidamente, los logs podrían mostrar la salida del intento fallido más reciente. Para ver los logs de una instancia anterior de un contenedor que falla, usa la bandera
-p(previous):kubectl logs <nombre-del-pod> -p -n <namespace>Describe el Pod: Busca
Restart Counten la secciónContainers, que indica cuántas veces ha fallado el contenedor. También, verificaLast StateparaExit Code.kubectl describe pod <nombre-del-pod> -n <namespace>Un código de salida de
0generalmente significa un apagado graceful, pero cualquier código de salida distinto de cero significa un error. Los códigos de salida comunes distintos de cero incluyen1(error general),137(SIGKILL, a menudo OOMKilled),139(SIGSEGV, fallo de segmentación).
Solución:
- Revisa los Logs de la Aplicación: Basado en los logs, depura el código de tu aplicación o configuración. Asegúrate de que todas las variables de entorno,
ConfigMapsySecretsrequeridos estén montados/inyectados correctamente. - Prueba Localmente: Intenta ejecutar la imagen del contenedor localmente con las mismas variables de entorno y comandos para reproducir y depurar el problema.
Si el pod tiene múltiples contenedores, siempre especifica el nombre del contenedor:
kubectl logs <nombre-del-pod> -c <nombre-del-contenedor> -n <namespace>
kubectl logs <nombre-del-pod> -c <nombre-del-contenedor> -p -n <namespace>
Sin -c, podrías estar leyendo los logs del sidecar mientras la aplicación principal es la que está fallando.
2. Fallo de las Sondas de Liveness y Readiness
Kubernetes usa sondas de Liveness y Readiness para determinar la salud y disponibilidad de tu aplicación. Si una sonda de liveness falla continuamente, Kubernetes reiniciará el contenedor, llevando a CrashLoopBackOff.
Pasos de Diagnóstico:
Describe el Pod: Verifica las definiciones de las sondas
LivenessyReadinessy suLast Stateen la secciónContainers.kubectl describe pod <nombre-del-pod> -n <namespace>Busca mensajes que indiquen fallos de sonda, como "
Liveness probe failed: HTTP probe failed with statuscode: 500".Revisa los Logs de la Aplicación: A veces los logs de la aplicación proporcionarán contexto sobre por qué el endpoint de la sonda está fallando.
Solución:
- Ajusta la Configuración de la Sonda: Corrige el
path,port,command,initialDelaySeconds,periodSecondsofailureThresholdde la sonda. - Asegura la Salud del Endpoint de la Sonda: Verifica que el endpoint de la aplicación al que apunta la sonda esté realmente saludable y responda como se espera. La aplicación podría estar tomando demasiado tiempo para iniciar, requiriendo un
initialDelaySecondsmás grande.
Para aplicaciones de inicio lento, considera un startupProbe. Le da a la aplicación más tiempo para inicializarse antes de que la sonda de liveness comience a juzgarla. Esto es más limpio que establecer un initialDelaySeconds de liveness enorme para cada reinicio.
3. Límites de Recursos Excedidos
Si un contenedor intenta consistentemente usar más memoria que su memory.limit o tiene la CPU estrangulada debido a exceder su cpu.limit, el kernel podría terminar el proceso, a menudo con un evento OOMKilled (Out Of Memory Killed).
Pasos de Diagnóstico:
Describe el Pod: Busca
OOMKilleden la secciónLast StateoEvents. UnExit Code: 137a menudo indica un eventoOOMKilled.kubectl describe pod <nombre-del-pod> -n <namespace>Verifica
kubectl top: Simetrics-serverestá instalado, usakubectl top podpara ver el uso real de recursos de tus Pods.kubectl top pod <nombre-del-pod> -n <namespace>
Solución:
- Aumenta los Límites de Recursos: Si tu aplicación realmente necesita más recursos, aumenta los
limitsdememoryy/ocpuen el manifiesto de tu Pod. Esto podría requerir más capacidad en tus nodos.resources: requests: memory: "256Mi" cpu: "500m" limits: memory: "512Mi" # Aumenta esto cpu: "1000m" # Aumenta esto - Optimiza la Aplicación: Perfila tu aplicación para identificar y reducir su consumo de recursos.
4. Problemas de Permisos
Los contenedores podrían fallar si carecen de los permisos necesarios para acceder a archivos, directorios o recursos de red que requieren.
Pasos de Diagnóstico:
- Revisa los Logs: Los logs de la aplicación podrían mostrar errores de permiso denegado (
EACCES). - Describe el Pod: Verifica el
ServiceAccountque se está usando y cualquier configuración desecurityContextmontada.
Solución:
- Ajusta
securityContext: ConfigurarunAsUser,fsGroupoallowPrivilegeEscalationsegún sea necesario. - Permisos de ServiceAccount: Asegúrate de que el
ServiceAccountasociado con el Pod tenga losRolesyClusterRolesnecesarios vinculados a través deRoleBindingsyClusterRoleBindings. - Permisos de Volumen: Asegúrate de que los volúmenes montados (por ejemplo,
emptyDir,hostPath,ConfigMap,Secret) tengan los permisos correctos para el usuario del contenedor.
Un Árbol de Decisión Rápido
Cuando alguien dice "el pod está roto", ejecuta estos en orden:
kubectl get pod <nombre-del-pod> -n <namespace> -o wide
kubectl describe pod <nombre-del-pod> -n <namespace>
kubectl logs <nombre-del-pod> -n <namespace> --all-containers=true --tail=100
kubectl logs <nombre-del-pod> -n <namespace> --all-containers=true -p --tail=100
Luego bifurca:
- Si no hay nodo en
kubectl get pod -o wide, concéntrate en la programación: requests, taints, afinidad, cuota y disponibilidad del nodo. - Si hay un nodo pero el evento menciona extracción de imagen, concéntrate en el nombre de la imagen, etiqueta, autenticación del registro y acceso de red del nodo al registro.
- Si el evento menciona montaje o adjuntar, concéntrate en PVCs, PVs, StorageClass, modos de acceso y ubicación de zona.
- Si el pod se inicia y luego se reinicia, concéntrate en logs, código de salida, sondas, comando/args, configuración, secretos y límites de memoria.
Este orden evita un error común: leer logs de aplicación para un pod que nunca inició un contenedor de aplicación.
Leyendo Códigos de Salida Sin Sobrerreaccionar
Los códigos de salida son pistas, no explicaciones completas.
1generalmente significa que la aplicación devolvió un error general. Los logs importan más que el número.2puede apuntar a errores de uso de línea de comandos en muchos programas.126a menudo significa que el comando existe pero no puede ejecutarse.127a menudo significa que el comando no fue encontrado.137aparece comúnmente cuando el proceso recibeSIGKILL; en Kubernetes eso a menudo, pero no siempre, está conectado a OOMKilled.143significa que el proceso recibióSIGTERM, lo que puede ocurrir durante la terminación normal.
Si el código de salida es 137, verifica el Last State del pod y los eventos antes de asumir una fuga de memoria. Un drenaje de nodo, desalojo o eliminación manual también pueden terminar un contenedor.
Pasos de Diagnóstico Generales y Herramientas
Aquí hay una lista de verificación rápida de comandos para ejecutar cuando enfrentes problemas de Pods:
- Obtén una Visión General Rápida: Verifica el estado de tus Pods.
kubectl get pods -n <namespace> kubectl get pods -n <namespace> -o wide - Información Detallada del Pod: El comando más crucial para entender eventos, estados y condiciones del Pod.
kubectl describe pod <nombre-del-pod> -n <namespace> - Logs del Contenedor: Mira lo que tu aplicación está reportando.
kubectl logs <nombre-del-pod> -n <namespace> kubectl logs <nombre-del-pod> -p -n <namespace> # Instancia anterior kubectl logs <nombre-del-pod> -f -n <namespace> # Seguir logs - Eventos a Nivel de Clúster: A veces el problema no es con un Pod específico sino un evento a nivel de clúster (por ejemplo, presión en el nodo).
kubectl get events -n <namespace> - Depuración Interactiva: Si tu contenedor se inicia pero falla rápidamente, podrías poder hacer
execen él por un breve momento o en un contenedor de depuración separado si está configurado.
(Nota: Esto funciona solo si el contenedor permanece vivo el tiempo suficiente para adjuntarse.)kubectl exec -it <nombre-del-pod> -n <namespace> -- bash
Mejores Prácticas para Evitar Problemas de Pods
La prevención siempre es mejor que la cura. Seguir estas mejores prácticas puede reducir significativamente los incidentes de Pending y CrashLoopBackOff:
- Establece Solicitudes y Límites de Recursos Realistas: Comienza con
requestsylimitsrazonables, luego ajústalos basándote en la creación de perfiles y monitoreo de la aplicación. - Usa Etiquetas de Imagen Específicas: Evita las etiquetas
latesten producción. Usa etiquetas inmutables (por ejemplo,v1.2.3,commit-sha) para la reproducibilidad. - Implementa Sondas Robusta: Configura sondas
livenessyreadinessque reflejen con precisión la salud de tu aplicación. Ten en cuenta los tiempos de inicio coninitialDelaySeconds. - Registro y Monitoreo Centralizados: Usa herramientas como Prometheus, Grafana, ELK stack o servicios de registro nativos de la nube para recopilar y analizar logs y métricas de Pods.
- Control de Versiones para Manifiestos: Almacena tus manifiestos de Kubernetes en un sistema de control de versiones (por ejemplo, Git) para rastrear cambios y facilitar reversiones.
- Pruebas Exhaustivas: Prueba tus imágenes de contenedor y despliegues de Kubernetes en entornos de desarrollo y staging antes de desplegar en producción.
- Apagados Graceful: Asegúrate de que tus aplicaciones manejen las señales
SIGTERMpara apagados graceful, permitiéndoles liberar recursos antes de la terminación.
Lo Que Generalmente lo Soluciona Más Rápido
Para Pending, kubectl describe pod es generalmente el camino más rápido porque los eventos del scheduler y kubelet explican lo que Kubernetes no pudo hacer. Para CrashLoopBackOff, los logs anteriores son generalmente el camino más rápido porque el contenedor actual puede ser demasiado nuevo para mostrar el fallo que causó el bucle.
Después de arreglar el problema inmediato, busca el paso de prevención: requests del tamaño adecuado, mejores etiquetas de imagen, una sonda de inicio, una verificación de secreto faltante en CI o un runbook más claro. El mejor incidente de pod es aquel que se vuelve más fácil de reconocer la próxima vez.