En entornos de contenedores, los problemas de conectividad intermitente, como los errores 5xx esporádicos en APIs, suelen apuntar a fallos en la capa de red. Para aislar la causa, se recomienda seguir sistemáticamente el camino del paquete: desde el espacio de nombres del contenedor, a través del veth y el bridge del host (como cni0 o docker0), pasando por el proxy de servicios o reglas NAT, hasta la red subyacente (física o de túnel) y el destino final.
El siguiente es un flujo de trabajo diagnóstico basado en comandos y observaciones reales, adaptable a clústeres de Kubernetes.
- Determinación inicial del alcance
Lo primero es identificar qué componentes están involucrados. En un entorno Kubernetes, se inspeccionan los pods y servicios relevantes.
$ kubectl get pods -n prod -o wide | head -5
$ kubectl get svc,endpoints -n prod -l app=api
Con esta información, se seleccionan rutas de prueba representativas, por ejemplo:
- Entre pods en el mismo nodo.
- Entre pods en nodos distintos.
- Desde un pod hacia un IP de servicio (ClusterIP).
- Diagnóstico desde la perspectiva del contenedor
El objetivo es verificar la conectividad básica (ICMP, TCP, DNS) desde dentro del contenedor.
Ingreso al entorno de red del contenedor
Si la imagen del contenedor no incluye herramientas de diagnóstico, se puede acceder a su espacio de red desde el host.
# Obtener el PID del contenedor
CONTAINER_ID="api-67f6cc8974-2kmdg"
PID=$(docker inspect -f '{{.State.Pid}}' "$CONTAINER_ID" 2>/dev/null || crictl inspect "$CONTAINER_ID" | jq -r '.info.pid')
# Entrar al espacio de red
sudo nsenter -t "$PID" -n ip addr show
Pruebas de conectividad
Se ejecutan pruebas hacia los destinos identificados en el paso 1.
# Prueba ICMP a un pod en el mismo nodo
ping -c 3 10.244.1.42
# Prueba TCP a un servicio
curl -sS --connect-timeout 5 -o /dev/null -w "HTTP %{http_code} - Tiempo %{time_total}s\n" http://10.96.12.34:80/healthz
# Verificación de resolución DNS
nslookup api.prod.svc.cluster.local 10.96.0.10
Un patrón típico de fallo es una alta latencia variable en los pings a pods en otros nodos, lo que sugiere congestión en el túnel de superposición.
- Inspección en el host: veth, bridge y reglas
Desde el host, se revisa el estado del dispositivo veth correspondiente al pod y las tablas de puente.
# Identificar el veth del pod (por ejemplo, para la IP 10.244.1.23)
ip link show type veth | grep -B1 "master cni0"
# O buscar en /sys
ls -l /sys/class/net/veth*/ifindex
# Las estadísticas del veth pueden revelar paquetes descartados
ethtool -S vethb42c3 | grep -E 'rx_|tx_'
Se inspeccionan las reglas de iptables/nftables y los contadores de conexión.
# Ver reglas NAT relevantes
sudo iptables -t nat -vnL KUBE-SERVICES | grep "10.96.12.34"
# Revisar el estado de connection tracking
sudo conntrack -S
sysctl net.netfilter.nf_conntrack_max
- Análisis de la red entre nodos (Underlay)
Para tráfico entre nodos a través de túneles (VXLAN, WireGuard, etc.) o BGP (Calico), se verifica la salud del mecanismo de superposición.
# Para VXLAN (Flannel), verificar el puerto UDP 4789
ss -ulnp | grep 4789
sudo tcpdump -ni any udp port 4789 -c 4
# Para BGP (Calico), verificar sesiones
calicoctl node status
# Para Cilium/eBPF, monitorear descartes
cilium monitor --type drop
Un factor crítico y frecuente es la discrepancia de MTU. Se debe verificar el MTU en las interfaces relevantes.
ip -br link show | grep -E 'eth0|cni0|flannel|wg0'
# Probar Path MTU desde un pod
sudo nsenter -t "$PID" -n ping -M do -s 1472 8.8.8.8
- Consideraciones avanzadas y trampas comunes
Algunos problemas requieren revisar configuraciones específicas de Kubernetes o del CNI.
- Hairpin NAT: Si un pod no puede acceder a un servicio cuyo endpoint está en el mismo nodo, puede faltar la configuración de hairpin en el kube-proxy o el CNI.
- Filtrado inverso (rp_filter): En hosts con múltiples interfaces, un filtrado estricto puede soltar paquetes legítimos. Ajustarlo a modo "loose" (valor 2) puede resolverlo. ```
sysctl -w net.ipv4.conf.all.rp_filter=2
- SNAT para tráfico externo: Si los pods no pueden acceder a Internet, se debe verificar que existan reglas de SNAT (MASQUERADE) para la red de pods. ```
sudo iptables -t nat -vnL POSTROUTING | grep MASQUERADE
- Captura de tráfico para evidencia definiitva
La captura de paquetes (tcpdump) en diferentes puntos del camino es la herraimenta final para entender el flujo exacto.
# Capturar en el veth del contenedor
sudo tcpdump -ni vethb42c3 host 10.244.1.23 and port 80 -w /tmp/pod_traffic.pcap
# Capturar en la interfaz del túnel
sudo tcpdump -ni flannel.1 -c 10
# Capturar en la interfaz física principal
sudo tcpdump -ni eth0 host 10.0.0.12 and udp port 4789
Combinar la captura con el estado del sistema para correlacionar eventos.
sudo ss -tnp > /tmp/ss_$(date +%s).txt
sudo conntrack -L > /tmp/conntrack_$(date +%s).txt
sudo nft list ruleset > /tmp/nft_$(date +%s).txt
- Script de automatización rápida
Un script simple para obtener el veth y realizar una captura inicial puede acelerar el diagnóstico.
#!/bin/bash
POD=$1
NAMESPACE=${2:-default}
POD_IP=$(kubectl get pod "$POD" -n "$NAMESPACE" -o jsonpath='{.status.podIP}')
NODE=$(kubectl get pod "$POD" -n "$NAMESPACE" -o jsonpath='{.spec.nodeName}')
echo "Ejecutando en nodo $NODE para pod $POD ($POD_IP)"
ssh "$NODE" "sudo bash -c '
VETH=\"\$(ip -o link show type veth | awk -v ip=$POD_IP '\"'\"'{ if (\$0 ~ ip) print \$2 }'\"'\"' | tr -d :)\"
echo \"Interfaz veth detectada: \$VETH\"
tcpdump -ni \$VETH host $POD_IP -c 20
'"