Cilium
auf einem Blatt.
Dichte Referenz für Senior Platform Engineers und SREs zur eBPF-basierten Networking-, Observability- und Security-Lösung für Kubernetes. Identity-based Policies von L3 bis L7, kube-proxy-Replacement, Hubble, Encryption, ClusterMesh, Gateway API, Diagnose und Anti-Patterns. Keine Einsteiger-Folien.
Vorschau (2 Seiten A4 quer + Brand-Rückseite)


PDF herunterladen
Direkter Download, keine Mail-Adresse nötig. CC BY-SA 4.0: kopieren, drucken, weiterverteilen ist ausdrücklich erlaubt, solange die Quellenangabe sichtbar bleibt.
Was drin steht
eBPF & Identity
eBPF-Datapath statt iptables, cilium-agent/-operator, clusterweite Security-Identity aus security-relevanten Pod-Labels statt IP-basierter Regeln.
Policies L3–L7
CiliumNetworkPolicy + CiliumClusterwideNetworkPolicy: fromEndpoints, toEntities, toCIDR, toFQDNs, HTTP-Rules via node-lokalem Envoy, Enforcement-Modi.
kube-proxy-Replacement
Socket-LB für ClusterIP, NodePort, LoadBalancer, externalIPs, HostPort. k8sServiceHost/-Port als Pflicht, Kombination mit Istio, Helm-Install per OCI.
Hubble
Flow-Observability direkt aus dem Datapath: Relay clusterweit, UI mit Service-Map, hubble observe, Metriken für Prometheus.
Encryption & ClusterMesh
WireGuard (cilium_wg0, UDP 51871, Strict Mode), IPsec mit Per-Tunnel-Keys, ztunnel (Beta). Multi-Cluster-Verbund per Helm, globale Services oder MCS-API, Zertifikatslaufzeit.
Gateway API & Diagnose
Eingebauter Gateway-API-Controller (GatewayClass cilium). cilium status, connectivity test, sysdump. Anti-Patterns aus der Praxis.
Cheatsheet im Volltext
Derselbe Inhalt wie im PDF, zum Mitlesen, Durchsuchen und direkten Kopieren der YAML-Snippets. Stand: Cilium v1.20.2 (Edition 2026.10).
Architektur & Identity
eBPF-Datapath
CNI mit eBPF-Datapath: Networking, Load-Balancing, Policy und Observability laufen als eBPF-Programme im Kernel, mit kube-proxy-Replacement ohne iptables-Ketten pro Service.
Komponenten: cilium-agent
(DaemonSet, je Node), cilium-operator (clusterweite
Aufgaben, z.B. IPAM), Hubble (Observability),
cilium-CLI. CNCF-graduated.
Identity statt IP
Jeder Endpoint bekommt eine clusterweite Security-Identity, abgeleitet aus den security-relevanten Pod-Labels. Endpoints mit identischem Label-Set teilen eine Identity.
Policy-Entscheidungen laufen gegen die Identity, nicht gegen flüchtige Pod-IPs. Das skaliert unabhängig von der Endpoint-Zahl.
cilium status --wait kubectl get ciliumendpoints -A # Identity je Pod kubectl get ciliumidentities
Install & kube-proxy-Replacement
Helm-Install
Ohne kube-proxy müssen
k8sServiceHost / k8sServicePort gesetzt
sein, sonst findet der Agent den API-Server nicht (den
Service löst sonst niemand auf). Chart per OCI,
cosign-signiert, Version ohne v pinnen (oder per
Digest).
helm install cilium \ oci://quay.io/cilium/charts/cilium \ --version 1.20.2 -n kube-system \ --set kubeProxyReplacement=true \ --set k8sServiceHost=<api-server-ip> \ --set k8sServicePort=6443
kube-proxy-Replacement
eBPF übernimmt ClusterIP, NodePort, LoadBalancer, externalIPs und HostPort.
Socket-LB: übersetzt Service auf Backend
schon beim connect()/sendmsg(), kein
Paket-Rewriting auf dem Pfad.
Mit Istio (Sidecar oder Ambient),
kube-proxy-frei: socketLB.hostNamespaceOnly=true,
sonst greift Socket-LB schon im Pod und stört die Umleitung
zum Istio-Proxy; dazu cni.exclusive=false, damit
Istios CNI-Plugin erhalten bleibt. Die Cilium-Doku empfiehlt
mit Istio weiterhin kubeProxyReplacement=false.
kubectl -n kube-system exec ds/cilium -- \ cilium-dbg status --verbose | \ grep KubeProxyReplacement
CiliumNetworkPolicy (L3/L4)
Selektoren, Entities, CIDR
endpointSelector wählt die Ziel-Endpoints;
fromEndpoints/toEndpoints selektieren
per Label (Identity).
toEntities: world,
cluster, host,
kube-apiserver.
toCIDR/toCIDRSet: für
externe Ziele, Cluster-intern per Label
selektieren.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata: {name: backend-allow, namespace: shop}
spec:
endpointSelector:
matchLabels: {app: backend}
ingress:
- fromEndpoints:
- matchLabels: {app: frontend}
toPorts:
- ports:
- {port: "8080", protocol: TCP}
Clusterwide & Enforcement-Modi
CiliumClusterwideNetworkPolicy: gleiche
Syntax, nicht namespaced, für Baselines über alle
Namespaces. Baseline ohne Deny-Nebenwirkung:
enableDefaultDeny: {ingress: false, egress: false},
gilt nicht für L7-Regeln (L7 ohne Allow-all droppt
trotzdem).
policyEnforcementMode: default
(alles offen, bis eine Regel den Endpoint selektiert, dann
default-deny je Richtung), always,
never.
L7-Policies & toFQDNs
HTTP-Rules (L7)
L7-Regeln hängen unter toPorts.rules.http:
method, path, host als
POSIX-Regex. Header nie per Regex: headers prüft
Präsenz, als "Name: Wert" den exakten Wert;
headerMatches vergleicht exakt (Wert auch aus Secret,
mismatch steuert die Reaktion). Durchsetzung via
node-lokalem Envoy; Verstoß liefert
HTTP 403 statt Paket-Drop.
Weiterer L7-Typ: dns. Kafka- und proxylib-Regeln
(kafka, l7, l7proto) sind
seit 1.20 entfernt und müssen vor dem Upgrade aus den
Policies raus.
spec:
endpointSelector:
matchLabels: {app: api}
ingress:
- fromEndpoints:
- matchLabels: {app: frontend}
toPorts:
- ports:
- {port: "80", protocol: TCP}
rules:
http:
- method: GET
path: /v1/.*
toFQDNs (Egress nach Namen)
matchName exakt, matchPattern mit
Wildcard.
Pflicht-Voraussetzung: eine
rules.dns-Regel schaltet den DNS-Proxy ein,
ohne DNS-Sichtbarkeit kann Cilium FQDNs nicht auf IPs mappen und
die Policy läuft leer.
egress:
- toEndpoints:
- matchLabels: {k8s-app: kube-dns}
toPorts:
- ports: [{port: "53", protocol: ANY}]
rules:
dns: [{matchPattern: "*"}]
- toFQDNs:
- matchName: api.example.com
- matchPattern: "*.storage.example.com"
toPorts:
- ports: [{port: "443", protocol: TCP}]
Hubble (Observability)
Flows, Relay, UI
Hubble liest Flows direkt aus dem eBPF-Datapath, ohne Sidecars oder Paket-Mirroring. L7-Flows (HTTP, DNS) gibt es nur für Traffic, den eine L7-Regel über den Proxy leitet, und diese Regel filtert dann auch.
Relay aggregiert clusterweit (auch über
ClusterMesh), UI zeigt die
Service-Dependency-Map, die CLI
(hubble) filtert Flows live.
Redaction: Hubble schwärzt L7-Daten
(Query-Parameter, Header) standardmäßig nicht.
hubble.redact.enabled=true plus
hubble.redact.http.urlQuery=true, Header per
hubble.redact.http.headers.allow oder
.deny (nur eine der beiden Listen).
cilium hubble enable --ui cilium hubble port-forward & hubble status hubble observe --namespace shop \ --verdict DROPPED hubble observe --protocol http --last 20
Metriken
Hubble-Metriken für Prometheus per Helm:
hubble.metrics.enabled="{dns,drop,tcp,flow,icmp,httpV2}".
Agent: prometheus.enabled=true,
Operator: operator.prometheus.enabled=true.
Encryption
WireGuard
Transparente Verschlüsselung des Pod-Traffics
zwischen Nodes (Device cilium_wg0,
UDP 51871, Firewall freischalten!).
Key-Paar erzeugt jeder Node selbst, Public-Key-Austausch via
CiliumNode-Annotation.
Node-zu-Node zusätzlich:
encryption.nodeEncryption=true. Nodes mit Label
node-role.kubernetes.io/control-plane nimmt Cilium
davon automatisch aus. Same-Node-Traffic bleibt
unverschlüsselt.
Strict Mode:
encryption.strictMode.egress.enabled=true plus
.egress.cidr (Pod-CIDR, nur IPv4) verhindert
unverschlüsselte Erstpakete.
encryption.strictMode.ingress.enabled=true (nur
WireGuard) droppt unverschlüsselten Pod-Traffic. Die alten
Schlüssel
encryption.strictMode.enabled/.cidrs
sind seit 1.20 entfernt.
# Konfig-Änderung: --version = installierte Chart-Version helm upgrade cilium \ oci://quay.io/cilium/charts/cilium \ --version 1.20.2 -n kube-system \ --reuse-values \ --set encryption.enabled=true \ --set encryption.type=wireguard kubectl -n kube-system exec ds/cilium -- \ cilium-dbg status | grep Encryption
IPsec
encryption.type=ipsec; Key liegt im Secret
cilium-ipsec-keys (Cilium-Namespace), z.B.
"3+ rfc4106(gcm(aes)) <key> 128". Das
+ erzwingt Per-Tunnel-Keys, globale Keys gelten als
unsicher (GHSA-pwqm-x5x6-5586).
Key-Rotation ist manuell (KEYID 1–15 inkrementieren), nie während eines Upgrades rotieren.
ztunnel (Beta)
encryption.type=ztunnel: L4-mTLS je Node über
Istios ztunnel, Enrollment je Namespace (Label
io.cilium/mtls-enabled=true), CA
internal (Default) oder spire. Nicht mit
ClusterMesh kombinierbar. Empfohlene Alternative zur seit 1.20
deprecateten Mutual Authentication.
ClusterMesh
Multi-Cluster-Verbund
Pod-Konnektivität über Cluster-Grenzen, globale
Services mit Cross-Cluster-Load-Balancing. Policies selektieren
seit 1.19 nur den lokalen Cluster, Remote-Endpoints explizit per
Label io.cilium.k8s.policy.cluster.
Voraussetzungen: PodCIDRs aller Cluster
disjunkt, eindeutiger cluster.name +
cluster.id (1–255, mit
clustermesh.maxConnectedClusters=511 bis 511, nur bei
der Installation setzbar, in allen Clustern gleich), gegenseitiges
TLS-Vertrauen (gemeinsame CA, z.B. cilium-ca
kopieren, oder tls.caBundle),
IP-Konnektivität zwischen allen Nodes,
clustermesh-apiserver gegenseitig erreichbar.
# CLI-Weg (Lab, Demo) cilium clustermesh enable --context c1 cilium clustermesh connect --context c1 \ --destination-context c2 cilium clustermesh status --wait
Helm-Setup & Zertifikate
Setup laut Doku Helm-first:
clustermesh.useAPIServer=true,
clustermesh.config.enabled=true, Remote-Cluster unter
clustermesh.config.clusters. Die CLI ist ein
Helm-Wrapper für schnelle Setups (Lab, Demo).
Zertifikate: seit 1.20 gelten auto-generierte
Cluster-Mesh-Zertifikate ein Jahr. Methode helm
(Default) erneuert nur beim Re-Render, also beim Upgrade.
Produktiv cronJob oder certmanager, oder
clustermesh.apiserver.tls.auto.certValidityDuration
setzen.
Globale Services
Annotation service.cilium.io/global: "true" auf
dem gleichnamigen Service in beiden Clustern, Cilium
load-balanct auf die Backends beider Cluster.
service.cilium.io/shared: "false":
Remote-Backends nutzen, eigene nicht teilen.
Alternative zu globalen Services: MCS-API
(clustermesh.mcsapi.enabled=true, seit 1.20 stabil,
CRDs v1beta1, braucht CoreDNS ab 1.12.2 für
clusterset.local).
Gateway API
Eingebauter Controller
Cilium implementiert die Gateway API (CRDs
v1.6.1 vorab installieren): GatewayClass, Gateway, HTTPRoute,
GRPCRoute, ReferenceGrant, TLSRoute sowie
TCPRoute/UDPRoute (seit Gateway API 1.6 GA,
v1; CRDs optional, Traffic läuft am Envoy vorbei
direkt auf den Gateway-Service; im Host-Network-Modus nicht nutzbar).
Gateway-Service per Default vom Typ
LoadBalancer.
Voraussetzungen:
kubeProxyReplacement=true, l7Proxy=true
(Default), gatewayAPI.enabled=true. Ohne
bpf.tproxy=true (beta) läuft der Redirect zu
Envoy über iptables-TPROXY: fehlen die Netfilter-Module,
laufen Verbindungen in Timeouts. GatewayClass heißt
cilium.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata: {name: web-gw, namespace: shop}
spec:
gatewayClassName: cilium
listeners:
- {name: http, port: 80, protocol: HTTP}
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata: {name: web, namespace: shop}
spec:
parentRefs: [{name: web-gw}]
rules:
- matches:
- path: {type: PathPrefix, value: /}
backendRefs: [{name: web, port: 80}]
Diagnose (cilium-CLI)
Werkzeuge
cilium status --wait: Health aller Komponenten.
cilium connectivity test: E2E-Testsuite im Cluster.
cilium sysdump: Support-Archiv für
Bug-Reports.
Im Agent-Pod: cilium-dbg
(endpoint list, policy get,
monitor).
cilium connectivity test cilium sysdump --output-filename dump kubectl -n kube-system exec ds/cilium -- \ cilium-dbg endpoint list kubectl -n kube-system exec ds/cilium -- \ cilium-dbg monitor --type drop
Neu in v1.20
Highlights (29.07.2026)
ClusterNetworkPolicy (network-policy-api,
v1alpha2): opt-in per
k8sClusterNetworkPolicy.enabled=true, CRD separat
installieren. Tier Admin schlägt auch CNP/CCNP,
Baseline greift erst nach ihnen. Volle
API-Konformität verlangt
--policy-cidr-match-mode=pods,nodes (Helm
policyCIDRMatchMode={pods,nodes}, Beta), weil die API
CIDR-Regeln auch auf Pod- und Node-IPs anwendet;
pods kostet je getroffenem Pod eine zusätzliche
Identity.
Gateway API v1.6.1: TCPRoute/UDPRoute GA, delegierte Listener (ListenerSets), ExternalAuth-Filter, Backend-TLS.
netkit automatisch (Beta):
bpf.datapathMode=auto nimmt netkit, wenn der Kernel
es kann (ab 6.8, eBPF-Host-Routing nötig), sonst veth;
Default bleibt veth. Kein In-place-Wechsel: erkennt
auto netkit auf einem Node mit bestehenden
veth-Pods, startet Cilium mit Fehler. Mit
bpf.tproxy=true fällt auto immer
auf veth zurück, explizites netkit plus tproxy startet
nicht.
Traffic Distribution:
PreferSameZone / PreferSameNode werden
ausgewertet; Maglev beachtet
service.cilium.io/weight auf EndpointSlices
(Gewicht 0 = draining, Bestandsverbindungen laufen weiter).
MCS-API stabil für portable Service-Discovery über ClusterMesh.
Getestet gegen Kubernetes 1.33 bis 1.36 (ältere ohne
Support, 1.37 erst im Entwicklungszweig für 1.21 gelistet),
Envoy 1.37.x. Das
cilium-cni-Binary schrumpft von rund 77 auf
16 MB.
Upgrade-Reihenfolge
Gateway-API-CRDs vor dem Cilium-Upgrade auf
v1.6.1 heben und TLSRoute-Ressourcen vorher
sichern. Kafka-/l7-/l7proto-Regeln
vorher aus den Policies entfernen, CiliumNodeConfig
auf cilium.io/v2 umstellen. Ziel mindestens
1.20.2: frühere 1.20-Patches scheitern auf
Clustern, die mit 1.15 oder älter angelegt wurden, und ein
HTTPRoute-ExternalAuth mit ungültiger
Backend-Referenz schlägt erst ab 1.20.2 geschlossen
fehl.
Mit kube-proxy-Replacement ohne Socket-LB oder mit
socketLB.hostNamespaceOnly=true balanciert 1.20
Pod-Verbindungen auf NodePort-Services schon beim Verlassen des
Client-Pods. Die Egress-Policy des Clients muss die Backends
erlauben, die Ingress-Policy der Backends den Client.
Support-Fenster: drei Minor-Linien parallel (1.20.2, 1.19.8, 1.18.14 vom 15.09.2026). Die aktuelle Linie bekommt alle Bugfixes, die beiden Vorgänger nur Security- und schwere Korrektheits-Fixes.
Anti-Patterns
Was du nicht tun solltest
toFQDNs ohne DNS-Rule: ohne
rules.dns-Sichtbarkeit kein FQDN-zu-IP-Mapping,
Policy blockt oder läuft leer.
kube-proxy-frei ohne k8sServiceHost/Port: Agent erreicht den API-Server nicht, Cluster-Bootstrap hängt.
CIDR-Regeln für Cluster-Traffic:
toCIDR ist für externe Ziele gedacht; Pod-IPs
sind flüchtig, Labels/Identities selektieren.
Default-Modus falsch verstanden: ohne
selektierende Regel ist alles offen; die erste Regel schaltet den
Endpoint auf default-deny (je Richtung), sofern sie nicht
enableDefaultDeny abschaltet.
WireGuard ohne UDP 51871: Nodes müssen sich auf dem Port erreichen, sonst kein Tunnel.
--reuse-values beim Minor-Upgrade:
neue Chart-Werte fehlen, das Template rendert falsch. Werte per
helm get values sichern, auf umbenannte Keys
prüfen, mit -f übergeben.
IPsec-Keys während des Upgrades rotieren: erst alle Nodes auf gleiche Cilium-Version, dann rotieren.
ClusterMesh mit überlappenden PodCIDRs
oder doppelter cluster.id: Verbund kommt nicht
sauber hoch, vorab planen.
Verwandte Cheatsheets
Ebenfalls von OMNI52:
service-mesh-cheatsheet.de, Service Mesh im Vergleich
istio-cheatsheet.de, Istio in der Tiefe
kubernetes-cheatsheet.de, Kubernetes Core
rke2-cheatsheet.de, RKE2 (CNI-Wahl)
Lizenz & Weiterverteilung
Nicht erlaubt: Logo, Marken oder den Eindruck zu vermitteln, dass der Inhalt von dir/euch stammt oder dass OMNI52 GmbH die Weiterverwendung sponsort.
Volltext der Lizenz: creativecommons.org/licenses/by-sa/4.0/deed.de.
Cilium is a trademark of The Linux Foundation, registered in the United States and/or other countries. Kubernetes is a registered trademark of The Linux Foundation. OMNI52™ is a trademark of OMNI52 GmbH (filed, not yet registered). This website is operated by OMNI52 GmbH and is not affiliated with, endorsed by, or sponsored by The Linux Foundation, the CNCF, or the Cilium project. “Cilium” is used in a nominative / descriptive sense to indicate the technology this cheatsheet documents.