Módulo 4: Networking Ingress And Networkpolicy

2. El modelo de red de Kubernetes: cada Pod, una IP

Descripción

Desde el Módulo 2, esta guía ha usado direcciones IP de Pod sin explicar de dónde salen: 10.244.1.3, 10.244.2.4, distintas cada vez que un Pod se recrea. Esta lección abre esa caja. Kubernetes exige, como contrato no negociable, que cada Pod tenga su propia dirección IP, sin necesidad de traducción de direcciones (NAT) para hablarle a otro Pod — sin importar si ese otro Pod vive en el mismo nodo o en uno distinto. Ese contrato lo cumple una pieza que todavía no habías conocido por nombre: el CNI. kind trae uno por defecto, kindnet, y esta lección explica exactamente qué hace.

Conexión con el módulo

Esta lección es el fundamento técnico de todo lo demás en este módulo. El Ingress de la lección 3 depende de que el controlador pueda alcanzar cualquier Pod de andes-cargo-status-api sin importar en qué nodo corre; la NetworkPolicy de la lección 6 depende de que exista una capa capaz de interceptar ese mismo tráfico y decidir si lo deja pasar. Ambas cosas son trabajo del CNI — esta lección explica qué es antes de construir sobre él.


El contrato de red de Kubernetes, en cuatro reglas

Kubernetes no implementa la red por sí mismo — delega esa responsabilidad a un complemento externo, el CNI (Container Network Interface), pero exige que cualquier CNI que se instale cumpla cuatro reglas, sin excepción, documentadas por el propio proyecto:

  1. Todos los Pods pueden comunicarse con todos los demás Pods, sin usar NAT.
  2. Todos los nodos pueden comunicarse con todos los Pods (y viceversa), sin NAT.
  3. La IP que un Pod ve de sí mismo es la misma IP que ven los demás — sin traducción de direcciones en el camino.
  4. Los Pods de un DaemonSet/agentes del sistema pueden comunicarse igual que cualquier otro Pod.

La primera regla es la que más rompe la intuición de quien viene de Docker liso: en Docker, por defecto, los contenedores en la misma red bridge sí pueden hablarse, pero exponer un puerto hacia el mundo exterior típicamente pasa por mapeo de puertos del host (-p 8080:8080) — una forma de NAT. Kubernetes descarta esa idea desde la raíz: cada Pod recibe una IP completa, enrutable dentro del clúster, y punto. Nunca vas a ver, en un manifiesto de Kubernetes, algo parecido a -p de docker run.

                LO QUE EL CNI GARANTIZA (las cuatro reglas)

  Nodo: andes-cargo-cluster-worker         Nodo: andes-cargo-cluster-worker2
  ┌───────────────────────────┐            ┌───────────────────────────┐
  │  Pod A                     │            │  Pod C                     │
  │  10.244.1.2                │◄──────────►│  10.244.2.3                 │
  │                             │  sin NAT   │                             │
  │  Pod B                     │            │  Pod D                     │
  │  10.244.1.5                │            │  10.244.2.2                 │
  └───────────────────────────┘            └───────────────────────────┘
         ▲                                          ▲
         │              sin NAT, en cualquier        │
         └──────────────  dirección  ─────────────────┘

Quién asigna esas direcciones: el podCIDR por nodo

Cada nodo de andes-cargo-cluster recibe, al unirse al clúster, un rango propio de direcciones del cual el CNI reparte una IP a cada Pod que se cree ahí. Puedes confirmarlo tú mismo contra tu propio clúster:

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"  podCIDR="}{.spec.podCIDR}{"\n"}{end}'

Qué esperar (literal — estos tres rangos son la configuración por defecto de kind, fija mientras no cambies kind-config.yaml):

andes-cargo-cluster-control-plane  podCIDR=10.244.0.0/24
andes-cargo-cluster-worker  podCIDR=10.244.1.0/24
andes-cargo-cluster-worker2  podCIDR=10.244.2.0/24

