Kubernetes: CrashLoopBackOff — Back-off restarting failed container
Cómo diagnosticar y resolver CrashLoopBackOff en Kubernetes. Los pasos para ver logs, identificar la causa y corregir el pod que se reinicia en bucle.
¿Por qué ocurre?
CrashLoopBackOff significa que el contenedor arranca, falla, Kubernetes intenta reiniciarlo, vuelve a fallar, y así en bucle con tiempo de espera exponencial. Las causas más comunes son: - Error en la aplicación al iniciar (excepción no capturada, puerto ya en uso) - Variables de entorno o secrets faltantes (DATABASE_URL, API_KEY, etc.) - Imagen Docker incorrecta o comando de inicio mal configurado - Recursos insuficientes (OOMKilled: sin memoria) - Liveness probe demasiado agresiva que mata el contenedor antes de que inicie - Volúmenes no montados o permisos incorrectos en archivos de configuración
Solución paso a paso
1. Diagnóstico inicial — ver estado del pod
# Ver estado de todos los pods
kubectl get pods -n tu-namespace# Ver detalles del pod (buscar "Events" al final)
kubectl describe pod nombre-del-pod -n tu-namespace
# Ver los últimos eventos del namespace
kubectl get events -n tu-namespace --sort-by='.lastTimestamp'
2. Ver los logs del contenedor que crashea
# Logs del contenedor actual
kubectl logs nombre-del-pod -n tu-namespace# Logs del contenedor ANTERIOR (el que crasheó)
kubectl logs nombre-del-pod -n tu-namespace --previous
# Seguir los logs en tiempo real
kubectl logs -f nombre-del-pod -n tu-namespace
3. Entrar al contenedor para depurar (si arranca brevemente)
# Ejecutar shell interactivo
kubectl exec -it nombre-del-pod -n tu-namespace -- /bin/sh# Si bash está disponible
kubectl exec -it nombre-del-pod -n tu-namespace -- /bin/bash
4. Verificar variables de entorno y secrets
# Ver las env vars configuradas en el deployment
kubectl get deployment mi-app -n tu-namespace -o yaml | grep -A 20 env:# Ver los secrets disponibles
kubectl get secrets -n tu-namespace
# Verificar que el secret existe y tiene las claves correctas
kubectl describe secret mi-secret -n tu-namespace
5. Forzar que el pod no se reinicie para poder depurar
# En el deployment, cambiar el comando temporalmente
spec:
containers:
- name: mi-app
image: mi-imagen:latest
# Reemplazar el comando normal por un sleep infinito
command: ["/bin/sh", "-c", "sleep infinity"]
# Ahora el pod no crashea y puedes entrar y ejecutar el comando original
kubectl exec -it nombre-del-pod -- /bin/sh
# Dentro: ejecutar tu app manualmente
node server.js
6. OOMKilled: aumentar límites de memoria
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi" # ← Aumentar si el pod se mata por OOM
cpu: "500m"
7. Liveness probe demasiado agresiva
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30 # ← Dar tiempo a que la app inicie
periodSeconds: 10
failureThreshold: 3
Cómo evitarlo en el futuro
- Prueba siempre la imagen Docker localmente antes de desplegarla: `docker run --env-file .env mi-imagen` - Configura `initialDelaySeconds` en liveness probes según el tiempo real de arranque de tu app - Usa `kubectl rollout undo deployment/mi-app` para revertir un despliegue problemático - Implementa un endpoint `/health` que verifique las dependencias (DB, Redis) de la app - Configura alertas en tu sistema de monitoreo para CrashLoopBackOff
¿Quieres que una IA te ayude? Genera el prompt perfecto para tu error:
Generador de Prompts