Al desplegar una aplicación en Kubernetes, la arquitectura de red se fundamenta en tres recursos primordiales: el Deployment (que gestiona los réplicas de Pods), el Service (que actúa como balanceador de carga interno) y el Ingress (que enruta el tráfico externo hacia el Service). Comprender la interconexión exacta de estos elementos es el primer paso para diagnosticar errores de conectividad y dsepliegue.
Interconexión de los recursos fundamentales
Un error conceptual común es asumir que el Deployment y el Service están vinculados directamente. En realidad, el Service apunta a los Pods, ignorando por completo al Deployment. Por lo tanto, el enfoque debe estar en cómo los Pods y los Services se asocian entre sí.
A continuación, se presenta una configuración moderna y actualizada que ilustra estas relaciones:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-backend-deploy
spec:
replicas: 3
selector:
matchLabels:
component: api
template:
metadata:
labels:
component: api
spec:
containers:
- name: api-container
image: registry.internal/api-service:v2.4
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: api-backend-svc
spec:
selector:
component: api
ports:
- protocol: TCP
port: 8080
targetPort: 3000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-backend-ingress
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-backend-svc
port:
number: 8080
Para evitar conflictos de red, es crucial verificar las siguientes reglas de enlace:
- El
selectordel Service (component: api) debe coincidir exactamente con las etiquetas definidas en la plantilla del Pod. - El
targetPortdel Service (3000) debe ser idéntico alcontainerPortexpuesto por el contenedor. - El
portdel Service (8080) es el puerto interno del clúster y puede ser cualquier valor disponible; múltiples Services pueden usar el mismo puerto interno. - En el Ingress (utilizando la API
v1), el camposervice.namedebe coincidir con el nombre del Service, yservice.port.numberdebe coincidir con elportdel Service.
Validación de la conectividad
Para verificar que el Service enruta correctamente el tráfico a los Pods, se puede utilizar el reenvío de puertos local:
kubectl port-forward svc/api-backend-svc 4000:8080
Al acceder a localhost:4000, la solicitud se reenvía al puerto 8080 del Service, que a su vez la dirige al puerto 3000 del Pod. Si la conexión falla, el problema reside en las etiquetas o en la configuración de puertos.
Para validar el Ingress, el reenvío de puertos debe apuntar directamente al Pod del controlador de Ingress (por ejemplo, NGINX Ingress Controller):
kubectl get pods -n ingress-nginx
kubectl port-forward pod/ingress-nginx-controller-xyz 4000:80 -n ingress-nginx
Protocolo de diagnóstico en tres niveles
Cuando un despliegue falla, el diagnóstico debe seguir un enfoque ascendente: comenzar desde la capa más baja (el Pod) y avanzar hacia la capa de red externa (Ingress).
1. Diagnóstico a nivel de Pod
La mayoría de los fallos se originan en el propio Pod. El primer paso es verificar su estado:
kubectl get pods -l component=api
Si el Pod no está en estado Running o Ready, se deben utilizar los siguientes comandos para extraer información:
kubectl logs <pod-name>: Para inspeccionar los registros de la aplicación.kubectl describe pod <pod-name>: Para revisar eventos del clúster y errores de programación.kubectl exec -it <pod-name> -- sh: Para ejecutar comandos interactivos dentro del contenedor.
Errores de inicio comunes:
- ImagePullBackOff / ErrImagePull: Indica que el contenedor no puede descargar la imagen. Las causas típicas son errores tipográficos en el nombre de la imagen, etiquetas (tags) inexistentes o falta de credenciales (
imagePullSecrets) para repositorios privados. - CrashLoopBackOff: El contenedor se inicia pero termina abruptamente. Esto suele deberse a errores en el código de la aplicación, configuraciones de entorno incorrectas o fallos en las sondas de liveness (
livenessProbe). Si el contenedor se reinicia muy rápido, usekubectl logs <pod-name> --previouspara ver los registros de la instancia anterior. - RunContainerError: Fallo antes de que la aplicación se ejecute, generalmente por montar volúmenes inexistentes (ConfigMaps o Secrets faltantes) o problemas de permisos de sistema de archivos.
Estado Pending o Not Ready:
- Si el Pod está
Pending, el planificador (scheduler) no puede asignarlo. Esto ocurre por falta de recursos (CPU/Memoria) en los nodos, violaciones deResourceQuotao dependencias dePersistentVolumeClaimno resueltas. - Si el Pod está
Runningpero noReady, la sonda de preparación (readinessProbe) está fallando. El Pod no recibirá tráfico del Service hasta que esta sonda sea exitosa.
2. Diagnóstico a nivel de Service
Si los Pods están sanos pero la aplicación no responde, el problema puede estar en el Service. El objetivo es verificar si el Service está descubriendo los Pods correctos mediante sus Endpoints:
kubectl describe svc api-backend-svc | grep Endpoints
Si la lista de Endpoints está vacía, el Service no encuentra ningún Pod. Las causas son:
- Los Pods no tienen la etiqueta exacta que busca el
selectordel Service. - Los Pods y el Service están en namespaces diferentes y no se está utilizando un servicio externo o DNS cruzado.
Si los Endpoints están poblados pero la conexión falla, verifique que el targetPort del Service coincida con el puerto real en el que escucha el proceso dentro del contenedor.
3. Diagnóstico a nivel de Ingress
Si el Service funciona correctamente pero el tráfico externo no llega, el fallo reside en la configuración del Ingress o en el controlador subyacente.
Verifique la configuración del recurso Ingress:
kubectl describe ingress api-backend-ingress
Revise la columna Backends. Si está vacía o muestra errores, hay un desajuste entre el service.name o service.port.number definidos en el Ingress y el Service real.
Para aislar si el problema es del Ingress o de la infraestructura de red (como un balanceador de carga externo o reglas de firewall), realice un port-forward directamente al Pod del controlador de Ingress, como se mostró anteriormente. Si el tráfico fluye mediante el port-forward al controlador, el Ingress está bien configurado y el problema es de red externa.
Depuración específica para Ingress NGINX
Si se utiliza el controlador Ingress-NGINX, existe un plugin oficial de kubectl que facilita la inspección profunda. Tras instalarlo, se pueden ejecutar comandos específicos:
kubectl ingress-nginx lint: Valida la sintaxis y configuración del archivonginx.confgenreado.kubectl ingress-nginx backends: Muestra los backends configurados y sus endpoints actuales, útil para confirmar si NGINX ha sincronizado los Endpoints del Service.kubectl ingress-nginx logs: Inspecciona los registros de acceso y error del controlador NGINX para identificar rechazos de conexión o errores 502/504.
Es fundamental especificar el namespace correcto utilizando la bandera --namespace o -n al ejecutar estos comandos, ya que el controlador suele desplegarse en un namespace dedicado como ingress-nginx o kube-system.