Terminal mostrando el error CrashLoopBackOff en Kubernetes
|

CrashLoopBackOff en Kubernetes: causas y soluciones

CrashLoopBackOff es uno de los errores mas frecuentes en Kubernetes. El pod arranca, falla, Kubernetes lo reinicia, vuelve a fallar… y entra en un bucle. En este post te explico todas las causas posibles y como diagnosticarlo y solucionarlo paso a paso. Si acabas de empezar con Kubernetes, te recomiendo leer primero el post de Kubernetes para principiantes.

Que significa CrashLoopBackOff en Kubernetes

CrashLoopBackOff no es un error en si mismo — es el estado que muestra Kubernetes cuando un contenedor falla repetidamente al arrancar. El sufijo «BackOff» indica que Kubernetes va aumentando el tiempo de espera entre reinicios (10s, 20s, 40s… hasta 5 minutos) para no saturar el sistema.

# Ver el estado de los pods
kubectl get pods

# Salida tipica:
# NAME          READY   STATUS             RESTARTS   AGE
# mi-app-xyz    0/1     CrashLoopBackOff   5          3m

Paso 1: Lo primero siempre es ver los logs

Igual que con Systemd, el log es tu mejor amigo. El contenedor crash justo al arrancar, pero los logs del intento anterior siguen disponibles:

# Ver logs del contenedor (intento actual)
kubectl logs mi-app-xyz

# Ver logs del intento ANTERIOR (el que crasheo)
kubectl logs mi-app-xyz --previous

# Ver logs en tiempo real mientras el pod intenta arrancar
kubectl logs mi-app-xyz -f

# Ver los ultimos 50 logs
kubectl logs mi-app-xyz --tail=50

Paso 2: Describir el pod para mas contexto

kubectl describe pod mi-app-xyz

Busca en la seccion «Events» al final del output — ahi suele estar la causa real. Lineas como estas son muy informativas:

# Ejemplos de eventos tipicos:
Back-off restarting failed container
Error: failed to create containerd task: ... no such file or directory
OOMKilled: container exceeded memory limit
Liveness probe failed: ...
Error: secret "mi-secreto" not found

Causas mas comunes de CrashLoopBackOff

Causa 1: Error en la aplicacion al arrancar

La causa mas frecuente. La aplicacion falla al inicializarse por un error de codigo, configuracion o dependencia.

# Ver el error en los logs
kubectl logs mi-app-xyz --previous

# Ejemplos tipicos:
# Error: Cannot connect to database
# SyntaxError: Unexpected token in config.json
# FATAL: required env variable APP_SECRET not set

La solucion depende del error especifico. Lo mas habitual es que falte una variable de entorno o una conexion a base de datos.

Causa 2: Variables de entorno o secrets que faltan

# Verificar variables de entorno del pod
kubectl exec mi-app-xyz -- env

# Verificar que el secret existe
kubectl get secret mi-secreto

# Verificar que el configmap existe
kubectl get configmap mi-config

# Ver el contenido del configmap
kubectl describe configmap mi-config

Causa 3: OOMKilled — el contenedor se queda sin memoria

Kubernetes mata el contenedor cuando supera el limite de memoria definido en el deployment. Aparece como «OOMKilled» en el describe.

# Verificar si fue OOMKilled
kubectl describe pod mi-app-xyz | grep -A5 "Last State"

# Salida:
# Last State: Terminated
#   Reason: OOMKilled
#   Exit Code: 137

# Solucion: aumentar el limite de memoria en el deployment
resources:
  requests:
    memory: "128Mi"
  limits:
    memory: "512Mi"   # aumentar este valor

Causa 4: Imagen incorrecta o que no existe

# Error tipico en el describe:
# Failed to pull image "mi-app:latest": ... not found

# Verificar la imagen del deployment
kubectl get deployment mi-app -o yaml | grep image

# Soluciones:
# 1. Corregir el nombre o tag de la imagen
# 2. Crear el imagePullSecret si es un registry privado
kubectl create secret docker-registry mi-registry-secret   --docker-server=registry.ejemplo.com   --docker-username=user   --docker-password=password

Causa 5: Liveness probe mal configurada

Si la liveness probe falla antes de que la aplicacion este lista, Kubernetes reinicia el pod continuamente.

# Error tipico:
# Liveness probe failed: HTTP probe failed with statuscode: 500

# Solucion: aumentar initialDelaySeconds para dar tiempo a la app
livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30   # dar 30s para que arranque
  periodSeconds: 10
  failureThreshold: 3

Causa 6: El comando del contenedor termina inmediatamente

Si el proceso principal del contenedor termina, Kubernetes lo reinicia. Tipico en scripts que se ejecutan y terminan, o en contenedores con un CMD incorrecto.

# Error: el contenedor vive 0-2 segundos y muere

# Verificar el comando del contenedor
kubectl get pod mi-app-xyz -o yaml | grep -A5 command

# Depurar ejecutando el contenedor con un comando que no termine
kubectl run debug-pod   --image=mi-app:latest   --command -- sleep 3600

# Luego conectarse y ejecutar el comando manualmente
kubectl exec -it debug-pod -- bash

Workflow de diagnostico para CrashLoopBackOff

  1. kubectl logs mi-pod --previous — ver el error del ultimo crash
  2. kubectl describe pod mi-pod — ver eventos y estado del contenedor
  3. Buscar «OOMKilled», «Error», «Liveness probe failed» en el output
  4. Verificar variables de entorno y secrets: kubectl get secret
  5. Si la imagen falla: kubectl describe pod en la seccion «Events»
  6. Si no ves el error: ejecuta el contenedor con sleep 3600 y depura desde dentro

Conclusion

CrashLoopBackOff siempre tiene una causa concreta. El 90% de los casos se resuelven con los dos primeros pasos: kubectl logs --previous y kubectl describe pod. El log siempre te dice que ha pasado, solo hay que saber leerlo.

En el proximo post veremos Pods, Deployments y Services en detalle. Tienes algun CrashLoopBackOff que no hayas podido resolver? Dejalo en los comentarios.

¡No te pierdas los próximos posts!

¡No hacemos spam! Lee nuestra política de privacidad para obtener más información.

Publicaciones Similares

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *