Tancàvem el mòdul 3 assenyalant que la xarxa de Rutas Norte és completament plana: qualsevol pod de rutas-norte-pro pot obrir una connexió a postgres-reserves:5432, i cap client d'internet no pot arribar encara a www.rutasnorte.example. Abans de posar portes (les polítiques de xarxa de 04-06) i finestres (l'Ingress de 04-04), cal entendre com està construïda la casa. Aquesta lliçó és la que explica què hi ha realment sota d'aquella 10.244.x.x que veus a kubectl get pods -o wide, qui crea aquesta interfície de xarxa, per què la IP d'un Service no apareix en cap targeta de xarxa de cap màquina, i com un paquet que surt d'api-reserves acaba entrant a postgres-reserves. És la lliçó més "de lampisteria" del curs, i també la que fa que tota la resta deixi de semblar màgia.
Contingut
- El model de xarxa de Kubernetes i les seves quatre regles
- Per què aquest model simplifica tota la resta
- Els quatre plans de comunicació
- CNI: la interfície que connecta el pod a la xarxa
- Els plugins: Flannel, Calico, Cilium i Weave Net
- Superposició (VXLAN), encaminament natiu (BGP) i eBPF
- Els rangs d'adreces del clúster
- Com s'implementa de debò un ClusterIP: kube-proxy
- Recorregut complet d'un paquet a Rutas Norte
- Comprovació pràctica a minikube
- El model de xarxa de Kubernetes i les seves quatre regles
Kubernetes no implementa la xarxa. El que fa és imposar un contracte: defineix un model que qualsevol implementació de xarxa ha de complir, i deixa que altres el compleixin com vulguin. El contracte té quatre regles.
| # | Regla | Què significa a la pràctica |
|---|---|---|
| 1 | Cada pod té la seva pròpia adreça IP | No es comparteix la IP del node ni es fa mapatge de ports. api-reserves escolta al 3000 dins de la seva pròpia IP, encara que hi hagi cinc rèpliques al mateix node |
| 2 | Tot pod pot parlar amb tot pod sense NAT | Tant és si són al mateix node o en nodes diferents: la connexió és directa, sense traducció d'adreces |
| 3 | Els agents del node arriben als pods d'aquest node | El kubelet, i per tant les sondes de salut de 07-01, poden connectar amb els pods sense trucs |
| 4 | La IP que el pod veu de si mateix és la que veuen els altres | Si dins del contenidor hostname -i diu 10.244.1.37, els altres pods el veuen exactament com a 10.244.1.37 |
La quarta regla sembla redundant, però és la que prohibeix explícitament el model de Docker clàssic. En un docker run -p 8080:80, el contenidor es pensa que és 172.17.0.4:80 mentre la resta del món el veu com a 192.168.1.10:8080. Aquesta discrepància trenca qualsevol protocol que anunciï la seva pròpia adreça: bases de dades en clúster, sistemes de descobriment, registres de servei. Kubernetes l'elimina d'arrel.
Fixa't en el que no diu el contracte: res sobre com s'encaminen els paquets, si hi ha encapsulació, quin rang d'IP s'usa o si hi ha tallafocs. Tot això és llibertat d'implementació.
- Per què aquest model simplifica tota la resta
El model es resumeix en una frase: "IP per pod, xarxa plana". Les seves conseqüències són enormes.
- Els ports deixen de ser un recurs escàs. En un món de mapatge de ports, desplegar tres rèpliques d'
api-reservesal mateix node obliga a assignar-los 3000, 3001 i 3002, i que algú en porti el compte. Amb IP per pod, totes tres escolten al 3000. El manifest no canvia segons on caigui el pod. - Les aplicacions no necessiten saber que són a Kubernetes. Una aplicació que funciona en una màquina virtual funciona en un pod: obre el seu port i connecta a
host:port. Això és el que va permetre migrar tant programari sense reescriure'l. - El descobriment esdevé trivial. Com que no hi ha NAT, la IP que l'
EndpointSlicede 02-05 apunta és directament connectable. Sense aquesta garantia, cada Service hauria de traduir adreces i ports per node. - La migració de pods és transparent. Un pod mor i un altre neix amb una altra IP, però la mecànica de connexió és idèntica.
El preu és que per defecte no hi ha cap aïllament. La regla 2 diu "tot pod pot parlar amb tot pod", i això és exactament el que significa: el pod més insignificant de rutas-norte-pro pot intentar connectar amb postgres-reserves. Les NetworkPolicies de 04-06 existeixen precisament per retallar aquest permís universal.
- Els quatre plans de comunicació
Quan algú diu "la xarxa de Kubernetes" acostuma a estar barrejant quatre problemes diferents, amb solucions diferents.
flowchart TB
subgraph N1["Node 1"]
subgraph P1["Pod api-reserves 10.244.1.5"]
C1["contenidor api"]
C2["sidecar de registres"]
end
P2["Pod redis-cache<br/>10.244.1.9"]
end
subgraph N2["Node 2"]
P3["Pod postgres-reserves<br/>10.244.2.4"]
end
EXT["Client d'internet"]
SVC["Service ClusterIP<br/>10.96.31.72"]
C1 -.->|"1. localhost"| C2
P1 -->|"2. pod a pod, sense NAT"| P3
P1 -->|"3. pod a Service"| SVC
SVC --> P2
EXT -->|"4. exterior a Service"| SVC
| Pla | Com es resol | On s'estudia |
|---|---|---|
| 1. Contenidor ↔ contenidor dins del mateix pod | Comparteixen el network namespace: es veuen per localhost i competeixen pels mateixos ports |
Ja vist a 02-01; patrons a 06-04 |
| 2. Pod ↔ pod | Ho implementa el plugin CNI. És el tema central d'aquesta lliçó | Aquí, apartats 4 a 7 |
| 3. Pod ↔ Service | Ho implementa kube-proxy (o el CNI, si substitueix kube-proxy) reescrivint destinacions | Aquí, apartat 8 |
| 4. Exterior ↔ Service | Tipus de Service NodePort/LoadBalancer i Ingress |
04-02 i 04-04 |
Un error de diagnòstic molt habitual és atacar el pla equivocat. Si api-reserves no arriba a postgres-reserves per IP de pod, el problema és del CNI. Si hi arriba per IP de pod però no pel nom del Service, el problema és de kube-proxy o del DNS de 04-03. Separar els plans estalvia hores.
- CNI: la interfície que connecta el pod a la xarxa
CNI (Container Network Interface) és una especificació de la CNCF, molt curta i deliberadament avorrida: defineix com un runtime de contenidors demana a un programa extern que connecti o desconnecti un contenidor d'una xarxa. No és un producte: és un contracte entre dues parts.
La cadena d'invocació en crear un pod és aquesta:
sequenceDiagram
participant K as kubelet
participant CR as containerd
participant CNI as Plugin CNI
participant IPAM as IPAM
K->>CR: crear sandbox del pod
CR->>CR: crear network namespace buit
CR->>CNI: ADD (namespace, ID del pod)
CNI->>IPAM: dona'm una IP del podCIDR del node
IPAM-->>CNI: 10.244.1.37/24
CNI->>CNI: crear veth, moure un extrem al ns
CNI->>CNI: assignar IP, ruta per defecte
CNI-->>CR: OK, IP 10.244.1.37
CR-->>K: sandbox llest
K->>CR: arrencar els contenidors del pod
Els punts que convé fixar:
- Qui invoca el plugin és el kubelet a través del runtime (containerd, al nostre clúster). L'apiserver no toca la xarxa.
- El plugin s'instal·la com un binari a
/opt/cni/bini es configura amb un fitxer JSON a/etc/cni/net.d. Per això els plugins es despleguen gairebé sempre com un DaemonSet (06-02): un pod per node que copia el binari i el fitxer de configuració en arrencar i després es queda executant el seu agent. - Les operacions són
ADD,DEL,CHECKiVERSION. En esborrar el pod s'invocaDELi la IP torna al pool. - IPAM (IP Address Management) és un subcomponent: decideix quina IP concreta s'assigna dins del rang que li toca al node.
El que fa el plugin en un ADD típic, traduït a ordres que ja coneixes de Linux:
- Crea un parell veth (dues interfícies virtuals unides com un cable).
- Deixa un extrem al network namespace de l'amfitrió (amb nom tipus
veth3a7f2c1@if3) i mou l'altre dins del namespace del pod, on s'anomenaeth0. - Demana una IP a l'IPAM i l'assigna a
eth0. - Afegeix la ruta per defecte del pod, apuntant al pont o a la passarel·la d'enllaç del node.
- A l'amfitrió, connecta el seu extrem al pont (
cni0,docker0,cbr0) o crea la ruta corresponent. - Retorna al runtime la IP assignada, que acaba a
status.podIPdel pod.
Si el CNI falla o no està instal·lat, veuràs el símptoma clàssic:
NAME READY STATUS RESTARTS AGE
api-reserves-7d9f5c8b4-x2kp9 0/1 ContainerCreating 0 3m
Events:
Warning FailedCreatePodSandBox kubelet Failed to create pod sandbox:
plugin type="bridge" failed (add): failed to set bridge addr: could not add IPPods eternament en ContainerCreating amb errors de sandbox gairebé sempre són problema de xarxa del node, no del teu manifest.
- Els plugins: Flannel, Calico, Cilium i Weave Net
Triar plugin és una de les decisions més duradores d'un clúster: canviar-lo amb càrrega en producció és una operació delicada. Aquests són els quatre històricament més utilitzats.
| Flannel | Calico | Cilium | Weave Net | |
|---|---|---|---|---|
| Model de dades | Superposició VXLAN (o host-gw) |
Encaminament natiu L3 amb BGP; opció VXLAN/IPIP | eBPF al kernel; opcional VXLAN/geneve o natiu | Superposició pròpia (VXLAN "fast datapath") |
| NetworkPolicy | No la implementa | Sí, i a més polítiques pròpies més riques | Sí, incloses polítiques L7 (HTTP, Kafka, DNS) | Sí (suport bàsic) |
| Rendiment | Bo; penalització per encapsulació | Molt bo en mode natiu (sense encapsular) | El millor: pot substituir kube-proxy | Acceptable; el menys ràpid dels quatre |
| Complexitat | Mínima | Mitjana (BGP requereix entendre la xarxa física) | Alta; requereix kernel modern | Baixa |
| Xifratge en trànsit | No | WireGuard | WireGuard o IPsec | Sí, integrat |
| Observabilitat | Cap | Mètriques Prometheus | Hubble: fluxos, mapes de servei, L7 | Bàsica |
| Quan triar-lo | Aprendre, laboratori, clúster sense requisits d'aïllament | Producció amb NetworkPolicy i xarxa sota el teu control | Producció exigent, observabilitat, polítiques L7, malla sense sidecars | Instal·lacions senzilles on ja s'usa |
Conseqüència pràctica per a Rutas Norte, i cal subratllar-la: si el clúster fa servir Flannel, les NetworkPolicies que escriguis a 04-06 s'aplicaran sense error i no faran absolutament res. L'objecte es crea, kubectl get networkpolicy el llista, i el trànsit continua passant. És la fallada silenciosa més perillosa d'aquesta part del curs, i per això la verificarem explícitament.
Els clústers gestionats de 10-06 porten el seu propi plugin (Amazon VPC CNI, Azure CNI, el de GKE), que sol assignar als pods IP de la xarxa real del núvol. Això fa que un pod sigui directament encaminable des d'altres màquines de la VPC, amb la contrapartida de consumir adreces de l'espai corporatiu.
- Superposició (VXLAN), encaminament natiu (BGP) i eBPF
El problema que resolen tots és el mateix: el pod 10.244.1.5 és al node A i vol parlar amb 10.244.2.4, que és al node B. La xarxa física entre nodes no sap res de 10.244.0.0/16: si li lliures aquest paquet tal qual, el descarta.
Xarxa superposada (VXLAN)
Es construeix una xarxa virtual damunt de la física. El node origen fica el paquet original sencer dins d'un paquet UDP adreçat a la IP real del node destinació (port 8472 a VXLAN), que el desencapsula i el lliura al pod.
[ IP nodeA -> IP nodeB | UDP 8472 | VXLAN | IP 10.244.1.5 -> 10.244.2.4 | TCP 5432 | dades ]
\_______________ sobre exterior _______________/ \____________ paquet original ______/- Avantatge decisiu: funciona sobre qualsevol xarxa, sense tocar routers ni demanar res a l'equip de xarxes. Per això és el mode per defecte de tantes instal·lacions.
- Cost: la capçalera afegeix uns 50 bytes, cosa que redueix la MTU efectiva (de 1500 a 1450 típicament) i provoca fragmentació si alguna cosa la ignora; hi ha feina extra d'encapsular i desencapsular a cada paquet; i el trànsit és opac per als tallafocs i analitzadors de la xarxa física, que només veuen UDP entre nodes.
Encaminament natiu (BGP)
No s'encapsula res. Cada node anuncia per BGP als routers de la xarxa física: "el rang 10.244.2.0/24 s'assoleix a través meu". La xarxa física aprèn les rutes i lliura els paquets de pod directament.
- Avantatge: sense sobrecost, MTU íntegra, el trànsit de pods és visible i filtrable amb les eines de xarxa existents.
- Requisit: la xarxa ho ha de permetre. En un centre de dades propi amb routers que parlin BGP, és l'ideal. En molts núvols o en xarxes corporatives tancades, no és possible i es torna a l'encapsulació.
eBPF
eBPF permet carregar programes verificats dins del kernel de Linux i enganxar-los a punts concrets de la pila de xarxa. Cilium l'utilitza per prendre decisions d'encaminament, balanceig i política abans que el paquet recorri tota la maquinària d'iptables.
- Pot substituir per complet kube-proxy, eliminant les cadenes d'
iptablesque veurem a l'apartat 8. - Escala molt millor: on
iptablesdegrada amb milers de Services, eBPF fa servir taules hash de cost constant. - Habilita polítiques amb coneixement d'HTTP (per ruta i mètode) i identitat de càrrega de treball.
- A canvi, exigeix un kernel raonablement recent i apuja el llistó de coneixement per depurar.
| Criteri | VXLAN | BGP natiu | eBPF |
|---|---|---|---|
| Sobrecost per paquet | Alt (~50 B + encapsulat) | Nul | Nul o negatiu |
| Requisits de la xarxa física | Cap | Ha d'encaminar/parlar BGP | Cap |
| Visibilitat des de la xarxa física | Baixa | Alta | Mitjana |
| Escalat amb molts Services | Depèn de kube-proxy | Depèn de kube-proxy | Excel·lent |
- Els rangs d'adreces del clúster
En un clúster conviuen tres espais d'adreces que no s'han de confondre mai.
| Rang | Què adreça | Exemple a minikube | Encaminable fora? |
|---|---|---|---|
| Xarxa de nodes | Les màquines físiques o virtuals | 192.168.49.0/24 |
Sí, és la xarxa real |
podCIDR / cluster CIDR |
Les IP dels pods | 10.244.0.0/16, trossejat en /24 per node |
Només dins del clúster |
serviceCIDR |
Les IP virtuals dels Services | 10.96.0.0/12 |
No existeix en cap interfície |
El cluster CIDR global es reparteix: el kube-controller-manager, amb --allocate-node-cidrs, assigna a cada node una porció (per defecte un /24, és a dir 254 pods útils per node) i l'escriu a spec.podCIDR de l'objecte Node. L'IPAM del plugin CNI reparteix IP dins d'aquesta porció. Així es garanteix que dos nodes no assignin mai la mateixa IP.
On es configuren:
# En crear el cluster amb kubeadm (llico 10-02)
kubeadm init --pod-network-cidr=10.244.0.0/16 --service-cidr=10.96.0.0/12
# A minikube, en crear el perfil
minikube start -p rutas-norte --extra-config=kubeadm.pod-network-cidr=10.244.0.0/16Tres avisos que estalvien incidents:
- No es poden canviar en calent. Canviar el
serviceCIDRd'un clúster viu no és una operació suportada; es planifica abans de crear-lo. - No s'han de solapar amb la xarxa corporativa. Si la teva empresa fa servir
10.96.0.0/16per a servidors, els pods de Rutas Norte no hi podran parlar: el node es pensarà que aquelles IP són Services del clúster. - El
/24per node és un límit real. Un node gran amb 300 pods es queda sense adreces encara que li sobri CPU i memòria.
- Com s'implementa de debò un ClusterIP: kube-proxy
Aquí hi ha la revelació de la lliçó. Quan a 02-05 vas crear el Service postgres-reserves amb clusterIP: 10.96.140.22, aquella adreça no es va assignar a cap interfície de cap màquina. És una ficció. No respon al ping. No hi ha cap procés escoltant-hi.
El que existeix són regles de reescriptura de destinació instal·lades a cada node per kube-proxy, un DaemonSet del namespace kube-system que observa l'API i, cada vegada que canvia un Service o un EndpointSlice, actualitza aquestes regles.
flowchart LR
API["kube-apiserver<br/>Services + EndpointSlices"] -->|watch| KP["kube-proxy<br/>(un pod per node)"]
KP -->|programa regles| DP["iptables / IPVS<br/>del kernel del node"]
POD["Pod origen"] -->|"connecta a 10.96.140.22:5432"| DP
DP -->|"DNAT a 10.244.2.4:5432"| DEST["Pod postgres-reserves"]
Mode iptables (el més habitual)
Per a cada Service, kube-proxy crea una cadena KUBE-SERVICES que casa per IP i port de destinació, salta a una cadena KUBE-SVC-XXXX pròpia del Service, i d'allà reparteix entre les cadenes KUBE-SEP-YYYY, una per endpoint, cadascuna amb la seva regla DNAT.
# Cadena d'entrada: captura el transit cap a la IP del Service
-A KUBE-SERVICES -d 10.96.140.22/32 -p tcp --dport 5432
-j KUBE-SVC-QW3RTY5432ABCD
# Repartiment entre 2 endpoints amb probabilitat estadistica
-A KUBE-SVC-QW3RTY5432ABCD -m statistic --mode random --probability 0.50000
-j KUBE-SEP-AAA111
-A KUBE-SVC-QW3RTY5432ABCD -j KUBE-SEP-BBB222
# Cada endpoint: traduccio de desti a la IP real del pod
-A KUBE-SEP-AAA111 -p tcp -j DNAT --to-destination 10.244.2.4:5432
-A KUBE-SEP-BBB222 -p tcp -j DNAT --to-destination 10.244.3.7:5432D'aquí surten tres fets importants:
- El balanceig és aleatori per connexió, no per petició. Una connexió TCP llarga (una sessió de PostgreSQL, un WebSocket) queda enganxada a un pod fins que es tanca. Per això una API que multiplexa peticions sobre poques connexions pot repartir malament la càrrega.
- La probabilitat és en cascada: amb 3 endpoints, les regles porten 1/3, després 1/2, després la resta. Així surt uniforme.
- El cost és lineal:
iptablesavalua regles en ordre. Amb desenes de milers de Services, cada actualització obliga a reprogramar taules enormes i apareixen latències de sincronització. És el motiu que existeixin IPVS i eBPF.
Mode IPVS
IPVS és el balancejador de càrrega L4 del kernel de Linux, amb taules hash en lloc de llistes de regles.
iptables |
IPVS |
|
|---|---|---|
| Estructura | Llista de regles avaluada en ordre | Taula hash, cost constant |
| Escalat | Degrada amb milers de Services | Estable amb desenes de milers |
| Algorismes | Només aleatori | rr, lc, dh, sh, sed, nq |
| Depuració | iptables-save |
ipvsadm -Ln |
| Requisits | Cap | Mòduls ip_vs* carregats |
En mode IPVS sí que apareix una interfície kube-ipvs0 al node amb les IP dels Services assignades, però és una interfície dummy: serveix perquè el kernel accepti els paquets, no per respondre.
La regla mental que cal endur-se: el Service és una regla, no una màquina. Si un ClusterIP no respon, no busquis un procés caigut: busca endpoints buits (selector que no casa, com vas veure a 02-05) o un kube-proxy que no sincronitza.
- Recorregut complet d'un paquet a Rutas Norte
Seguim una connexió real: el pod api-reserves-7d9f5c8b4-x2kp9 (10.244.1.5, node 1) obre una connexió a postgres-reserves:5432 (ClusterIP 10.96.140.22), l'únic endpoint del qual és 10.244.2.4 al node 2. El clúster fa servir VXLAN.
sequenceDiagram
participant APP as api-reserves (10.244.1.5)
participant DNS as CoreDNS
participant NS1 as Kernel node 1
participant NET as Xarxa fisica
participant NS2 as Kernel node 2
participant PG as postgres-reserves (10.244.2.4)
APP->>DNS: postgres-reserves.rutas-norte-pro.svc.cluster.local?
DNS-->>APP: 10.96.140.22
APP->>NS1: SYN a 10.96.140.22:5432 (surt per eth0/veth)
NS1->>NS1: KUBE-SERVICES -> KUBE-SVC -> KUBE-SEP<br/>DNAT desti = 10.244.2.4:5432
NS1->>NS1: ruta: 10.244.2.0/24 esta via VXLAN al node2
NS1->>NET: encapsula UDP 8472 node1 -> node2
NET->>NS2: lliura el paquet exterior
NS2->>NS2: desencapsula: IP 10.244.1.5 -> 10.244.2.4
NS2->>PG: SYN pel veth del pod
PG-->>NS2: SYN-ACK a 10.244.1.5
NS2->>NET: tornada encapsulada
NET->>NS1: lliurament
NS1->>NS1: conntrack desfa el DNAT:<br/>origen passa a 10.96.140.22:5432
NS1-->>APP: SYN-ACK aparentment del ClusterIP
Els detalls que importen:
- La resolució del nom passa primer i és independent de tota la resta (04-03).
- El DNAT passa al node d'origen, abans d'encaminar. El node 2 no veu mai la IP del Service.
postgres-reservesveu com a origen10.244.1.5, la IP real del pod client, no la del node. Això és la regla 2 (sense NAT d'origen) i és el que permet que les NetworkPolicies de 04-06 puguin identificar l'emissor per les seves etiquetes. Compte: això canvia quan el trànsit entra des de fora ambexternalTrafficPolicy: Cluster(04-02).conntrackés imprescindible: el kernel recorda la traducció per desfer-la a la resposta. Una taulaconntrackplena provoca connexions que es perden aleatòriament sota càrrega, un símptoma clàssic als pics dels ponts de Rutas Norte.
- Comprovació pràctica a minikube
Tot l'anterior es pot tocar amb les mans al perfil rutas-norte.
Els rangs del clúster
# podCIDR assignat a cada node
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'# El serviceCIDR no s'exposa com a camp; es dedueix provocant un error
kubectl create svc clusterip prova-cidr --tcp=80:80 --dry-run=server \
-o yaml --clusterip=1.2.3.4The Service "prova-cidr" is invalid: spec.clusterIPs[0]:
Invalid value: []string{"1.2.3.4"}: failed to allocate IP 1.2.3.4:
the provided IP (1.2.3.4) is not in the valid range. The range of valid IPs is 10.96.0.0/12És un truc molt útil: el missatge d'error et revela el rang exacte.
Les IP reals de la plataforma
NAME READY STATUS IP NODE
api-reserves-7d9f5c8b4-x2kp9 1/1 Running 10.244.0.31 rutas-norte
postgres-reserves-5c9d7f-4nm2q 1/1 Running 10.244.0.14 rutas-norte
NAME TYPE CLUSTER-IP PORT(S)
postgres-reserves ClusterIP 10.96.140.22 5432/TCPLes IP de pod són a 10.244.0.x (el podCIDR de l'únic node) i la del Service a 10.96.x.x. Rangs diferents, natureses diferents.
Les regles que no existeixen i les que sí
# La IP del Service no es a cap interficie del node
minikube -p rutas-norte ssh -- ip -4 addr show | grep -E "inet " inet 127.0.0.1/8 scope host lo
inet 192.168.49.2/24 brd 192.168.49.255 scope global eth0
inet 10.244.0.1/24 brd 10.244.0.255 scope global bridgeNi rastre de 10.96.140.22. Ara les regles:
-A KUBE-SERVICES -d 10.96.140.22/32 -p tcp -m comment
--comment "rutas-norte-pro/postgres-reserves cluster IP" -m tcp --dport 5432
-j KUBE-SVC-6GHJ2KLM4NOPQRSTEl comentari inclou <namespace>/<servei>: és la manera més ràpida de localitzar les regles d'un Service concret.
Un pod efímer amb eines de xarxa
La imatge nicolaka/netshoot porta dig, curl, nc, tcpdump, traceroute i ipvsadm. És la navalla suïssa per depurar xarxes a Kubernetes.
kubectl run netshoot --rm -it --restart=Never \
-n rutas-norte-pro --image=nicolaka/netshoot -- bashDins del pod:
# 1. La meva propia IP: ha d'estar al podCIDR del node
ip -4 addr show eth0 | grep inet
# inet 10.244.0.42/24 scope global eth0
# 2. Connectivitat pod a pod DIRECTA (pla 2, salta el Service)
nc -zv 10.244.0.14 5432
# Connection to 10.244.0.14 5432 port [tcp/postgresql] succeeded!
# 3. Connectivitat pod a Service (pla 3)
nc -zv postgres-reserves 5432
# Connection to postgres-reserves 5432 port [tcp/postgresql] succeeded!
# 4. El que demostra l'avis del modul 3: un pod qualsevol,
# sense cap relacio amb la plataforma, arriba a la base de dades
# amb les dades personals dels clients. Aixo ho arregla 04-06.Si el pas 2 funciona i el 3 no, el CNI està bé i el problema és de Service o DNS. Si el 2 tampoc no funciona, és el CNI o una política de xarxa. Aquesta bifurcació és el 80 % del diagnòstic de xarxa a Kubernetes.
Errors Comuns i Consells
- Confondre els tres rangs. Veure
10.96.x.xi buscar en quin node és aquell pod és un clàssic. Regla:10.244.x.xés un pod (existeix),10.96.x.xés un Service (és una regla),192.168.x.xés un node. - Fer ping a un ClusterIP. No respon i això és normal: les regles de kube-proxy només casen TCP/UDP al port declarat, no ICMP. Un ping fallit a un Service no demostra res. Fes servir
nc -zvocurl. - Solapar el
podCIDRo elserviceCIDRamb la xarxa corporativa. Provoca fallades incomprensibles en parlar amb serveis externs, com la passarel·la de pagaments. Comprova-ho abans de crear el clúster, no després. - Ignorar la MTU amb VXLAN. Connexions que obren bé però es pengen en transferir blocs grans (una restauració de PostgreSQL, una resposta JSON de 2 MB) solen ser MTU mal ajustada. Diagnòstic:
ping -M do -s 1400 <ip>. - Triar Flannel i escriure NetworkPolicies. S'apliquen sense error i no filtren res. Abans de confiar en una política, verifica que el CNI la implementa amb una prova real.
- Culpar el CNI de tot. Abans d'això, comprova els plans per ordre:
localhostdins del pod, IP de pod, ClusterIP, nom DNS. El primer que falli assenyala la capa culpable. - Consell: desa un àlies per al pod de depuració.
alias kshoot='kubectl run netshoot-$RANDOM --rm -it --restart=Never --image=nicolaka/netshoot -- bash'. Amb--rmno deixes brossa al clúster. - Consell: en producció, revisa les mètriques de
conntrack(nf_conntrack_countdavant denf_conntrack_max). Als pics dels ponts de Rutas Norte, la taula plena es manifesta com a errors de connexió intermitents sense cap pod caigut.
Exercicis
Exercici 1: Cartografiar la xarxa del clúster
Sobre el perfil rutas-norte, documenta: el podCIDR del node, el serviceCIDR, la IP del node, i les IP dels pods i Services de rutas-norte-pro. Classifica cada adreça al seu rang i explica quines existeixen físicament i quines no.
Exercici 2: Demostrar que el ClusterIP és una ficció
Tria el Service redis-cache. Demostra amb tres comprovacions que la seva IP no existeix en cap interfície, que sí que existeixen regles d'iptables per a ella, i que tot i així s'hi pot connectar. Explica qui fa la traducció i en quin node passa.
Exercici 3: Separar els plans davant d'una avaria
Un company diu que api-reserves "no veu la base de dades". Dissenya una seqüència de comprovacions, de la capa més baixa a la més alta, que permeti decidir si el problema és del CNI, del Service, del DNS o de la mateixa aplicació. Executa-la amb netshoot i anota quina sortida esperaries en cada cas de fallada.
Solucions
Exercici 1
kubectl get nodes -o custom-columns=NODE:.metadata.name,\
POD_CIDR:.spec.podCIDR,IP:.status.addresses[0].address
kubectl create svc clusterip x --tcp=80:80 --clusterip=1.2.3.4 --dry-run=server 2>&1 | tail -1
kubectl get pods -n rutas-norte-pro -o custom-columns=POD:.metadata.name,IP:.status.podIP
kubectl get svc -n rutas-norte-pro -o custom-columns=SVC:.metadata.name,CLUSTERIP:.spec.clusterIPClassificació esperada:
| Adreça | Rang | Existeix? |
|---|---|---|
192.168.49.2 |
Xarxa de nodes | Sí, és eth0 del node |
10.244.0.31 |
podCIDR |
Sí, és eth0 dins del pod |
10.96.140.22 |
serviceCIDR |
No: només regles al kernel |
10.244.0.1 |
podCIDR |
Sí, és el pont del node (passarel·la d'enllaç dels pods) |
Exercici 2
IP=$(kubectl get svc redis-cache -n rutas-norte-pro -o jsonpath='{.spec.clusterIP}')
# 1. No es a cap interficie
minikube -p rutas-norte ssh -- "ip -4 addr | grep $IP || echo 'NO APAREIX: correcte'"
# 2. Si que hi ha regles
minikube -p rutas-norte ssh -- "sudo iptables-save -t nat | grep $IP"
# 3. I tanmateix connecta
kubectl run t --rm -it --restart=Never -n rutas-norte-pro \
--image=nicolaka/netshoot -- nc -zv redis-cache 6379La traducció (DNAT) la fa el kernel del node on s'executa el pod client, fent servir les regles que kube-proxy va programar a partir de l'EndpointSlice. El paquet surt del node ja amb la IP real del pod destinació.
Exercici 3
Seqüència de menor a major nivell, amb la conclusió de cada fallada:
kubectl exec -it deploy/api-reserves -n rutas-norte-pro -- sh
# Pla 1: el proces local escolta?
nc -zv localhost 3000 # falla -> l'app no ha arrencat: no es xarxa
# Pla 2: IP de pod directa
PGIP=$(kubectl get pod -l app=postgres-reserves -n rutas-norte-pro \
-o jsonpath='{.items[0].status.podIP}')
nc -zv $PGIP 5432 # falla -> CNI o NetworkPolicy
# Pla 3: ClusterIP
nc -zv 10.96.140.22 5432 # falla (i l'anterior OK) -> kube-proxy o endpoints buits
kubectl get endpointslices -n rutas-norte-pro -l kubernetes.io/service-name=postgres-reserves
# Pla DNS
nslookup postgres-reserves # falla (i l'anterior OK) -> CoreDNS o resolv.conf
# Pla aplicacio
psql -h postgres-reserves -U reserves -c 'select 1' # falla -> credencials o base de dadesCada esglaó que funciona descarta una capa sencera. El primer que falla anomena el culpable.
Conclusió
Ja saps què hi ha sota la xarxa de Kubernetes. El model se sosté en quatre regles obligatòries —IP per pod, comunicació pod a pod sense NAT, els agents del node arriben als seus pods, i la IP que el pod veu de si mateix és la que veuen els altres— i és aquesta uniformitat la que permet que les aplicacions no sàpiguen que són en un clúster i que els ports deixin de ser un recurs a administrar. Distingeixes els quatre plans de comunicació i saps quin diagnosticar primer quan alguna cosa falla.
Has vist que Kubernetes delega la implementació en un plugin CNI, que el kubelet invoca a través del runtime en crear cada pod, i que fa una feina molt concreta: crear un parell veth, demanar una IP a l'IPAM dins del podCIDR del node i programar les rutes. Coneixes les diferències reals entre Flannel, Calico, Cilium i Weave Net, i en particular que Flannel no implementa NetworkPolicy, un detall que condicionarà la lliçó 04-06. Entens el compromís entre encapsular amb VXLAN (funciona a qualsevol lloc, costa 50 bytes i MTU) i encaminar de forma nativa amb BGP (gratis, però exigeix col·laboració de la xarxa física), i per què eBPF està desplaçant tots dos enfocaments als clústers exigents.
I sobretot, has desmuntat la ficció més útil de Kubernetes: el ClusterIP no existeix. No és a cap interfície, no respon al ping i no hi ha cap procés al darrere. Només hi ha regles d'iptables o entrades d'IPVS que kube-proxy manté sincronitzades amb els EndpointSlices, fent DNAT al node d'origen i desfent-lo a la resposta gràcies a conntrack. Has seguit un paquet d'api-reserves a postgres-reserves de principi a fi i ho has comprovat al teu propi minikube.
Amb la lampisteria entesa, toca pujar un pis. A 04-02 veurem que ClusterIP és només un dels quatre tipus de Service, que cadascun es construeix sobre l'anterior, i com NodePort, LoadBalancer i ExternalName comencen a obrir la plataforma a l'exterior: el primer pas perquè un client que vol comprar un bitllet d'autobús pugui, per fi, arribar a botiga-web.
Curs de Kubernetes
Mòdul 1: Introducció a Kubernetes
- Què és Kubernetes?
- Arquitectura de Kubernetes
- Conceptes i Terminologia Clau
- Configuració d'un Clúster de Kubernetes
- La CLI de Kubernetes: kubectl
- Objectes, Manifests YAML i el Model Declaratiu
- El Projecte del Curs: la Plataforma Rutas Norte
Mòdul 2: Components Principals de Kubernetes
- Pods
- ReplicaSets
- Deployments
- Actualitzacions, Rollbacks i Estratègies de Desplegament
- Serveis
- Namespaces
- Etiquetes, Selectors i Anotacions
Mòdul 3: Gestió de Configuració i Secrets
- ConfigMaps
- Secrets
- Variables d'Entorn
- Quotes i Límits de Recursos
- LimitRanges i Classes de Qualitat de Servei (QoS)
- ServiceAccounts i Accés a l'API des dels Pods
Mòdul 4: Xarxes a Kubernetes
- Xarxes de Clúster
- Tipus de Serveis
- DNS Intern i Descobriment de Serveis
- Controladors d'Ingress
- TLS i Gestió de Certificats amb cert-manager
- Polítiques de Xarxa
Mòdul 5: Emmagatzematge a Kubernetes
- Volums
- Volums Persistents
- Reclamacions de Volums Persistents
- Classes d'Emmagatzematge
- Aprovisionament Dinàmic, Expansió i Snapshots
- Còpies de Seguretat i Restauració de Dades
Mòdul 6: Conceptes Avançats de Kubernetes
- StatefulSets
- DaemonSets
- Treballs i CronJobs
- Init Containers, Sidecars i Patrons Multicontenidor
- Planificació: Afinitat, Taints i Toleracions
- Definicions de Recursos Personalitzats (CRDs)
- Operadors i el Patró Controlador
Mòdul 7: Monitoratge i Registre
- Verificacions de Salut i Sondes
- Servidor de Mètriques i kubectl top
- Monitoratge amb Prometheus
- Visualització i Alertes amb Grafana i Alertmanager
- Registre Centralitzat amb Elasticsearch, Fluentd i Kibana (EFK)
- Depuració d'Aplicacions i Esdeveniments del Clúster
Mòdul 8: Seguretat a Kubernetes
- Control d'Accés Basat en Rols (RBAC)
- Contextos de Seguretat i Enduriment del Contenidor
- Polítiques de Seguretat de Pods i Pod Security Standards
- Seguretat de Xarxa
- Seguretat d'Imatges
- Auditoria, Escaneig i Gestió de Vulnerabilitats
Mòdul 9: Escalat i Rendiment
- Autoescalat Horitzontal de Pods
- Autoescalat Vertical de Pods
- Autoescalat de Clúster
- Escalat per Esdeveniments i Mètriques Personalitzades amb KEDA
- Alta Disponibilitat: PodDisruptionBudgets i Topologia
- Ajust de Rendiment
Mòdul 10: Ecosistema i Eines de Kubernetes
- Minikube i Entorns Locals amb kind
- Kubeadm
- Helm
- Kustomize
- GitOps amb Argo CD i Flux
- Kubernetes Gestionat: EKS, AKS i GKE
Mòdul 11: Estudis de Cas i Aplicacions del Món Real
- Desplegament d'una Aplicació Web
- Execució d'Aplicacions amb Estat
- CI/CD amb Kubernetes
- Estratègies de Desplegament: Blue-Green i Canary
- Gestió Multi-Clúster
- Operació en Producció: Incidències, Runbooks i Costos