Tres rangos /24 (254 direcciones utilizables cada uno), uno por nodo, todos dentro del rango más amplio 10.244.0.0/16 que kind reserva para Pods de todo el clúster. Esto explica algo que ya viste sin saberlo: por qué las IPs de los Pods de andes-cargo-status-api en el Módulo 2 empezaban con 10.244.1. o 10.244.2. — el prefijo delata en qué nodo corre cada uno, sin necesidad de correr kubectl get pods -o wide para saberlo.


kindnet: el CNI que kind instala por defecto

Cuando corriste kind create cluster en el Módulo 1, la línea ✓ Installing CNI 🔌 del resultado no era decorativa — instaló, de verdad, un CNI llamado kindnet, mantenido por el propio proyecto kind. Confírmalo:

kubectl get daemonset kindnet -n kube-system -o wide

Qué esperar (literal — la etiqueta de versión de la imagen, con formato vAAAAMMDD-<hash>, cambia con cada release de kind; el resto es literal para tu versión de kind):

NAME      DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE     CONTAINERS    IMAGES                                          SELECTOR
kindnet   3         3         3       3            3           kubernetes.io/os=linux   7m15s   kindnet-cni   docker.io/kindest/kindnetd:v20260528-9350166c   app=kindnet

DESIRED: 3 — un Pod de kindnet por cada uno de los tres nodos del clúster, porque kindnet está declarado como un DaemonSet (un tipo de carga de trabajo que este módulo no cubre a fondo, pero que ya puedes intuir por el nombre: "un demonio por nodo", sin excepción, incluido el control-plane). Cada instancia de kindnetd es responsable de programar las rutas de red del nodo donde vive, para que las cuatro reglas del CNI se cumplan entre ese nodo y todos los demás.

kindnet es deliberadamente simple: usa rutas de red estándar del kernel de Linux (netlink) y una implementación mínima de ptp/host-local para asignar IPs — suficiente para cumplir las cuatro reglas del contrato, sin las capacidades avanzadas de un CNI de nivel empresarial (segmentación de tráfico entre namespaces, cifrado en tránsito, motores de política de red propios). Esa simplicidad tiene una consecuencia concreta que la lección 7 de este módulo investiga a fondo con evidencia real: qué tan lejos llega kindnet cuando le pides que aplique una NetworkPolicy.


Prueba de las cuatro reglas, con evidencia real de este mismo clúster

No hace falta creer la teoría — el clúster ya la demuestra. En el Módulo 2, un Service (status-api-service) balanceó tráfico entre Pods que corrían en nodos distintos (andes-cargo-cluster-worker y andes-cargo-cluster-worker2), sin que ninguna configuración de red adicional lo hiciera posible — funcionó porque el CNI ya cumplía la regla 1 desde el momento en que el clúster se creó. Confírmalo de nuevo, ahora que sabes qué lo hace posible:

kubectl get pods -n andes-cargo -o wide

Qué esperar (nombres, IPs y AGE son tus valores variables — el patrón de dos nodos distintos, con prefijo 10.244.1. y 10.244.2., es lo que confirma la regla 1 en acción):

NAME                                      READY   STATUS    RESTARTS   AGE   IP           NODE                          NOMINATED NODE   READINESS GATES
andes-cargo-status-api-548966dd97-bpqjq   1/1     Running   0          10m   10.244.1.2   andes-cargo-cluster-worker    <none>           <none>
andes-cargo-status-api-548966dd97-jwx5r   1/1     Running   0          10m   10.244.2.3   andes-cargo-cluster-worker2   <none>           <none>
andes-cargo-status-api-548966dd97-ls2bc   1/1     Running   0          10m   10.244.2.2   andes-cargo-cluster-worker2   <none>           <none>

Tres Pods, repartidos en dos nodos distintos por el kube-scheduler (una pieza que el Módulo 1, lección 6, ya presentó), y el status-api-service del Módulo 2 les habla a los tres exactamente igual, sin ninguna diferencia de configuración según en qué nodo viva cada uno. Esa uniformidad —"no importa dónde corra el Pod, la red funciona igual"— es, en una frase, todo lo que este contrato promete.


Analogía: el sistema postal de una ciudad con calles nuevas cada semana

