Zurück zum Hub

cargo.ayedo.cloud/ayedo/k8s/cilium

Registry-Block

polycrate block pull cargo.ayedo.cloud/ayedo/k8s/cilium:0.6.5

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)
  • kubectl und helm auf dem Polycrate-Host verfügbar
  • Für kube-proxy Replacement: kubeadm-Cluster mit --skip-phases=addon/kube-proxy oder 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 auf ImagePullBackOff. Vivavis: erst testen, wenn Egress/Registry wieder steht.
  • Hubble Relay beendet sich beim Shutdown jetzt sauber; nach dem Upgrade kurz hubble-relay und hubble-peer prüfen (bekanntes KPR/Socket-LB-Thema, Block-Default peer_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 status und ein Service-Smoke (NodePort/ClusterIP) machen.
  • cilium-dbg map events darf 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-termination mit custom CNI, enableIdentityMark auß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)
  • CiliumBGPPeerConfig
  • CiliumBGPAdvertisement
  • CiliumBGPNodeConfigOverride (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.