Dominio de kubectl logs y describe para la depuración eficiente de Pods

Esta guía proporciona técnicas expertas para dominar los comandos esenciales de depuración de Kubernetes: `kubectl logs` y `kubectl describe`. Aprende las banderas críticas, como `-f`, `--tail`, `-c` y `--previous`, necesarias para una resolución de problemas eficiente. Detallamos cómo interpretar la sección crucial de 'Eventos' en `describe` para diagnosticar problemas de programación y configuración, y cómo usar `logs` para extraer errores de tiempo de ejecución de pods que fallan o tienen múltiples contenedores, acelerando tu flujo de trabajo de depuración.

Dominio de kubectl logs y describe para la depuración eficiente de Pods

Cuando un pod de Kubernetes falla, kubectl describe y kubectl logs suelen indicarte dónde buscar a continuación. describe explica lo que Kubernetes intentó hacer. logs muestra lo que el contenedor escribió antes, durante o después del fallo.

Estos comandos proporcionan vistas diferentes, aunque complementarias, del estado y la historia de un Pod de Kubernetes. kubectl describe te proporciona los metadatos del Pod, el estado, las variables de entorno y, crucialmente, un historial de eventos del sistema. kubectl logs proporciona los flujos de salida estándar (stdout) y error estándar (stderr) generados por la propia aplicación contenerizada.

El truco está en usarlos en el orden correcto. Si el pod nunca fue programado, los logs no ayudarán. Si el pod se inicia y sale, los eventos pueden solo decirte que falló; los logs de la aplicación generalmente explican por qué.


El flujo de trabajo de depuración de Pods en tres pasos

Antes de sumergirnos en los comandos, es útil entender el flujo de trabajo típico de depuración:

  1. Verificar el Estado: Usa kubectl get pods para identificar el estado de fallo (Pending, CrashLoopBackOff, ImagePullBackOff, etc.).
  2. Obtener Contexto y Eventos: Usa kubectl describe pod para entender por qué ocurrió la transición de estado (por ejemplo, el scheduler falló, la sonda de vida falló, el volumen no se pudo montar).
  3. Inspeccionar la Salida de la Aplicación: Usa kubectl logs para examinar el comportamiento en tiempo de ejecución de la aplicación (por ejemplo, errores de configuración, fallos de conexión a la base de datos, trazas de pila).

1. kubectl describe: La herramienta de triaje del sistema

kubectl describe es el primer comando que debes ejecutar cuando un Pod se comporta mal. No muestra la salida de la aplicación, pero proporciona los metadatos críticos y el historial que el propio Kubernetes ha registrado sobre el Pod.

Uso básico

El uso fundamental solo requiere el nombre del Pod:

kubectl describe pod my-failing-app-xyz789

Usa espacios de nombres explícitamente cuando no estés en el espacio de nombres predeterminado:

kubectl describe pod my-failing-app-xyz789 -n payments

Si solo conoces el deployment o la etiqueta, encuentra el pod primero:

kubectl get pods -n payments -l app=checkout -o wide

Secciones clave en la salida

Al revisar la salida de describe, concéntrate en estas secciones críticas:

A. Estado y Condición

Mira el campo Status en la parte superior, y luego revisa los estados individuales de los contenedores dentro del Pod. Esto te dice si el contenedor está Running, Waiting o Terminated, y proporciona la razón de ese estado.

Campo Estado/Razón Común Significado
Status Pending El Pod está esperando ser programado o le faltan recursos.
Reason ContainerCreating El runtime del contenedor está descargando la imagen o ejecutando la configuración.
State Waiting / Reason: CrashLoopBackOff El contenedor se inició y salió repetidamente.
State Terminated / Exit Code El contenedor terminó su ejecución. Los códigos de salida distintos de cero generalmente indican errores.

B. Configuración del Contenedor

Esta sección verifica que tus variables de entorno, solicitudes/límites de recursos, montajes de volumen y sondas de vida/readiness estén definidos correctamente, coincidiendo con el manifiesto que aplicaste.

C. La sección Events (Crucial)