Piensa en cada Pod como un residente nuevo de una ciudad donde las calles se reconstruyen constantemente —Pods que se recrean, con IPs distintas cada vez, exactamente como viste en el Módulo 2—. Sin un sistema postal confiable, cada vez que alguien se muda tendrías que avisarle a mano a todos sus contactos su nueva dirección. El CNI es el sistema postal de la ciudad: garantiza que, sin importar en qué calle (nodo) viva cada residente hoy, cualquier carta (paquete de red) dirigida a su dirección actual (IP de Pod) llegue directo, sin pasar por una oficina central que traduzca direcciones (NAT). El cartero (kindnet) hace ese trabajo en segundo plano, en cada esquina de la ciudad (cada nodo), sin que ningún residente tenga que pensar en cómo funciona el reparto.


Profundización: por qué esto importa para EKS

El contrato de las cuatro reglas no es una peculiaridad de kind — es parte de la especificación de Kubernetes en sí, y cualquier clúster que se llame "Kubernetes", incluido EKS, tiene que cumplirlo. Lo que cambia entre kind y EKS es qué CNI implementa el contrato: kind usa kindnet por defecto (esta lección); EKS usa, por defecto, el Amazon VPC CNI, un CNI propio de AWS que asigna a cada Pod una IP real de la VPC donde vive el clúster —no un rango interno separado como 10.244.0.0/16—, lo que le permite a un Pod hablar directo con otros recursos de AWS (una instancia EC2, una base de datos RDS) sin ningún salto adicional. El Módulo 7 de esta guía vuelve sobre esta diferencia con más detalle. Lo que no cambia es el contrato en sí: el mismo NetworkPolicy que escribes contra kind en la lección 7 de este módulo es sintácticamente idéntico al que escribirías contra un clúster EKS real — la API de Kubernetes es la misma, solo cambia qué CNI decide, por debajo, si esa política se cumple o no.


Errores comunes

Asumir que la IP de un Pod es estable, y guardarla en algún lugar para reutilizarla más tarde (conceptual, ya adelantado en el Módulo 2 pero fácil de olvidar aquí). Qué pasa: alguien, al ver que un Pod tiene una IP "real" y enrutable, la copia y la usa directamente en un script o en otra configuración, en vez de usar el nombre DNS del Service. Por qué pasa: la lección de hoy demuestra que la IP funciona de verdad, y es tentador tratarla como una dirección permanente. Cómo detectarlo: si tienes una IP de Pod escrita a mano en cualquier archivo de configuración de este proyecto. Cómo corregirlo: la IP es real y enrutable, pero efímera — cambia cada vez que el Pod se recrea (Módulo 2, lección 6). El CNI garantiza que la IP funcione mientras existe; nunca garantiza que siga existiendo.

Pensar que el podCIDR de un nodo limita cuántos Pods pueden correr ahí, sin verificarlo (de cálculo). Qué pasa: alguien ve /24 (254 direcciones) y asume que ese es también el límite real de Pods por nodo, sin considerar que Kubernetes tiene un límite independiente y típicamente más bajo (por defecto, 110 Pods por nodo, configurable). Cómo detectarlo: si estás dimensionando un clúster basándote solo en el tamaño del podCIDR. Cómo corregirlo: el podCIDR es el límite superior de direcciones disponibles; el límite real de Pods que un nodo puede sostener casi siempre lo alcanza antes la capacidad de CPU/memoria del propio nodo, no el espacio de direcciones — esta guía no llega a ese límite en ningún módulo, pero vale la pena no confundir ambos números.

Confundir "el CNI cumple las cuatro reglas" con "cualquier tráfico está permitido" (el error conceptual más importante de esta lección, que la lección 6 corrige a fondo). Qué pasa: alguien concluye que, porque todo Pod puede hablarle a todo Pod técnicamente, eso significa que debería poder hacerlo en un clúster de producción real. Por qué pasa: "puede" y "debería poder" suenan a lo mismo cuando acabas de confirmar la conectividad con evidencia real. Cómo detectarlo: si terminas esta lección pensando que el modelo de red de Kubernetes es, por diseño, inseguro. Cómo corregirlo: el contrato del CNI garantiza capacidad técnica de comunicación — no dice nada sobre si esa comunicación debería existir. Esa es exactamente la pregunta que NetworkPolicy responde, empezando en la lección 6 de este mismo módulo.


