--- title: "Cómo solucionar los errores más comunes de Kubernetes" description: "Diagnostica pods en CrashLoopBackOff, Pending o ImagePullBackOff, fallos de DNS y Services sin endpoints en Kubernetes con kubectl describe, logs y debug." category: "Kubernetes Avanzado" language: es source: https://cubepath.com/es/docs/kubernetes-avanzado/solucion-de-problemas-comunes-de-kubernetes updated: 2026-09-25 --- # Cómo solucionar los errores más comunes de Kubernetes La mayoría de incidencias en Kubernetes se repiten: un contenedor que se reinicia en bucle, un pod que no encuentra nodo, una imagen que no se descarga o un Service que no responde. En esta guía aprenderás un método de diagnóstico con `kubectl` y lo aplicarás a los errores más frecuentes, con la causa típica y la corrección de cada uno. Los comandos funcionan en cualquier clúster reciente, ya sea kubeadm, K3s o MicroK8s. ## Requisitos previos - Un clúster de Kubernetes y `kubectl` configurado con permisos para leer pods, eventos y logs en el namespace afectado. Si tu clúster corre en un VPS de CubePath con Ubuntu 24.04, puedes trabajar directamente desde el nodo del plano de control. - metrics-server instalado si quieres usar `kubectl top`. En los ejemplos, `your_namespace` es el namespace de la aplicación y `your_pod` el nombre del pod. Para no repetir `-n` en cada comando, puedes fijar el namespace en el contexto actual: ```bash kubectl config set-context --current --namespace=your_namespace ``` ## Paso 1: Seguir un método de diagnóstico Ante cualquier fallo, sigue siempre el mismo orden, de lo general a lo concreto: 1. **Estado**: `kubectl get pods` te dice en qué fase está el pod y cuántas veces se ha reiniciado. 2. **Eventos**: `kubectl describe pod` muestra al final los eventos del planificador, del kubelet y de la descarga de imágenes. Aquí está la causa de casi todos los `Pending` e `ImagePullBackOff`. 3. **Logs**: `kubectl logs` muestra la salida de la aplicación. Es la fuente principal en los `CrashLoopBackOff`. 4. **Entorno**: configuración, secretos, volúmenes, red y recursos del nodo. Empieza por ver el estado de los pods: ```bash kubectl get pods -o wide ``` ```output NAME READY STATUS RESTARTS AGE IP NODE api-7c9d8f6b5-2xkq9 0/1 CrashLoopBackOff 5 (40s ago) 4m 10.42.1.12 worker1 web-5f4b7d9c8-m8zlp 0/1 Pending 0 3m worker-6b8c5d-p2hv4 0/1 ImagePullBackOff 0 2m 10.42.2.7 worker2 ``` Revisa también los eventos recientes del namespace, ordenados por tiempo: ```bash kubectl get events --sort-by=.lastTimestamp ``` Para ver solo los avisos, filtra por tipo: ```bash kubectl get events --field-selector type=Warning ``` > Nota: los eventos se conservan una hora por defecto. Si el fallo es antiguo, puede que ya no aparezcan y tengas que reproducirlo. ## Paso 2: Resolver un CrashLoopBackOff `CrashLoopBackOff` significa que el contenedor arranca, termina y el kubelet lo reinicia esperando cada vez más tiempo entre intentos. El problema está en la aplicación o en su configuración, no en Kubernetes. Lee primero los logs del intento anterior, que son los del contenedor que falló: ```bash kubectl logs your_pod --previous ``` Si el pod tiene varios contenedores, indica cuál con `-c nombre_del_contenedor`. Después consulta el código de salida: ```bash kubectl describe pod your_pod | grep -A 5 "Last State" ``` ```output Last State: Terminated Reason: Error Exit Code: 1 Started: Wed, 24 Sep 2026 10:12:03 +0000 Finished: Wed, 24 Sep 2026 10:12:04 +0000 ``` Los códigos más habituales y lo que suelen indicar: | Código | Significado | Causa típica | |--------|-------------|--------------| | 1 | Error genérico de la aplicación | Configuración incorrecta, variable de entorno ausente, fallo al conectar con una dependencia. | | 126 | Comando no ejecutable | Permisos del binario o del script de entrada. | | 127 | Comando no encontrado | `command` o `args` mal escritos, o binario ausente en la imagen. | | 137 | Proceso matado con `SIGKILL` | `Reason: OOMKilled` si superó su límite de memoria; también una sonda `livenessProbe` que falla. | | 139 | Violación de segmento | Fallo del binario o incompatibilidad de arquitectura. | Según la causa: - **Configuración o secretos**: lista las variables que recibe el contenedor y comprueba que existen los ConfigMaps y Secrets referenciados: ```bash kubectl set env pod/your_pod --list kubectl get configmaps,secrets ``` - **OOMKilled**: sube el límite de memoria o reduce el consumo de la aplicación. - **Sonda de vida demasiado agresiva**: si los eventos muestran `Liveness probe failed` antes del reinicio, la aplicación no ha tenido tiempo de arrancar. Añade una `startupProbe` o aumenta `initialDelaySeconds` y `failureThreshold`. Si el contenedor muere tan rápido que no hay nada que leer, crea una copia del pod que ejecute una shell en lugar del comando original y examina el sistema de archivos: ```bash kubectl debug your_pod -it --copy-to=your_pod-debug --container=nombre_del_contenedor -- sh ``` Borra la copia al terminar con `kubectl delete pod your_pod-debug`. ## Paso 3: Resolver un pod en Pending Un pod en `Pending` sin IP ni nodo asignado no ha podido programarse. El planificador explica el motivo en los eventos: ```bash kubectl describe pod your_pod | sed -n '/Events:/,$p' ``` ```output Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 30s default-scheduler 0/3 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }, 2 Insufficient memory. ``` Los mensajes más habituales: - **`Insufficient cpu` o `Insufficient memory`**: la suma de requests del pod no cabe en ningún nodo. Compara lo solicitado con lo que queda en cada nodo: ```bash kubectl describe nodes | grep -A 8 "Allocated resources" ``` Reduce las requests del pod si están sobredimensionadas o añade nodos al clúster. - **`untolerated taint`**: el nodo tiene un taint que el pod no tolera. Consulta los taints de los nodos: ```bash kubectl get nodes -o custom-columns=NOMBRE:.metadata.name,TAINTS:.spec.taints ``` Si el pod debe ejecutarse ahí, añádele la `toleration` correspondiente en su especificación. Quita el taint solo si sabes por qué se puso. - **`didn't match Pod's node affinity/selector`**: el pod tiene un `nodeSelector` o una afinidad que ningún nodo cumple. Compara las etiquetas de los nodos con lo que pide el pod: ```bash kubectl get nodes --show-labels kubectl get pod your_pod -o jsonpath='{.spec.nodeSelector}{"\n"}{.spec.affinity}{"\n"}' ``` - **`unbound immediate PersistentVolumeClaims`**: el volumen no se ha podido aprovisionar. Revisa el PVC y la StorageClass: ```bash kubectl get pvc kubectl describe pvc nombre_del_pvc kubectl get storageclass ``` Si el PVC no indica StorageClass y ninguna está marcada como `(default)`, no se aprovisionará nunca. Si el pod ni siquiera existe porque el Deployment no crea réplicas, el problema suele ser una ResourceQuota. El motivo aparece en los eventos del ReplicaSet: ```bash kubectl describe resourcequota kubectl get events --field-selector reason=FailedCreate ``` ## Paso 4: Resolver un ImagePullBackOff `ErrImagePull` y después `ImagePullBackOff` indican que el kubelet no puede descargar la imagen. El mensaje exacto está en los eventos: ```bash kubectl describe pod your_pod | grep -A 3 "Failed" ``` ```output Warning Failed 15s kubelet Failed to pull image "registry.example.com/app:1.4": ... not found Warning Failed 15s kubelet Error: ErrImagePull ``` Según el mensaje: - **`not found` o `manifest unknown`**: la imagen o la etiqueta no existen. Comprueba el nombre exacto que usa el pod y verifica que la etiqueta está publicada en el registro: ```bash kubectl get pod your_pod -o jsonpath='{.spec.containers[*].image}{"\n"}' ``` - **`unauthorized` o `authentication required`**: el registro es privado. Crea un Secret de tipo `docker-registry` con credenciales de solo lectura (sustituye los valores de ejemplo por los tuyos): ```bash kubectl create secret docker-registry regcred \ --docker-server=registry.example.com \ --docker-username=your_registry_user \ --docker-password=your_registry_token ``` Y referéncialo en la plantilla del pod, al mismo nivel que `containers`: ```yaml spec: imagePullSecrets: - name: regcred containers: - name: app image: registry.example.com/app:1.4 ``` - **`toomanyrequests`**: has superado el límite de descargas anónimas de Docker Hub. Autentícate con un Secret como el anterior o usa un registro espejo. - **`no match for platform in manifest`**: la imagen no está publicada para la arquitectura del nodo (por ejemplo, solo `amd64` en un nodo `arm64`). - **Timeouts o errores de DNS**: el nodo no llega al registro. Compruébalo desde el propio nodo con `curl -I https://registry.example.com/v2/` y revisa el registro del runtime con `sudo journalctl -u kubelet` (en K3s, `sudo journalctl -u k3s` o `-u k3s-agent`). ## Paso 5: Diagnosticar DNS y Services Si una aplicación no puede conectar con otra dentro del clúster, comprueba primero la resolución DNS. La documentación de Kubernetes proporciona un pod de pruebas con herramientas de DNS: ```bash kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml kubectl exec -it dnsutils -- nslookup kubernetes.default ``` ```output Server: 10.43.0.10 Address: 10.43.0.10#53 Name: kubernetes.default.svc.cluster.local Address: 10.43.0.1 ``` Este pod se crea en el namespace `default`. Si la resolución falla, revisa CoreDNS: ```bash kubectl -n kube-system get pods -l k8s-app=kube-dns kubectl -n kube-system logs -l k8s-app=kube-dns --tail=50 ``` Si los pods de CoreDNS están caídos o con errores de conexión hacia arriba, reinícialos: ```bash kubectl -n kube-system rollout restart deployment/coredns ``` Si el DNS funciona pero el Service no responde, lo habitual es que su `selector` no coincida con las etiquetas de los pods y no tenga endpoints: ```bash kubectl get service nombre_del_servicio -o jsonpath='{.spec.selector}{"\n"}' kubectl get endpointslices -l kubernetes.io/service-name=nombre_del_servicio ``` ```output NAME ADDRESSTYPE PORTS ENDPOINTS AGE nombre_del_servicio-8xk2d IPv4 5m ``` Unos endpoints vacíos indican que ningún pod listo tiene esas etiquetas. Compáralas con `kubectl get pods --show-labels`. Si los pods existen pero no están `READY`, el problema es su `readinessProbe`. Comprueba también que el `targetPort` del Service coincide con el puerto en el que escucha el contenedor. Para probar la conectividad desde dentro del clúster, lanza un pod temporal con herramientas de red: ```bash kubectl run nettest --rm -it --image=nicolaka/netshoot -- curl -sv http://nombre_del_servicio.your_namespace.svc.cluster.local:80 ``` Si la conexión se bloquea aunque haya endpoints, revisa si hay NetworkPolicies que la impidan: ```bash kubectl get networkpolicies -A ``` Cuando termines, elimina el pod de DNS: ```bash kubectl delete pod dnsutils ``` ## Paso 6: Depurar un contenedor en ejecución Las imágenes de producción a menudo no incluyen shell ni herramientas. `kubectl debug` añade un contenedor efímero al pod que comparte su espacio de procesos y red, sin reiniciarlo: ```bash kubectl debug -it your_pod --image=busybox:stable --target=nombre_del_contenedor ``` Desde esa shell puedes ver los procesos del contenedor objetivo con `ps` y probar la red con `wget` o `nc`. Para acceder al servicio desde tu equipo sin exponerlo, usa un reenvío de puertos: ```bash kubectl port-forward pod/your_pod 8080:80 ``` Y en otra terminal: ```bash curl -I http://localhost:8080 ``` Si sospechas del nodo (disco lleno, runtime colgado), puedes abrir una shell en él con un pod privilegiado; el sistema de archivos del nodo queda montado en `/host`: ```bash kubectl debug node/your_node_name -it --image=busybox:stable ``` Elimina el pod de depuración que crea este comando cuando termines (`kubectl get pods` lo muestra con el prefijo `node-debugger-`). ## Paso 7: Revisar el estado de los nodos Si muchos pods fallan a la vez, el problema suele estar en un nodo. Comprueba su estado y sus condiciones: ```bash kubectl get nodes kubectl describe node your_node_name | sed -n '/Conditions:/,/Addresses:/p' ``` Las condiciones `MemoryPressure`, `DiskPressure` o `PIDPressure` a `True` explican desalojos masivos de pods (estado `Evicted`). Un nodo `NotReady` suele indicar que el kubelet está parado o no llega a la API. En el propio nodo, revisa el servicio: ```bash sudo systemctl status kubelet sudo journalctl -u kubelet -n 100 --no-pager ``` En K3s el servicio es `k3s` en el servidor y `k3s-agent` en los workers; en MicroK8s, ejecuta `sudo microk8s inspect`. ## Conclusión Con el orden estado, eventos, logs y entorno puedes localizar la causa de la mayoría de fallos de Kubernetes: los eventos explican los `Pending` e `ImagePullBackOff`, los logs del intento anterior explican los `CrashLoopBackOff`, y los endpoints y el DNS explican los Services que no responden. Como siguientes pasos, define requests y limits en todas tus cargas para evitar `OOMKilled` y desalojos, configura sondas de arranque y de preparación realistas, y centraliza logs y métricas para conservar el contexto cuando los eventos ya han caducado.