La sección Events, ubicada al final de la salida, es posiblemente la parte más valiosa. Proporciona un registro cronológico de lo que el plano de control de Kubernetes hizo al Pod y para él, incluyendo advertencias y errores.

Errores comunes revelados por Events:

  • Problemas de Programación: Warning FailedScheduling: Indica que el scheduler no pudo encontrar un nodo adecuado (por ejemplo, debido a restricciones de recursos, taints del nodo o reglas de afinidad).
  • Fallos en la Descarga de Imágenes: Warning Failed: ImagePullBackOff: Indica que el nombre de la imagen es incorrecto, la etiqueta no existe o a Kubernetes le faltan credenciales para descargar de un registro privado.
  • Errores de Volumen: Warning FailedAttachVolume: Indica problemas para conectar el almacenamiento externo.

Consejo: Si la sección Events está limpia y el contenedor se ha iniciado, el problema suele estar relacionado con la aplicación: una variable de entorno incorrecta, una migración fallida, un secreto faltante, una dependencia inalcanzable o un proceso que sale inmediatamente.

2. kubectl logs: Inspeccionando la salida de la aplicación

Si describe muestra que el Pod fue programado con éxito y los contenedores intentaron ejecutarse, el siguiente paso es verificar los flujos de salida estándar usando kubectl logs.

Recuperación básica de logs y transmisión en tiempo real

Para ver los logs actuales del contenedor principal en un Pod:

# Recuperar todos los logs hasta el momento actual
kubectl logs my-failing-app-xyz789

# Transmitir logs en tiempo real (útil para monitorear el inicio)
kubectl logs -f my-failing-app-xyz789

Manejo de Pods con múltiples contenedores

Para pods que utilizan el patrón Sidecar u otros diseños de múltiples contenedores, debes especificar qué contenedor deseas ver usando la bandera -c o --container.

# Ver logs del contenedor 'sidecar-proxy' dentro del Pod
kubectl logs my-multi-container-pod -c sidecar-proxy

# Transmitir logs del contenedor de la aplicación principal
kubectl logs -f my-multi-container-pod -c main-app

Depuración de contenedores que se reinician (--previous)

Uno de los escenarios de depuración más comunes es el estado CrashLoopBackOff. Cuando un contenedor se reinicia, kubectl logs solo muestra la salida del intento actual (fallido), que a menudo contiene solo el mensaje de inicio antes del fallo.

Para ver los logs de la instancia anterior y terminada, que contiene el error real que causó la salida, usa la bandera --previous (-p):

# Ver logs de la instancia de contenedor anterior y fallida
kubectl logs my-crashloop-pod --previous

# Combinar con la especificación del contenedor si es necesario
kubectl logs my-crashloop-pod -c worker --previous

Limitando la salida

Para logs de alto volumen, recuperar todo el historial puede ser lento o abrumador. Usa --tail para limitar la salida a las últimas N líneas.

# Mostrar solo las últimas 50 líneas de los logs del contenedor
kubectl logs my-high-traffic-app --tail=50

También puedes agregar marcas de tiempo y una ventana de tiempo:

kubectl logs my-high-traffic-app --tail=100 --timestamps
kubectl logs my-high-traffic-app --since=10m

Para un deployment, las versiones recientes de kubectl pueden obtener logs a través del nombre de la carga de trabajo:

kubectl logs deploy/checkout-api -n payments --tail=100

Cuando eso es demasiado amplio, usa un selector de etiquetas:

kubectl logs -n payments -l app=checkout --all-containers=true --tail=50

3. Combinando técnicas para un diagnóstico avanzado

La depuración efectiva a menudo implica cambiar rápidamente entre describe y comandos específicos de logs.

Caso de estudio: Diagnosticando un fallo de la sonda de vida

Imagina un Pod que está atascado en Running pero ocasionalmente se reinicia, causando interrupción.

Paso 1: Verifica describe para la vista del sistema.

kubectl describe pod web-server-dpl-abc

La salida muestra en la sección Events:

Type     Reason      Age   From               Message
----     ------      ----  ----               -------
Warning  Unhealthy   2s    kubelet, node-a01  Liveness probe failed: HTTP GET http://10.42.0.5:8080/health failed: 503 Service Unavailable

