Kubernetes Networking: CNI, Cilium s eBPF a Network Policy
Kubernetes abstrahuje síť mistrovským způsobem: každý modul dostane směrovatelnou IP adresu, kontejnery ve stejném Podu sdílejí síťový jmenný prostor a Pody mohou komunikovat mezi sebou na libovolném uzlu bez NAT. Zdánlivá jednoduchost se však skrývá skutečná složitost: jak tento model vlastně funguje? Kdo se zabývá přidělovat IP adresy, směrovat provoz mezi uzly, implementovat síťové zásady?
Odpověď spočívá v Kontejnerové síťové rozhraní (CNI), standard, který definuje, jak by se síťové pluginy měly integrovat s Kubernetes. V tomto článku prozkoumáme síťový model Kubernetes zevnitř: jak funguje kube-proxy, proč Cilium s eBPF nahrazuje tradiční řešení a jak implementovat síťovou politiku k izolaci zátěže v produkčních klastrech.
Co se naučíte
- Síťový model Kubernetes: IP-per-Pod, plochá síť, žádný NAT
- Jak funguje rozhraní CNI (Container Network Interface) a jeho hlavní pluginy
- Rozdíl mezi kube-proxy (iptables/IPVS) a Ciliem s eBPF
- Protože eBPF přináší -30% latenci a +60% propustnost ve srovnání s iptables
- Jak nainstalovat a nakonfigurovat Cilium jako CNI
- Network Policy: syntaxe, praktické příklady, default-deny a izolace jmenného prostoru
- CiliumNetworkPolicy pro pravidla vrstvy 7 (HTTP, gRPC, Kafka)
Síťový model Kubernetes
Kubernetes zavádí síťový model se čtyřmi základními požadavky Implementace CNI musí splňovat:
- Všechny Pody mohou komunikovat se všemi ostatními Pody bez NAT
- Všechny uzly mohou komunikovat se všemi moduly bez NAT
- IP, kterou modul vidí jako svou vlastní, a stejnou IP, kterou ostatní používají k dosažení
- Kontejnery v podu sdílejí síťové jmenné prostory a IP adresy
Tento „model ploché sítě“ značně zjednodušuje uvažování aplikace: a mikroslužba nepotřebuje vědět, zda je služba, kterou volá, na stejném uzlu nebo na uzlu vzdálené. Složitost je přesunuta do síťové vrstvy clusteru.
Jak funguje komunikace mezi moduly
Když chce modul A komunikovat s modulem B na různých uzlech, typickým tokem je následující s řešením založeným na překryvné síti (např. VXLAN):
- Balíček opustí kontejner modulu A přes rozhraní
eth0 - Zadejte jmenný prostor uzlů prostřednictvím a
veth pair - CNI plugin to zachytí a zapouzdří do VXLAN (nebo GRE, Geneve...)
- Paket prochází fyzickou sítí do uzlu Pod B
- CNI na cílovém uzlu paket zapouzdří
- Paket dorazí do bloku B prostřednictvím svého veth páru
S řešeními založenými na BGP nebo nativním směrování (jako Cilium v režimu nativního směrování), zapouzdření není nutné a výkon se výrazně zlepšuje.
Kontejnerové síťové rozhraní (CNI)
CNI je specifikace CNCF, která definuje, jak by se měly vyvolat běhové moduly kontejneru síťové pluginy. Kubernetes používá CNI k delegování správy sítě na pluginy: když kubelet vytvoří Pod, zavolá nakonfigurovaný plugin CNI, aby přidělil adresu IP a nakonfigurujte síťové rozhraní.
Hlavní pluginy CNI
| Pluginy | Technologie | Zásady sítě | Zásady L7 | Use Case |
|---|---|---|---|---|
| Flanel | Překrytí VXLAN | Ne (nativní) | No | Vývoj, jednoduché shluky |
| Kaliko | BGP/překryvná vrstva | Si | No | On-premise, výkon |
| Cilium | eBPF | Si | Ano (HTTP, gRPC) | Výroba, servis pletiva |
| AWS VPC CNI | ENI nativní | ano (SG) | No | EKS |
| Azure CNI | Nativní virtuální síť | Ano (NSG) | No | AKS |
kube-proxy: Starý přístup
kube-proxy je komponenta Kubernetes zodpovědná za implementaci služeb: když klient zavolá Službu, kube-proxy zajistí, že provoz dorazí na jednu z nich Backend pod. Tradičně používá iptables pro tento účel.
Problém s iptables je v tom, že složitost se lineárně mění s počtem pravidel. V clusteru s 10 000 službami a 100 000 koncovými body spravuje iptables miliony pravidel. Každý paket musí projít tímto řetězcem pravidel s významným dopadem na latenci a CPU uzlu.
Alternativa ve stromu e IPVS (IP Virtual Server), který používá hashovací tabulku pro vyhledávání O(1) místo lineárního skenování iptables. Ale IPVS má také omezení: Nepodporuje pokročilé zásady a stále vyžaduje správu dalších pravidel iptables.
Problém škálování iptables
S 10 000 službami vytváří kube-proxy s iptables kolem 40 000 pravidel jen pro služby. Doba aktualizace těchto pravidel roste z milisekund na minuty. Seskupený velké, to vede k vysokým latencím během škálování událostí a aktualizací nasazení. To je jeden z hlavních důvodů, proč Cilium nahrazuje kube-proxy.
Cilium a eBPF: Budoucnost Kubernetes Networking
eBPF (extended Berkeley Packet Filter) je technologie linuxového jádra což vám umožňuje spouštět programy v sandboxu přímo v jádře, aniž byste jej upravovali e bez modulů jádra. Cilium používá eBPF k zachycení a zpracování síťového provozu na úrovni jádra, zcela obejít iptables a kube-proxy.
Výhody Cilium s eBPF
- Výkon: Latence snížena až o 30 %, propustnost zvýšena o 60 % ve srovnání s iptables
- Škálovatelnost: O(1) vyhledávání s mapami BPF namísto lineárního skenování iptables
- Pozorovatelnost: Hubble poskytuje viditelnost provozu L3/L4/L7 v reálném čase
- Zásady vrstvy 7: Zásady založené na HTTP cestě, metodě, hlavičce, metodě gRPC, Kafkově tématu
- Servisní síť bez postranního vozíku: mTLS a vyvažování zátěže implementované v jádře, nulová režie postranního vozíku
- Výměna proxy Kube: Cilium může zcela nahradit kube-proxy
Instalace Cilium
Cilium nainstalujeme do clusteru Kubernetes pomocí Helm a nakonfigurujeme jej tak, aby ho nahradil kube-proxy a povolit HST pro pozorovatelnost:
# Aggiungi il repo Helm di Cilium
helm repo add cilium https://helm.cilium.io/
helm repo update
# Installa Cilium con kube-proxy replacement e Hubble abilitati
helm install cilium cilium/cilium \
--version 1.16.0 \
--namespace kube-system \
--set kubeProxyReplacement=true \
--set k8sServiceHost=API_SERVER_HOST \
--set k8sServicePort=API_SERVER_PORT \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set ipam.mode=kubernetes
# Verifica installazione
cilium status --wait
# Verifica connettivita
cilium connectivity test
Cilium ve výrobě: Pokročilá konfigurace
Pro produkční cluster je zde kompletní konfigurace hodnot Helm s nativní směrování (bez zapouzdření VXLAN) pro maximalizaci výkonu:
# cilium-values-production.yaml
kubeProxyReplacement: true
k8sServiceHost: "10.0.0.1" # indirizzo API server
k8sServicePort: "6443"
# Native routing mode (senza overlay VXLAN)
# Richiede che la rete sottostante supporti il routing dei pod CIDR
tunnel: disabled
autoDirectNodeRoutes: true
ipv4NativeRoutingCIDR: "10.244.0.0/16"
# IPAM
ipam:
mode: kubernetes
# BGP per annunciare i pod CIDR ai router
bgp:
enabled: true
announce:
podCIDR: true
lbIP: true
# Hubble - osservabilita Layer 7
hubble:
enabled: true
metrics:
enabled:
- dns:query;ignoreAAAA
- drop
- tcp
- flow
- icmp
- http
relay:
enabled: true
replicas: 2
ui:
enabled: true
# Monitoring con Prometheus
prometheus:
enabled: true
serviceMonitor:
enabled: true
# Encryption (WireGuard)
encryption:
enabled: true
type: wireguard
# Load Balancing con DSR (Direct Server Return)
loadBalancer:
mode: dsr # elimina un hop di rete nel path di ritorno
# Limita connessioni per Pod
bpf:
mapDynamicSizeRatio: 0.0025
Síťové zásady v Kubernetes
Ve výchozím nastavení mohou všechny pody v clusteru Kubernetes mezi sebou volně komunikovat. To je vhodné pro vývoj, ale ve výrobě je to bezpečnostní problém. The NetworkPolicy umožňují definovat pravidla pro vstup a výstup pro moduly.
Pozor: Je vyžadován plugin CNI
NetworkPolicies jsou zdrojem Kubernetes, ale jejich implementace závisí na CNI pluginy. Flannel nativně nepodporuje NetworkPolicy. Abyste je mohli používat, potřebujete Cilium, Calico nebo jiné CNI, které je implementuje. Prostředek je přijímán serverovým API ale ignorován, pokud jej CNI nepodporuje.
Default Deny: The Fundamental Best Practice
První krok k izolaci úloh a použití zásad default-deny na každém jmenném prostoru. To zakáže veškerý provoz, který není výslovně povolen:
# default-deny-all.yaml
# Nega tutto il traffico ingress e egress nel namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {} # seleziona TUTTI i pod nel namespace
policyTypes:
- Ingress
- Egress
---
# Permetti il traffico DNS (necessario per la risoluzione dei nomi)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
NetworkPolicy pro typickou aplikaci
Podívejme se, jak izolovat třívrstvou aplikaci: frontend, backend, databáze. Pouze frontend přijímá provoz zvenčí, pouze backend může dosáhnout DB:
# network-policies-app.yaml
# Frontend: accetta traffico dall'ingress controller
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 8000
- ports:
- protocol: UDP
port: 53
---
# Backend: accetta solo dal frontend, puo raggiungere DB
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8000
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- ports:
- protocol: UDP
port: 53
---
# Database: accetta solo dal backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 5432
CiliumNetworkPolicy: Politická vrstva 7
Standardní Kubernetes NetworkPolicies fungují na vrstvě 3/4 (IP a port). Cilium se prodlužuje toto s CiliumNetworkPolicy, která umožňuje zásady založené na obsahu komunikace: HTTP cesta, metoda gRPC, téma Kafka, DNS dotaz.
Zásady HTTP s Ciliem
Umožňujeme frontendu volat pouze konkrétní koncové body backendu:
# cilium-http-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: frontend-to-backend-l7
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8000"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/products.*"
- method: "POST"
path: "/api/v1/orders"
- method: "GET"
path: "/health"
Zásady DNS s Ciliem
Omezte domény DNS, které může modul přeložit (užitečné pro zabránění exfiltraci dat):
# cilium-dns-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: restrict-dns-egress
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
egress:
# Permetti solo DNS verso il cluster DNS
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*.internal.company.com"
- matchPattern: "*.svc.cluster.local"
- matchPattern: "api.stripe.com"
Hubble: Pozorovatelnost sítě
Hubble a vrstva pozorovatelnosti Cilium. Poskytuje viditelnost v reálném čase veškerý síťový provoz klastru s komunikačními identitami založenými na Štítky Kubernetes místo IP adres.
# Installa il CLI di Hubble
export HUBBLE_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/hubble/master/stable.txt)
curl -L --fail --remote-name-all \
https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-amd64.tar.gz
tar xzvf hubble-linux-amd64.tar.gz
sudo mv hubble /usr/local/bin
# Port-forward al relay Hubble
cilium hubble port-forward &
# Osserva il traffico in tempo reale
hubble observe --namespace production --follow
# Filtra per Pod specifici
hubble observe \
--namespace production \
--from-pod frontend-7d9d6b8f-abc12 \
--to-pod backend-5c4f8d9-xyz99 \
--follow
# Mostra solo i drop (traffico bloccato dalle policy)
hubble observe \
--namespace production \
--verdict DROPPED \
--follow
# Statistiche per service
hubble observe \
--namespace production \
--output json | jq '.flow.destination.namespace'
Ladění síťových zásad a odstraňování problémů
Ladění NetworkPolicies je jednou z nejčastějších výzev v Kubernetes. Zde je jeden přístup systematický:
# 1. Verifica quali NetworkPolicy si applicano a un Pod
kubectl get networkpolicies -n production -o wide
# 2. Test di connettivita con un Pod temporaneo
kubectl run test-pod \
--image=nicolaka/netshoot \
--rm \
-it \
--restart=Never \
-n production \
-- bash
# All'interno del Pod:
# Test TCP
nc -zv backend-service 8000
# Test DNS
nslookup backend-service.production.svc.cluster.local
# Test HTTP
curl -v http://backend-service:8000/health
# 3. Con Cilium, usa il tool di policy verification
cilium policy get # mostra tutte le policy caricate
# 4. Testa la connettivita specifica
kubectl exec -n production frontend-pod -- \
curl -v http://backend-service:8000/api/v1/products
# 5. Con Hubble, vedi perche un pacchetto viene droppato
hubble observe \
--namespace production \
--verdict DROPPED \
--from-pod frontend-7d9d6b8f \
--follow
Izolace více jmenných prostorů
V clusterech s více nájemci je důležité izolovat jmenné prostory. Ve výchozím nastavení NetworkPolicies neblokují provoz napříč jmennými prostory. Zde je návod, jak implementovat úplnou izolaci:
# Isola completamente un namespace da tutti gli altri
# (ma permette il traffico interno al namespace)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: namespace-isolation
namespace: tenant-a
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
# Permetti solo traffico dallo stesso namespace
- from:
- podSelector: {}
# Permetti da monitoring namespace
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
egress:
# Permetti solo traffico verso lo stesso namespace
- to:
- podSelector: {}
# Permetti DNS
- ports:
- protocol: UDP
port: 53
# Permetti verso monitoring namespace
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
Výkonnostní benchmark: Cilium vs kube-proxy
Benchmarky ukazují významné rozdíly mezi Ciliem s eBPF a kube-proxy s iptables v klastrech s vysokým počtem služeb:
| Metrický | kube-proxy iptables | Cilium eBPF | Zlepšení |
|---|---|---|---|
| Latence P50 (10 kB svc) | 450 us | 130 us | -71 % |
| Latence P99 (10 kB svc) | 2,1 ms | 320 us | -85 % |
| Propustnost (Gbps) | 22 Gbps | 36 Gbps | +64 % |
| Pravidla aktualizace CPU (10 kB svc) | 180 sec | 2 sec | -99 % |
| Připojení/sec | 220 tis | 380 tis | +73 % |
Doporučené postupy pro Kubernetes Networking
Kontrolní seznam produkčních sítí
- Vyberte si správné CNI nyní: Migare CNI ve výrobě a komplexu. Pokud plánujete pokročilé síťové zásady nebo síť služeb, zvažte Cilium
- Výchozí odmítnutí v každém jmenném prostoru: Vždy začněte zásadou zakázat vše a poté přidejte výjimky
- Konzistentní štítky na modulech: NetworkPolicies závisí na štítcích; používat jasné konvence (aplikace, vrstva, verze)
- Před nasazením otestujte zásady: USA
cilium connectivity testnebo testovací moduly pro kontrolu - Povolit HST: V produkci je viditelnost provozu rozhodující pro ladění a dodržování předpisů
- Pokles stopy: Nakonfigurujte upozornění na Prometheus pro neočekávaný pokles provozu
- Neblokovat DNS: Vždy nezapomeňte povolit UDP/TCP 53 pro kube-dns ve vašich výstupních zásadách
- Zásady dokumentu: Pomocí anotací Kubernetes popište účel každé NetworkPolicy
Anti-vzory, kterým je třeba se vyhnout
Běžné chyby s NetworkPolicies
- Příliš laxní politika: Použití
namespaceSelector: {}bez matchLabels umožňuje provoz ze VŠECH jmenných prostorů, včetně kompromitovaných - Zapomenutí DNS: Pokud zablokujete veškerý výstup a zapomenete port 53, vaše moduly již nebudou rozlišovat žádné názvy hostitelů
- Štítky nebyly aktualizovány: Pokud přidáte nové moduly bez správných štítků, NetworkPolicies je nechrání
- Pouze testy ve vývoji: NetworkPolicies mohou blokovat neočekávaný provoz v produkci. Vždy testujte ve fázi s realistickým provozem
- Místo selektorů použijte IP: Změna IP adres; vždy používejte podSelector a namespaceSelector, nikdy ipBlock pro interní provoz
Závěry a další kroky
Síťový model Kubernetes s plochým přístupem IP-per-Pod má elegantní design jeho jednoduchost, ale sofistikovaná implementace. Výběr pluginu CNI je jedním z nejdůležitější architektonická rozhodnutí pro produkční klastr: ovlivnit dostupné funkce výkonu, zabezpečení a pozorovatelnosti.
Cilium s eBPF je dnes nejpokročilejší dostupný CNI: nahraďte kube-proxy za vynikající výkon, nabízí zásady 7. vrstvy, integruje pozorovatelnost s Hubbleem a může nahradit tradiční síť služeb pro mTLS. U nových klastrů ve výrobě a volba doporučená komunitou CNCF a velkými hráči, jako jsou Google, Amazon a Microsoft, kteří jej používají ve svých spravovaných službách Kubernetes.
Síťové zásady, správně implementované s přístupem default-deny, snižují útok se drasticky vynoří, pokud je modul kompromitován. nejsem volitelné ve výrobě: jsou základním bezpečnostním požadavkem.
Připravované články v sérii Kubernetes at Scale
Související série
- MLOps a strojové učení ve výrobě — Zátěž GPU na Kubernetes
- Platform Engineering — Interní vývojářské platformy na K8
- Pozorovatelnost a OpenTelemetry — sledování klastrů







