cilium
Installiert und konfiguriert Cilium als eBPF-basiertes CNI (Container Network Interface) in einem Kubernetes-Cluster. Cilium übernimmt Netzwerk, Load Balancing, Network Policies und optional auch Observability via Hubble.
Der Block deployt Cilium via offizielles Helm Chart (https://helm.cilium.io/) und unterstützt eine Vielzahl von Betriebsmodi:
- Overlay (VXLAN/Geneve) – Standard, funktioniert in jeder Umgebung ohne Routing-Anforderungen
- Native Routing – Für Umgebungen mit L3-Routing zwischen Nodes (höhere Performance)
- kube-proxy Replacement – Cilium ersetzt kube-proxy vollständig via eBPF
- BGP Control Plane – Cilium peert mit dem Netzwerk-Fabric und announced Services/Pods via BGP
- L2 Announcements – ARP-basierte VIP-Ankündigung für on-premise LoadBalancer-IPs ohne BGP
- WireGuard Encryption – Transparente Pod-to-Pod Verschlüsselung via WireGuard
Voraussetzungen
- Kubernetes-Cluster ohne vorher installiertes CNI (oder Migration geplant)
- Kernel-Version ≥ 5.10 (Pflicht ab Cilium 1.18)
kubectlundhelmauf dem Polycrate-Host verfügbar- Für kube-proxy Replacement: kubeadm-Cluster mit
--skip-phases=addon/kube-proxyoder kube-proxy DaemonSet muss vor der Installation entfernt werden - Für BGP: BGP-fähiger Router/Switch mit konfigurierten Peers
- Für Native Routing: L3-Routing zwischen allen Nodes vorhanden
Actions
polycrate run cilium install # Helm install/upgrade + zusätzliche Ressourcen
polycrate run cilium uninstall # Entfernt Helm Release + VMServiceScrapes
polycrate run cilium render # Rendert alle Templates nach artifacts/secrets/cilium/manifests/
polycrate run cilium status # Zeigt Helm Release Status + DaemonSet/Deployment Status
Was status zeigt
| Info | Beschreibung |
|---|---|
| Helm Release | Chart-Version, App-Version, Deployment-Status, letztes Deployment |
| Agent DaemonSet | desired / ready / available / updated |
| Operator Deployment | desired / ready / available / updated |
| Hubble Relay | ready / available (nur wenn hubble.enabled: true) |
| Hubble UI | ready / available (nur wenn hubble.enabled: true) |
| Nicht-laufende Pods | Liste aller Agent Pods die nicht im Status Running sind |
Vollständige Config-Referenz
# workspace.poly
blocks:
- name: cilium
from: cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5
config:
# Helm Chart Repository und Version
chart:
name: cilium
version: 1.19.8
repo:
url: https://helm.cilium.io/
name: cilium
# Anzahl Cilium Operator Replicas.
# Auf 1 reduzieren bei Single-Node Setups (Port-Konflikt bei >1).
replicas: 2
# MTU des Netzwerk-Interface. Standard 1500, bei VXLAN-Overlay effektiv ~1450.
# Für Jumbo Frames (z.B. 9000) auf den Nodes entsprechend setzen.
mtu: 1500
# Kubernetes Namespace für Cilium (Standard: kube-system)
namespace: kube-system
create_namespace: true
# kube-proxy Replacement via eBPF.
# true: Cilium ersetzt kube-proxy vollständig (NodePort, HostPort, ExternalIPs, HostServices).
# Voraussetzung: kube-proxy darf nicht im Cluster laufen.
# In Cilium 1.18+ subsumiert kpr=true alle vorherigen hostPort/nodePort/externalIPs Flags.
kube_proxy_replacement: false
# Kubernetes API Server Adresse für kube-proxy Replacement.
# Wird auch für den Preflight Check verwendet.
# Bei HA Controlplane: VIP oder Load Balancer IP angeben.
k8s_service_host: 127.0.0.1
k8s_service_port: 6443
# Routing-Modus: tunnel (VXLAN Overlay) oder native (direkt L3 Routing)
routing_mode: tunnel
# CIDR für Native Routing – alle Pod-CIDRs aller Nodes müssen enthalten sein.
# Nur relevant wenn routing_mode: native.
routing_cidr: 10.0.0.0/8
# Direkte Node-to-Node Routen automatisch via Kernel anlegen.
# Nur sinnvoll bei routing_mode: native in flachen L3-Netzen.
auto_direct_node_routes: false
# Interfaces, auf die Cilium sein Device-Detection beschränken soll (z.B. ein
# privates vSwitch-/VLAN-Interface für Node-zu-Node-Traffic). Leer = Ciliums
# Standard-Autodetection (alle nicht-virtuellen Interfaces mit Default-Route
# oder globaler Unicast-IP). Wichtig bei native routing (oder generell direkten
# Routen), wenn Traffic NICHT über eine öffentliche/nicht vertrauenswürdige NIC
# laufen darf – ohne diese Einschränkung versucht Cilium ggf. auch dort zu routen.
devices: []
# IPv4 Masquerading deaktivieren (Standard: aktiviert).
# Nur deaktivieren wenn alle Ziele bereits die Pod-IP nativ routen können.
masquerade_disabled: false
# eBPF-basiertes Masquerading deaktivieren (Standard: aktiviert).
# Performanter als iptables-basiertes Masquerading.
bpf_masquerade_disabled: false
# Load Balancer Algorithmus: maglev (consistent hashing) oder random
loadbalancer_algorithm: maglev
# XDP-Acceleration: disabled, native (XDP Native Mode), best-effort
loadbalancer_acceleration: best-effort
# Load Balancer Mode: snat, dsr (Direct Server Return), hybrid
loadbalancer_mode: snat
# Bandwidth Manager via eBPF EDT (Earliest Departure Time).
# Erfordert Linux Kernel ≥ 5.1, empfohlen ≥ 5.10.
bandwidth_manager: false
# BGP Control Plane (BGPv2 API, CiliumBGPClusterConfig/PeerConfig/Advertisement)
bgp_controlplane: false
# L2 Announcements via ARP/NDP für LoadBalancer Services.
# Erfordert kube_proxy_replacement: true.
l2announcements: false
# Gateway API Support (Kubernetes Gateway API CRDs müssen installiert sein)
gateway_api: false
# Cilium als Ingress Controller betreiben
ingress_controller: false
# dedicated: eigener LoadBalancer pro Ingress; shared: ein LB für alle
ingress_controller_loadbalancer_mode: dedicated
# Als Default Ingress Class setzen
ingress_controller_default: false
# Hubble – eBPF-basierte Observability (Flow Visibility)
hubble:
enabled: true # Aktiviert Hubble Relay + UI + Metrics
# Kubernetes API Client Rate Limiting für den Cilium Agent.
# Bei vielen Nodes/Pods ggf. erhöhen.
k8s_client_rate_limit_qps: 35.0
k8s_client_rate_limit_burst: 45.0
# Metriken
metrics:
# Operator Metrics auf Port 9963 exponieren
operator_enabled: false
# VMServiceScrape Ressourcen für VictoriaMetrics deployen
vmservicescrape:
enabled: false
# WireGuard Verschlüsselung für Pod-to-Pod Traffic
encryption:
enabled: false
type: "wireguard" # wireguard oder ipsec
node_encryption: false # Auch Node-to-Node Traffic verschlüsseln
# Beliebige zusätzliche Kubernetes-Ressourcen (z.B. CiliumLoadBalancerIPPool,
# CiliumBGPClusterConfig, CiliumL2AnnouncementPolicy).
additional_resources: []
# Preflight Check vor Minor-Upgrades (z.B. 1.18 → 1.19).
# Deployt cilium-preflight Chart (Image Pre-Pull + CNP Validation),
# wartet auf Erfolg und bricht die Installation ab falls er fehlschlägt.
preflight:
enabled: false
Szenarien
Szenario 1: Minimale Installation (Overlay, Standard)
Standard-Overlay mit VXLAN. Funktioniert in jeder Umgebung ohne besondere Netzwerk-Anforderungen. Geeignet für Cloud-Instanzen, VMs, gemischte Umgebungen.
blocks:
- name: cilium
from: cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5
config:
routing_mode: tunnel
hubble:
enabled: true
Szenario 2: kube-proxy Replacement (vollständiges eBPF Netzwerk)
Cilium übernimmt alle kube-proxy Aufgaben via eBPF: NodePort, HostPort, ExternalIPs, HostServices. Deutlich performanter als iptables-basiertes kube-proxy.
Voraussetzung: kube-proxy darf nicht laufen. Bei kubeadm:
# Beim Cluster-Init:
kubeadm init --skip-phases=addon/kube-proxy
# Bei bestehendem Cluster:
kubectl -n kube-system delete daemonset kube-proxy
blocks:
- name: cilium
from: cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5
config:
kube_proxy_replacement: true
k8s_service_host: 10.10.0.100 # VIP/LB des Kubernetes API Servers
k8s_service_port: 6443
routing_mode: tunnel
loadbalancer_algorithm: maglev
loadbalancer_acceleration: best-effort
bandwidth_manager: true
Szenario 3: Native Routing (höchste Performance, on-premise)
Kein Overlay-Encapsulation. Pakete werden direkt geroutet. Alle Nodes müssen sich gegenseitig die Pod-CIDRs routen können (z.B. via BGP mit dem Uplink-Switch oder statische Routen).
blocks:
- name: cilium
from: cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5
config:
kube_proxy_replacement: true
k8s_service_host: 10.10.0.100
k8s_service_port: 6443
routing_mode: native
routing_cidr: 10.0.0.0/8 # Muss alle Pod-CIDRs aller Nodes umfassen
auto_direct_node_routes: true # Kernel-Routen zu anderen Nodes automatisch setzen
devices:
- eth1 # Auf privates/internes Interface beschränken, falls Nodes zusätzlich
# eine öffentliche NIC haben, über die NICHT geroutet werden soll
masquerade_disabled: false # Masquerade für externen Traffic beibehalten
bpf_masquerade_disabled: false
loadbalancer_algorithm: maglev
loadbalancer_acceleration: native # XDP Native Mode für maximale Performance
devices bei mehreren NICs pro Node: Ohne explizite devices-Angabe erkennt Cilium automatisch alle Interfaces mit Default-Route oder globaler Unicast-Adresse – bei Nodes mit sowohl öffentlicher als auch privater NIC kann das dazu führen, dass Cilium versucht, auch über die öffentliche NIC zu routen (z.B. wenn dort ebenfalls eine globale IP liegt). devices auf das gewünschte Interface (oder Interface-Pattern, z.B. vlan+) einschränken, um das zu verhindern.
Szenario 4: BGP Control Plane
Cilium peert mit dem Netzwerk-Fabric und announced Pod-CIDRs sowie LoadBalancer-IPs via BGP. Ideal für bare-metal Umgebungen mit BGP-fähigen ToR-Switches.
Schritt 1: BGP im Block aktivieren:
blocks:
- name: cilium
from: cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5
config:
kube_proxy_replacement: true
k8s_service_host: 10.10.0.100
k8s_service_port: 6443
routing_mode: native
routing_cidr: 10.0.0.0/8
auto_direct_node_routes: true
bgp_controlplane: true
Schritt 2: BGP-Ressourcen via additional_resources:
additional_resources:
# IP Pool für LoadBalancer Services
- apiVersion: cilium.io/v2alpha1
kind: CiliumLoadBalancerIPPool
metadata:
name: default-pool
spec:
blocks:
- cidr: 192.168.100.0/24
# BGP Cluster Config – definiert das lokale ASN
- apiVersion: cilium.io/v2
kind: CiliumBGPClusterConfig
metadata:
name: cilium-bgp
spec:
nodeSelector:
matchLabels:
kubernetes.io/os: linux
bgpInstances:
- name: instance-65000
localASN: 65000
peers:
- name: peer-tor-1
peerASN: 65001
peerAddress: 10.10.0.1
peerConfigRef:
name: cilium-peer
# BGP Peer Config – Verbindungsparameter
- apiVersion: cilium.io/v2
kind: CiliumBGPPeerConfig
metadata:
name: cilium-peer
spec:
transport:
peerPort: 179
timers:
holdTimeSeconds: 9
keepAliveTimeSeconds: 3
families:
- afi: ipv4
safi: unicast
advertisements:
matchLabels:
advertise: bgp
# BGP Advertisement – was announced wird
- apiVersion: cilium.io/v2
kind: CiliumBGPAdvertisement
metadata:
name: bgp-advertisements
labels:
advertise: bgp
spec:
advertisements:
- advertisementType: PodCIDR # Pod-Netz announced
- advertisementType: Service # LoadBalancer IPs announced
service:
addresses:
- LoadBalancerIP
Szenario 5: L2 Announcements (on-premise ohne BGP)
ARP-basierte Ankündigung von LoadBalancer-IPs. Cilium antwortet auf ARP-Requests für IPs aus dem Pool – kein BGP-Router notwendig. Geeignet für einfache bare-metal Setups mit L2-Konnektivität.
Voraussetzung: kube_proxy_replacement: true
blocks:
- name: cilium
from: cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5
config:
kube_proxy_replacement: true
k8s_service_host: 10.10.0.100
k8s_service_port: 6443
routing_mode: tunnel
l2announcements: true
additional_resources:
# IP Pool für LoadBalancer Services
- apiVersion: cilium.io/v2alpha1
kind: CiliumLoadBalancerIPPool
metadata:
name: local-pool
spec:
blocks:
- cidr: 192.168.1.200/29 # 6 nutzbare IPs
# L2 Announcement Policy – definiert welche Services announced werden
- apiVersion: cilium.io/v2alpha1
kind: CiliumL2AnnouncementPolicy
metadata:
name: default-l2-policy
spec:
# Nur Services mit diesem Label berücksichtigen (leer = alle)
serviceSelector:
matchLabels: {}
# Nur auf diesen Nodes ARP-Requests beantworten
nodeSelector:
matchLabels:
kubernetes.io/os: linux
# Interfaces auf denen ARPs gesendet werden
interfaces:
- ^eth[0-9]+
loadBalancerIPs: true
externalIPs: false
Szenario 6: WireGuard Verschlüsselung
Transparente Pod-to-Pod Verschlüsselung via WireGuard. Kein manuelles Key-Management – Cilium rotiert Keys automatisch.
blocks:
- name: cilium
from: cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5
config:
routing_mode: tunnel
encryption:
enabled: true
type: wireguard
node_encryption: false # true: auch Node-to-Node Traffic verschlüsseln
# Erfordert Kernel-Bugfix (CVE-2025-37959) in 1.19+
Szenario 7: Cilium als Ingress Controller
Cilium kann als nativer Ingress Controller betrieben werden und ersetzt nginx-ingress oder ähnliches. Erfordert kube-proxy Replacement.
blocks:
- name: cilium
from: cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5
config:
kube_proxy_replacement: true
k8s_service_host: 10.10.0.100
k8s_service_port: 6443
ingress_controller: true
ingress_controller_loadbalancer_mode: shared # shared: ein LB für alle Ingresses
ingress_controller_default: true # Als default IngressClass setzen
l2announcements: true # oder bgp_controlplane: true für externe IP-Bekanntmachung
Szenario 8: VictoriaMetrics Monitoring
Hubble Metriken und Cilium Agent/Operator Metriken via VMServiceScrape für VictoriaMetrics/VMAgent.
blocks:
- name: cilium
from: cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5
config:
hubble:
enabled: true
metrics:
operator_enabled: true # Operator Metrics auf Port 9963
vmservicescrape:
enabled: true # Deployt VMServiceScrape für Agent (9962) + Operator (9963)
Deployte Metriken (Agent, Port 9962): dns, drop, tcp, flow, icmp, http
Patch 1.19.8 (Block 0.6.5)
Chart/App-Default ist 1.19.8 (vorher 1.19.1). Das ist ein Patch in derselben Minor-Linie — keine neuen Block-Keys, kein Preflight-Zwang.
Worauf zu achten ist
- Images kommen von
quay.io/cilium/*:v1.19.8. Ohne Registry-Zugang (oder Mirror) bleibt der Helm-Upgrade aufImagePullBackOff. Vivavis: erst testen, wenn Egress/Registry wieder steht. - Hubble Relay beendet sich beim Shutdown jetzt sauber; nach dem Upgrade kurz
hubble-relayundhubble-peerprüfen (bekanntes KPR/Socket-LB-Thema, Block-Defaultpeer_service_internal_traffic_policy: Cluster). - Socket-LB: nur noch Cilium-eigene cgroup-Programme werden detached — fremde cgroup-BPF-Hooks bleiben.
- NodePort: Fix für Egress-Tuple-Reuse auf geschlossenen Connections — bei KPR/L2/LB nach dem Upgrade
cilium statusund ein Service-Smoke (NodePort/ClusterIP) machen. cilium-dbg map eventsdarf den Agent nicht mehr crashen.- Fünf Config-Keys wurden bisher akzeptiert und still ignoriert (
vtep-sync-interval,enable-xt-socket-fallback,eni-delete-on-terminationmit custom CNI,enableIdentityMarkaußerhalb CNI-Chaining,lb-retry-backoff-max). Unser Values-Template setzt sie nicht.
Nicht in diesem Schritt
Kein Sprung auf Cilium 1.20. 1.20 hat Breaking Changes (Kafka/proxylib entfernt, CiliumNodeConfig v2alpha1 weg, CNI 1.0.0, Gateway API ≥ 1.6.1, KPR/SocketLB-Verhalten). Erst 1.19.8 auf dem Cluster, dann 1.20 separat analysieren.
Release notes: https://github.com/cilium/cilium/releases/tag/v1.19.8
Upgrade-Workflow (Minor Version)
Bei einem Minor-Upgrade (z.B. 1.19 → 1.20) ist ein Preflight Check zwingend empfohlen. Der Block führt diesen automatisch durch wenn preflight.enabled: true gesetzt ist. Vor jedem Minor zuerst den neuesten Patch der aktuellen Linie installieren (jetzt 1.19.8).
Ablauf
1. polycrate run cilium install (mit preflight.enabled: true)
→ Deployed cilium-preflight Chart (Pre-Pull + CNP Validation)
→ Wartet bis alle Nodes das neue Image gepullt haben
→ Wartet bis CNP Validator Deployment READY 1/1 ist
→ Cleanup: helm uninstall cilium-preflight (auch bei Fehler)
→ Bei Erfolg: Helm Upgrade auf neue Version
→ Bei Fehler: Abbruch, kein Upgrade
Schritt-für-Schritt
1. Patch-Update zuerst (immer auf neuesten Patch-Stand vor Minor-Upgrade):
# workspace.poly
config:
chart:
version: 1.19.8 # Neuester 1.19.x Patch
polycrate run cilium install
2. Minor-Upgrade vorbereiten (erst nach Analyse — nicht 1.20 ohne Review):
# workspace.poly
config:
chart:
version: 1.20.2
preflight:
enabled: true
polycrate run cilium install
3. Nach erfolgreichem Upgrade:
preflight:
enabled: false # Wieder deaktivieren
Was der Preflight prüft
| Check | Beschreibung |
|---|---|
| Image Pre-Pull | Zieht das neue Cilium-Image auf alle Nodes vorab (DaemonSet READY = desiredNumberScheduled) |
| CNP Validation | Validiert alle CiliumNetworkPolicy und CiliumClusterwideNetworkPolicy gegen das neue Schema |
Schlägt der CNP-Validator an (Deployment READY 0/1), gibt es ungültige Policies. Logs einsehen:
kubectl logs -n kube-system deployment/cilium-pre-flight-check -c cnp-validator
Hinweise
Single-Node Setup
Bei einem einzelnen Node muss replicas: 1 gesetzt werden – der Cilium Operator versucht sonst zwei Instanzen zu starten, was zu Port-Konflikten führt:
config:
replicas: 1
MTU
Bei VXLAN-Overlay reduziert Cilium die effektive MTU automatisch um den Encapsulation-Overhead (~50 Bytes). Bei einem physischen MTU von 1500 sind für Pod-Traffic ~1450 Bytes effektiv verfügbar. Jumbo Frames auf den Nodes setzen und mtu: 9000 konfigurieren für maximalen Durchsatz:
config:
mtu: 9000 # Nur wenn alle Nodes und der Uplink Jumbo Frames unterstützen
BGP: CiliumBGPPeeringPolicy entfernt
Ab Cilium 1.19 ist CiliumBGPPeeringPolicy (BGPv1) vollständig entfernt. Alle Ressourcen müssen auf die neuen cilium.io/v2 CRDs migriert sein:
CiliumBGPClusterConfig(ersetzt BGPPeeringPolicy)CiliumBGPPeerConfigCiliumBGPAdvertisementCiliumBGPNodeConfigOverride(optional)
L2 Announcements und kube-proxy Replacement
L2 Announcements benötigen zwingend kube_proxy_replacement: true. Ohne KPR werden ARP-Requests nicht beantwortet.
Kernel-Anforderungen
| Feature | Mindest-Kernel |
|---|---|
| Cilium 1.18+ | 5.10 |
| WireGuard Node Encryption | 5.10 + CVE-2025-37959 Bugfix |
| XDP Native Acceleration | 5.4 (je nach NIC-Treiber) |
| eBPF Host Routing | 5.10 |
| BPF Bandwidth Manager | 5.1 |
k8s_service_host bei HA Controlplane
Bei einem HA-Controlplane mit VIP oder Load Balancer muss k8s_service_host auf die VIP/LB-Adresse zeigen, nicht auf 127.0.0.1. Der Wert wird zur Laufzeit aus primary_ip der Polycrate-Inventory-Variable überschrieben wenn gesetzt.
Hubble und CiliumNetworkPolicies
Hubble ist standardmäßig aktiviert und sammt Flow-Daten für: dns, drop, tcp, flow, icmp, http. Die Daten stehen in der Hubble UI und via hubble observe zur Verfügung:
kubectl exec -n kube-system -it ds/cilium -- hubble observe --last 50
kubectl exec -n kube-system -it ds/cilium -- hubble observe --namespace default --last 50 --output json
hubble-peer / hubble-relay (cilium#44891)
Das Upstream-Helm-Chart setzt hubble-peer fest auf internalTrafficPolicy: Local (kein Values-Knob).
Mit kube-proxy-replacement + Socket-LB kann die lokale Backend-Map auf einzelnen Nodes
in Quarantäne geraten (count=0, qcount=1) — Pods auf diesem Node bekommen dann
connect: operation not permitted zum ClusterIP und hubble-relay CrashLoopt.
Der Block patcht den Service nach dem Helm-Install auf Cluster (Default):
hubble:
enabled: true
# Cluster = Workaround (default). Local = Upstream-Verhalten belassen.
peer_service_internal_traffic_policy: Cluster
Kein Node-Pinning für hubble-relay nötig.