Conclusión del Paso 1: El contenedor se está ejecutando, pero la sonda de vida está fallando con un error 503, lo que hace que Kubernetes reinicie el contenedor.

Paso 2: Verifica logs para el contexto de la aplicación.

Ahora, investiga por qué la aplicación está devolviendo un estado 503, que es un fallo a nivel de aplicación.

kubectl logs web-server-dpl-abc --tail=200

La salida del log revela:

2023-10-26 14:01:15 ERROR Database connection failure: Timeout connecting to DB instance 192.168.1.10

Conclusión Final: El Pod se reinicia debido a un fallo de la sonda de vida, y la sonda falla porque la aplicación no puede conectarse a la base de datos. El problema es de red externa o configuración de la base de datos, no del contenedor en sí.

Caso de estudio: Pod pendiente sin logs

Un pod en Pending a menudo no tiene logs de contenedor útiles porque ningún contenedor se ha iniciado todavía.

kubectl get pod report-worker-6f9c7b9b7d-f2q8m -n analytics

Salida:

NAME                                  READY   STATUS    RESTARTS   AGE
report-worker-6f9c7b9b7d-f2q8m        0/1     Pending   0          4m

Ve directamente a describe:

kubectl describe pod report-worker-6f9c7b9b7d-f2q8m -n analytics

Los eventos podrían mostrar:

Warning  FailedScheduling  default-scheduler  0/6 nodes are available: 6 Insufficient memory.

Eso no es un error de la aplicación. El pod está solicitando más memoria de la que el scheduler puede colocar. El siguiente paso es inspeccionar las solicitudes del deployment, la capacidad del clúster, los taints de los nodos y el comportamiento del autoscaler:

kubectl get deploy report-worker -n analytics -o yaml
kubectl top nodes

Caso de estudio: ImagePullBackOff

Para ImagePullBackOff, los logs suelen estar vacíos porque la imagen del contenedor nunca se inició. describe da el error útil:

kubectl describe pod api-7dfb9c8b7f-bd2p9 -n staging

Los mensajes de evento comunes incluyen una etiqueta de imagen que no existe, un fallo de autenticación contra un registro privado o un problema de DNS/red para llegar al registro. La solución podría ser tan simple como corregir la etiqueta:

kubectl set image deploy/api api=registry.example.com/api:2026-05-24 -n staging

O podría requerir verificar el secreto de descarga de la imagen:

kubectl get secret regcred -n staging
kubectl describe serviceaccount default -n staging

Caso de estudio: Pod con múltiples contenedores y una aplicación silenciosa

Los sidecars pueden ocultar la señal si miras el contenedor equivocado. Primero lista los nombres de los contenedores:

kubectl get pod checkout-84f7c9d7bf-px5mx -n payments \
  -o jsonpath='{.spec.containers[*].name}{"\n"}'

Luego inspecciona cada uno deliberadamente:

kubectl logs checkout-84f7c9d7bf-px5mx -n payments -c checkout --tail=100
kubectl logs checkout-84f7c9d7bf-px5mx -n payments -c envoy --tail=100

Si los logs de la aplicación están silenciosos pero los logs del proxy muestran fallos de conexión ascendente, el pod puede estar saludable desde el punto de vista de Kubernetes mientras el tráfico aún falla a través de la configuración del service mesh o del proxy.

Mejores prácticas y advertencias

Práctica Comando Razón
Siempre verifica los logs anteriores kubectl logs --previous Necesario para diagnosticar CrashLoopBackOff. El error crítico casi siempre está en la ejecución anterior.
Especifica contenedores kubectl logs -c <nombre> Evita ambigüedades en Pods con múltiples contenedores y previene la obtención de logs de sidecars no deseados.
Usa etiquetas para operaciones masivas kubectl logs -l app=frontend -f Permite transmitir logs de múltiples Pods que coinciden con un selector simultáneamente (útil para actualizaciones continuas).
Advertencia: Rotación de logs N/A Los nodos de Kubernetes realizan rotación de logs. Los logs más antiguos que la política de retención configurada del nodo (a menudo unos días o basada en el tamaño) se eliminarán y no estarán disponibles a través de kubectl logs. Usa una solución de registro centralizada externa (por ejemplo, Fluentd, Loki, Elastic Stack) para la retención a largo plazo.

