„La mine pe laptop merge, dar în cluster nu.” De nouă ori din zece, e o problemă de rețea. Și majoritatea inginerilor tratează container networking-ul ca pe o cutie neagră.
Hai să deschidem cutia. Vom urmări cum călătorește un pachet de la un container la altul — mai întâi pe un singur host, apoi într-un cluster Kubernetes. Dacă înțelegi asta, debugging-ul devine de 10x mai rapid.
Nivelul 0: network namespace-uri în Linux
Containerele nu au propriul lor stack de rețea. Ele folosesc network namespace-urile din Linux — o primitivă de izolare care dă fiecărui container propriile interfețe de rețea, propria tabelă de rutare și propriile reguli iptables.
# Create a network namespace (this is what container runtimes do)
ip netns add container1
# List interfaces inside the namespace — it's empty
ip netns exec container1 ip link
# 1: lo: <LOOPBACK> ... state DOWN
Un namespace proaspăt are doar o interfață loopback. Nicio conectivitate. Ca să-l conectăm la lumea exterioară, avem nevoie de o pereche veth.
Nivelul 1: perechi veth — cabluri Ethernet virtuale
O pereche veth este un cablu Ethernet virtual cu două capete. Pui un capăt în namespace-ul containerului și celălalt pe host.
# Create a veth pair
ip link add veth-host type veth peer name veth-container
# Move one end into the container namespace
ip link set veth-container netns container1
# Assign IPs
ip addr add 10.0.0.1/24 dev veth-host
ip netns exec container1 ip addr add 10.0.0.2/24 dev veth-container
# Bring them up
ip link set veth-host up
ip netns exec container1 ip link set veth-container up
# Ping from host to container
ping 10.0.0.2 # Works!
Acesta este blocul fundamental de construcție. Fiecare container are o pereche veth care îl conectează la rețeaua host-ului.
Nivelul 2: Linux bridge — container-la-container pe același host
Cu două containere pe același host, avem nevoie de un bridge — un switch virtual de Layer 2:
┌─────────────┐ ┌─────────────┐
│ Container A │ │ Container B │
│ 10.0.0.2 │ │ 10.0.0.3 │
│ veth-a-in │ │ veth-b-in │
└──────┬───────┘ └──────┬───────┘
│ │
veth-a-out veth-b-out
│ │
└───────┬───────────┘
│
┌────┴────┐
│ bridge │ (docker0, cni0, etc.)
│ 10.0.0.1 │
└────┬─────┘
│
eth0 (host)
# Create bridge
ip link add br0 type bridge
ip link set br0 up
ip addr add 10.0.0.1/24 dev br0
# Attach container A's veth to bridge
ip link set veth-a-out master br0
# Attach container B's veth to bridge
ip link set veth-b-out master br0
Acum Containerul A poate ajunge la Containerul B prin bridge. Exact asta face bridge-ul docker0 al Docker.
Nivelul 3: traversarea host-urilor — rețele overlay
Containerele de pe host-uri diferite nu pot ajunge unul la altul printr-un bridge local. Avem nevoie de o rețea overlay care încapsulează traficul containerelor în pachete host-la-host.
VXLAN
Cea mai răspândită tehnologie de overlay. Împachetează frame-ul Ethernet al containerului într-un pachet UDP:
Original packet:
[Container A: 10.244.1.5] → [Container B: 10.244.2.8]
Encapsulated:
[Host 1: 192.168.1.10] → [Host 2: 192.168.1.20]
└── UDP port 4789 (VXLAN)
└── [10.244.1.5] → [10.244.2.8] (original packet)
# Create VXLAN interface on Host 1
ip link add vxlan0 type vxlan id 42 \
local 192.168.1.10 \
dstport 4789 \
group 239.1.1.1 \
dev eth0
ip link set vxlan0 master br0
ip link set vxlan0 up
Overhead-ul este de aproximativ 50 de bytes per pachet (header-ele exterioare). Pentru majoritatea workload-urilor, neglijabil. Pentru workload-urile sensibile la latență, contează.
Nivelul 4: modelul de networking din Kubernetes
Kubernetes impune trei reguli:
- Fiecare Pod primește propriul IP — fără NAT între pod-uri
- Toate Pod-urile pot ajunge la toate celelalte Pod-uri — fără NAT
- IP-ul pe care un Pod îl vede pentru el însuși este același IP pe care îl văd ceilalți
Cum se implementează asta depinde de plugin-ul CNI:
| Plugin CNI | Abordare | Performanță | Funcționalități |
|---|---|---|---|
| Flannel | Overlay VXLAN | Bună | Simplu, minimal |
| Calico | Rutare BGP sau VXLAN | Excelentă | Network policies |
| Cilium | eBPF (la nivel de kernel) | Cea mai bună | Politici L7, criptare |
| Weave | VXLAN cu criptare | Bună | Simplu, auto-mesh |
Cum călătorește un pachet pod-la-pod (Calico în mod BGP)
Pod A (10.244.1.5) on Node 1
→ veth pair → cali* interface on host
→ host routing table (learned via BGP from other nodes)
→ eth0 → physical network
→ Node 2 eth0
→ host routing table → cali* interface
→ veth pair → Pod B (10.244.2.8)
Fără încapsulare. Fără overhead. Rețeaua fizică rutează nativ CIDR-urile pod-urilor prin BGP. De aceea rulăm Calico în mod BGP pe infrastructura noastră — vorbim deja BGP peste tot (AS210622), așa că rutarea pod-urilor este doar încă un set de prefixe.
Nivelul 5: Services și kube-proxy
Service-urile din Kubernetes oferă IP-uri stabile (ClusterIP-uri) care fac load balancing între pod-uri. Dar ClusterIP-urile nu există pe nicio interfață — sunt IP-uri virtuale implementate de kube-proxy folosind iptables sau IPVS.
Modul iptables
# kube-proxy creates rules like:
iptables -t nat -A KUBE-SERVICES \
-d 10.96.0.10/32 -p tcp --dport 80 \
-j KUBE-SVC-XXXX
# KUBE-SVC-XXXX distributes to endpoints:
iptables -t nat -A KUBE-SVC-XXXX \
-m statistic --mode random --probability 0.333 \
-j KUBE-SEP-AAAA # Pod 1
iptables -t nat -A KUBE-SVC-XXXX \
-m statistic --mode random --probability 0.500 \
-j KUBE-SEP-BBBB # Pod 2
iptables -t nat -A KUBE-SVC-XXXX \
-j KUBE-SEP-CCCC # Pod 3
Funcționează, dar nu scalează. Cu 10.000 de service-uri, ai zeci de mii de reguli iptables. Evaluarea regulilor este O(n).
Modul IPVS
IPVS folosește tabele hash pentru căutarea service-urilor — O(1) indiferent câte service-uri ai. Noi trecem fiecare cluster pe modul IPVS:
# kube-proxy configmap
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
scheduler: "lc" # least connections
Cilium: înlocuirea completă a kube-proxy
Cilium poate înlocui kube-proxy cu programe eBPF care gestionează rutarea service-urilor în kernel — înainte ca iptables să fie măcar consultat. Este cea mai rapidă opțiune și ceea ce facem deploy pe clusterele sensibile la performanță.
Nivelul 6: service mesh
Un service mesh adaugă un proxy sidecar (Envoy) la fiecare pod. Tot traficul trece prin proxy:
Pod A → Envoy sidecar → network → Envoy sidecar → Pod B
Asta permite:
- mTLS — Comunicare criptată și autentificată între toate serviciile
- Traffic splitting — Rutează 5% către canary, 95% către stable
- Retry-uri și circuit breaking — Reziliență fără modificări în aplicație
- Observabilitate — Fiecare request este trasat și măsurat automat
Costul: latență (2-5ms per hop) și overhead de resurse (fiecare sidecar Envoy folosește ~50MB RAM).
Când să folosești un service mesh: Când ai 20+ microservicii și ai nevoie de mTLS, gestionarea traficului sau observabilitate profundă. Pentru setup-uri mai simple, capabilitățile L7 ale Cilium sunt adesea suficiente, fără overhead-ul sidecar-ului.
Trusa de debugging
Când rețeaua se strică, aceste comenzi economisesc ore întregi:
# See which namespace a container is in
crictl inspect <container-id> | jq '.info.pid'
nsenter -t <pid> -n ip addr
# Trace packet path
tcpdump -i any -n host 10.244.1.5
# Check iptables rules for a service
iptables -t nat -L KUBE-SERVICES -n | grep <cluster-ip>
# Verify CNI is healthy
kubectl get pods -n kube-system -l k8s-app=calico-node
# Test pod-to-pod connectivity
kubectl exec -it debug-pod -- curl -v http://10.244.2.8:8080
# Check for conntrack table exhaustion
conntrack -C # current count
cat /proc/sys/net/nf_conntrack_max # max
Concluzii cheie
- Container networking este networking Linux — namespace-uri, perechi veth, bridge-uri. Primitivele sunt simple.
- Overlay vs. rutare nativă — Overlay-urile sunt mai simplu de configurat. Rutarea nativă (BGP) are mai puțin overhead. Alege în funcție de mediul tău.
- eBPF este viitorul — Cilium înlocuiește iptables, kube-proxy și părți din service mesh cu programe la nivel de kernel. Este mai rapid și mai simplu.
- Înțelege stack-ul — Când ceva se strică, să știi la ce nivel trebuie să faci debugging economisește ore.
Probleme de rețea în clusterul tău? Noi facem debugging de container networking zilnic, în zeci de medii. Scrie-ne și îți punem pachetele în mișcare.
Ai ceva asemănător de construit?
Proiectăm, construim și operăm software la comandă — platforme web, unelte interne, software care comunică cu hardware-ul — deseori cu agenți AI sub review uman. O singură echipă, de la specificație la producție și mai departe, oriunde ai fi.