Ejercicios

Ejercicio 1 — Enumera las cuatro reglas sin mirar la lección. Sin volver a la sección correspondiente, escribe de memoria las cuatro reglas que cualquier CNI de Kubernetes tiene que cumplir.

Ver solución
  1. Todos los Pods pueden comunicarse con todos los demás Pods, sin NAT.
  2. Todos los nodos pueden comunicarse con todos los Pods (y viceversa), sin NAT.
  3. La IP que un Pod ve de sí mismo es la misma que ven los demás.
  4. Los Pods de agentes de sistema (DaemonSet) se comunican igual que cualquier otro Pod.

Ejercicio 2 — Predice el podCIDR de un clúster de cinco nodos. Si andes-cargo-cluster tuviera, en vez de tres nodos, cinco (un control-plane y cuatro worker), y kind siguiera repartiendo rangos /24 consecutivos dentro de 10.244.0.0/16, ¿qué podCIDR esperarías ver en el quinto nodo (el último worker)?

Ver solución

10.244.4.0/24 — siguiendo el mismo patrón que ya viste (control-plane recibe 10.244.0.0/24, el primer worker recibe 10.244.1.0/24, el segundo 10.244.2.0/24), el orden de asignación continúa de forma secuencial: el tercer worker recibiría 10.244.3.0/24, y el cuarto (el quinto nodo del clúster en total) recibiría 10.244.4.0/24.

Ejercicio 3 — Explica, sin la palabra "NAT", por qué Docker liso y Kubernetes difieren en este punto. Un colega que solo conoce docker run -p 8080:8080 te pregunta por qué Kubernetes no usa mapeo de puertos del host de la misma forma para exponer un Pod. Explícaselo en dos o tres frases, sin usar la palabra "NAT".

Ver solución

Una explicación razonable: "Docker, por defecto, le da a cada contenedor una IP interna que solo la propia máquina puede alcanzar directamente — mapear un puerto del host es la forma de abrir una ventana hacia ese contenedor desde afuera. Kubernetes resuelve el problema distinto: le da a cada Pod una dirección completa, alcanzable directamente por cualquier otro Pod del clúster, sin necesidad de ninguna ventana especial — no porque sea 'más simple', sino porque un clúster tiene decenas o cientos de Pods hablándose entre sí todo el tiempo, y traducir cada una de esas conexiones sería mucho más trabajo que darle a cada uno una dirección real desde el principio."


Resumen y siguiente paso

Esta lección abrió la caja del modelo de red de Kubernetes: cuatro reglas que cualquier CNI tiene que cumplir (Pod-a-Pod sin NAT, nodo-a-Pod sin NAT, IP consistente, agentes de sistema incluidos), un podCIDR propio por nodo que reparte las direcciones, y kindnet como el CNI simple que kind instala por defecto para cumplir ese contrato — confirmado, con evidencia real de tu propio clúster, tanto en el DaemonSet mismo como en el tráfico cruzado entre nodos que el Módulo 2 ya demostró sin saberlo.

Antes de avanzar deberías poder: enumerar las cuatro reglas del CNI de memoria; explicar de dónde sale la IP de un Pod nuevo; y distinguir "el CNI permite la comunicación técnicamente" de "la comunicación debería estar permitida".

Siguiente lección: Ingress, una puerta HTTP para el clúster. Con el modelo de red como fundamento, la lección 3 explica el objeto que va a usar esa conectividad interna para resolver un problema distinto: cómo entra tráfico desde fuera del clúster, por una sola puerta HTTP, en vez de una por cada Service.

Recursos

  1. Kubernetes — Cluster Networking — la especificación oficial de las cuatro reglas de red de un clúster de Kubernetes.
  2. kind — Configuration: Networking — referencia oficial del campo networking de kind-config.yaml, incluidos podSubnet/serviceSubnet.
  3. GitHub — kubernetes-sigs/kind: kindnetd — el código fuente del CNI que instalaste sin saberlo desde el Módulo 1.
  4. Kubernetes — kubectl Reference: get nodes — referencia de kubectl get -o jsonpath, usado en esta lección para inspeccionar el podCIDR.