Cosas que estos comandos no pueden decirte

kubectl logs solo muestra stdout y stderr del contenedor retenidos por el nodo. Si la aplicación escribe en un archivo dentro del contenedor, kubectl logs puede no mostrar nada. Eso es un problema de diseño de registro, no un problema de kubectl.

kubectl describe muestra el estado del objeto de Kubernetes y eventos recientes, pero los eventos no son registros de auditoría permanentes. Los eventos antiguos caducan. Para investigaciones de larga duración, copia la salida relevante en las notas del incidente.

Ninguno de los comandos reemplaza las métricas. Un pod puede estar ejecutándose y registrando normalmente mientras la limitación de CPU, la presión de memoria o la latencia descendente causan problemas visibles para el usuario. Después de describe y logs, los siguientes comandos suelen ser:

kubectl top pod -n payments
kubectl top node
kubectl get events -n payments --sort-by=.lastTimestamp

Usa describe primero cuando Kubernetes no pudo crear o mantener el pod en ejecución. Usa logs primero cuando el pod se está ejecutando pero la aplicación se comporta mal. Cambia entre ellos hasta que puedas separar los síntomas de la plataforma de los síntomas de la aplicación.

Un flujo de depuración que puedes reutilizar

Cuando estés bajo presión, usa el mismo flujo cada vez:

kubectl get pod <pod> -n <namespace> -o wide
kubectl describe pod <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --all-containers=true --tail=100
kubectl logs <pod> -n <namespace> --all-containers=true --previous --tail=100
kubectl get events -n <namespace> --sort-by=.lastTimestamp

El orden importa. get pod -o wide te dice el nodo, la IP del pod, el recuento de reinicios y la antigüedad. describe te dice detalles de programación, imagen, volumen, sonda y estado del contenedor. Los logs actuales muestran lo que el contenedor en ejecución está haciendo ahora. Los logs anteriores capturan el fallo que ya ocurrió. Los eventos muestran si el mismo problema está ocurriendo en todo el espacio de nombres.

Para deployments, agrega una verificación de rollout:

kubectl rollout status deploy/<name> -n <namespace>
kubectl describe deploy/<name> -n <namespace>
kubectl get rs -n <namespace> -l app=<label>

A veces, el pod que estás depurando es de un ReplicaSet antiguo durante un rollout. Si arreglas el deployment pero sigues leyendo logs de un pod antiguo que se está terminando, puedes perseguir el problema equivocado durante media hora.

Leyendo los reinicios correctamente

La columna RESTARTS es una pista, no un diagnóstico. Un recuento de reinicios de 1 después de un drenaje de nodo puede ser inofensivo. Un recuento de reinicios que aumenta cada minuto es un fallo activo. Usa describe para verificar el último estado:

Last State:     Terminated
  Reason:       Error
  Exit Code:    1
  Started:      Sun, 24 May 2026 10:14:02 +0800
  Finished:     Sun, 24 May 2026 10:14:07 +0800

Un código de salida de 1 generalmente significa que el proceso salió con un error general de la aplicación. 137 a menudo significa que el proceso fue eliminado, comúnmente porque excedió los límites de memoria, aunque debes confirmarlo con el campo Reason y el contexto del runtime del nodo/contenedor. 143 a menudo aparece cuando un proceso recibe SIGTERM durante la terminación normal. No trates cada código de salida distinto de cero como el mismo tipo de fallo.

Cuando se sospeche de memoria, busca:

Reason:       OOMKilled
Exit Code:    137

Luego compara el límite del contenedor con el uso real:

kubectl describe pod <pod> -n <namespace> | rg -A5 'Limits|Requests'
kubectl top pod <pod> -n <namespace>

Si metrics-server no está instalado, kubectl top no funcionará. En ese caso, usa el sistema de métricas de tu plataforma o las herramientas a nivel de nodo.