Kubernetes en producción · Guía práctica · #004
Pods en estado Pending: por qué el scheduler de Kubernetes no puede programar tu carga de trabajo
Un Pod en fase Pending todavía no está completamente programado o configurado. El estado no explica por sí solo la causa: empieza por los eventos del Pod y el mensaje completo de FailedScheduling, y luego comprueba una hipótesis concreta.
Síntomas y escenario
Un rollout creó un Pod de reemplazo, pero permanece sin asignación. Las dos réplicas anteriores siguen en ejecución: el servicio conserva capacidad, aunque el despliegue está degradado y no puede completarse.
NAME READY STATUS NODE
checkout-api-7d9c6f8b5d-qm2kx 1/1 Running node-a
checkout-api-7d9c6f8b5d-r7vnp 1/1 Running node-b
checkout-api-6b8c9d7f6c-2qj8m 0/1 Pending <none>Los nombres, el namespace y la salida son ilustrativos. El hash distinto identifica el nuevo ReplicaSet de la revisión reciente; no señala la causa del bloqueo.
Un Pod también puede seguir en Pending después de tener un nodo asignado, mientras se descarga una imagen o se prepara un volumen. Comprueba primero si existe esa asignación: la columna NODE y los eventos ayudan a distinguir un problema de scheduling de un paso posterior de configuración.
Investiga en este orden
- Confirma el contexto del clúster.
- Comprueba si el Pod tiene un nodo asignado.
- Lee los eventos del Pod y el mensaje completo de
FailedScheduling. - Usa ese mensaje para elegir qué restricción inspeccionar.
kubectl config current-context
kubectl get pods -n checkout -o wide
kubectl describe pod checkout-api-6b8c9d7f6c-2qj8m -n checkout
kubectl get events -n checkout --sort-by=.metadata.creationTimestampEn describe, revisa primero Node: <none> y la sección Events. Después inspecciona los campos relacionados con el evento: requests, selectores o afinidad, tolerations, volúmenes y scheduler. Conserva el mensaje completo y la hora; Kubernetes puede agregar eventos y cambiar su redacción entre versiones.
Si el Pod ya tiene un nodo asignado, busca eventos posteriores de descarga de imagen, almacenamiento o preparación del contenedor en vez de asumir que faltan recursos:
kubectl get pod checkout-api-6b8c9d7f6c-2qj8m -n checkout \
-o jsonpath='{.spec.nodeName}{"\n"}'
kubectl describe pod checkout-api-6b8c9d7f6c-2qj8m -n checkoutLectura rápida de FailedScheduling
Por ejemplo, el scheduler puede reportar:
Events:
Type Reason Age From Message
Warning FailedScheduling 2m default-scheduler 0/3 nodes are available: 3 Insufficient cpu.El mensaje exacto depende del clúster. Que falte CPU no significa que todos los ciclos de CPU estén en uso: el scheduler compara los requests del Pod con recursos asignables y requests ya colocados en los nodos que cumplen las demás restricciones.
Insufficient cpu o Insufficient memory
Ningún nodo elegible tiene suficiente recurso asignable para los requests del Pod. Compara esos requests con la capacidad asignable y los requests ya ubicados en los nodos compatibles:
kubectl get pod checkout-api-6b8c9d7f6c-2qj8m -n checkout \
-o jsonpath='{range .spec.containers[*]}{.name}{" requests="}{.resources.requests}{" limits="}{.resources.limits}{"\n"}{end}'
kubectl describe nodeskubectl top nodes, si está instalado Metrics Server, ayuda a ver uso actual. No reemplaza el cálculo del scheduler, que se basa en requests, no en el uso instantáneo. No reduzcas requests sin mediciones de la carga y sus objetivos de servicio: podrías lograr que el Pod se programe y luego provocar contención.
El selector o la afinidad no coinciden
Un mensaje sobre nodeSelector o node affinity indica que las reglas de ubicación requeridas no coinciden con los nodos disponibles. Compara los requisitos del Pod con las etiquetas reales:
kubectl get pod checkout-api-6b8c9d7f6c-2qj8m -n checkout -o yaml
kubectl get nodes --show-labelsTanto nodeSelector como la afinidad requerida deben cumplirse. La afinidad preferida solo influye en la puntuación; por sí sola no vuelve imposible programar el Pod.
Los nodos tienen taints que el Pod no tolera
Un evento de untolerated taint señala que los nodos tienen una restricción que el Pod no acepta. Inspecciona taints y tolerations:
kubectl describe nodes
kubectl get pod checkout-api-6b8c9d7f6c-2qj8m -n checkout \
-o jsonpath='{.spec.tolerations}{"\n"}'Una toleration permite que un Pod se programe en un nodo con un taint; no garantiza que lo haga, porque todavía deben cumplirse los recursos y las demás restricciones. No agregues tolerations amplias solo para forzar la ubicación.
Topología, volúmenes u otras restricciones incompatibles
La anti-afinidad requerida, las reglas estrictas de distribución por topología, una zona incompatible con un PVC o un conflicto de hostPort pueden reducir el conjunto de nodos elegibles. Sigue el mensaje específico del scheduler e inspecciona los campos del Pod, los claims y la topología de los nodos. Si el evento proviene del controlador de volúmenes o CSI y no del scheduler, el diagnóstico cambia: identifica primero qué componente lo emitió.
No hay nodos sanos o elegibles
Cuando el mensaje apunta al estado de los nodos o a que ninguno es elegible, comprueba su salud y sus taints:
kubectl get nodes
kubectl describe nodesUn autoscaler o provisionador puede añadir capacidad solo si puede crear un tipo de nodo donde el Pod quepa y se cumplan sus restricciones. Escalar no resuelve reglas imposibles ni una selección de nodo que ningún tipo disponible satisface.
Resuelve con el cambio mínimo respaldado por evidencia
Si faltan recursos, reduce un request únicamente cuando las mediciones, el comportamiento en picos y el objetivo del servicio lo justifiquen. Cambia la plantilla del Deployment en el repositorio o en la fuente de Helm/Kustomize que la genera; luego revisa el cambio y deja que el flujo GitOps lo aplique. No uses kubectl edit si el estado deseado se gestiona de forma declarativa.
Si el request es correcto, libera capacidad mediante un cambio de carga aprobado o añade capacidad compatible, después de confirmar que el Pod cabe en los tipos de nodo que el autoscaler puede crear. Para otras causas respaldadas por eventos:
- Corrige el selector o la afinidad, o aprovisiona nodos con las etiquetas previstas.
- Corrige un taint no intencionado o añade solo la toleration específica que necesita el workload.
- Resuelve la restricción concreta de topología, puerto o almacenamiento que muestran los eventos.
- En workloads de GitOps o con plantillas, modifica la fuente de verdad, no solo el objeto activo.
Verifica la recuperación
Comprueba que el Pod recibió un nodo y que los eventos muestran que fue programado correctamente:
kubectl get pod checkout-api-6b8c9d7f6c-2qj8m -n checkout -o wide
kubectl describe pod checkout-api-6b8c9d7f6c-2qj8m -n checkout
kubectl get events -n checkout --sort-by=.metadata.creationTimestampConfirma que la columna NODE ya tenga valor y que los eventos incluyan Scheduled. Después sigue el Pod durante la descarga de imagen, el montaje de volúmenes, el arranque y la readiness: que haya sido programado no significa todavía que la aplicación esté sana. Si continúa en Pending, lee el evento más reciente y ajusta la hipótesis.
Borrar el Pod no sirve para diagnosticar: normalmente su controlador lo recreará con los mismos requisitos. Reducir requests o añadir tolerations sin evidencia puede desplazar el problema a presión de recursos en runtime o colocar la carga en un nodo inadecuado.
Prevención
- Define y revisa periódicamente los requests con mediciones de la carga y sus objetivos de servicio.
- Valida juntas las etiquetas, taints, afinidad, restricciones de topología y zonas de almacenamiento al diseñar los node pools.
- Conserva capacidad compatible para el surge de los rollouts y los requisitos de dominios de fallo.
- Comprueba que los límites del autoscaler y los tipos de instancia puedan satisfacer los workloads que deben ubicar.
- Alerta por Pods sin asignación persistentes y analiza tendencias de
FailedScheduling, no solo el conteo de fases. - Documenta qué restricciones de scheduling son intencionales y qué equipo mantiene su contraparte en los node pools.
Referencias
Los títulos corresponden a la documentación oficial actual de Kubernetes; verifica las páginas de nuevo al publicar cambios futuros.
- Kubernetes: depurar Pods — diagnosticar Pods que permanecen en
Pending. - Kubernetes: gestión de recursos para Pods y contenedores — requests y límites.
- Kubernetes: asignar Pods a nodos — selectores y afinidad.
- Kubernetes: taints y tolerations — restricciones para ubicar Pods.