Kublr natively supports Cilium as a CNI provider. Cilium is an eBPF-based open source solution for securing and observing network connectivity between application services. Because eBPF runs inside the Linux kernel, Cilium security policies can be applied and updated without any changes to application code or container configuration.
When installed into a Kublr-managed cluster, the following Cilium features are available:
kube-proxy replacement — Cilium fully replaces kube-proxy using an eBPF-based dataplane, reducing CPU utilization and latency while improving throughput and scale. See Kubernetes Without kube-proxy.
Inter-node traffic encryption with WireGuard (kernel ≥ 5.6 with WireGuard module, or kernel ≥ 5.15 built-in) or IPsec.
NOTE WireGuard is the recommended option. IPsec requires additional key and CA configuration.
Hubble — eBPF-powered networking, service, and security observability. Provides service dependency maps, network monitoring, application monitoring, and security visibility with minimal overhead.
ClusterMesh — multi-cluster networking and service discovery.
To create a new Kublr cluster with Cilium, select cni-cilium in the new cluster creation form, Cluster tab,
Advanced Options section, CNI Provider field or, if you are using the cluster specification directly,
set spec.network.provider to cni-cilium as shown below:
spec:
network:
provider: cni-cilium
podCIDR: 10.0.0.0/16
serviceCIDR: 10.96.0.0/12
# ... other network parameters
When this provider is set, the Kublr agent automatically:
kube-proxy static pod manifest from all nodes (kubelet deletes the pod automatically).cni-cilium-chart.yaml addon, which causes the helm-manager to install the Cilium Helm chart into the cluster.All Cilium configuration is passed as Helm values via kublrAgentConfig in the cluster specification.
This is the only supported configuration path - fields directly under spec.network.cilium
(such as clusterId or hubbleEnabled) are not reliably processed and should not be used.
The configuration is set at the cluster level (applies to all nodes):
spec:
kublrAgentConfig:
cluster:
network:
cilium:
helm_values:
# Cilium Helm values go here
prop1: overrideValue
Note that if it is necessary to unset some values by specifying null, the helm_values field must be set as a multi-line
string to protect from Kublr API discarding null-valued fields.
This format can also be useful when implementing advanced templates in the configuration (available since Kublr 1.28):
spec:
parameters:
foo: bar
kublrAgentConfig:
cluster:
network:
cilium:
helm_values: |
# Cilium Helm values go here
# null values are treated by helm as a signal to remove the property defined in the default values.yaml
prop1: null
prop2: {{.spec.parameters.foo}}
spec:
network:
provider: cni-cilium
podCIDR: 10.0.0.0/16
serviceCIDR: 10.96.0.0/12
kublrAgentConfig:
cluster:
network:
cilium:
helm_values: |
cluster:
id: 0
name: my-cluster
spec:
network:
provider: cni-cilium
podCIDR: 10.0.0.0/16
serviceCIDR: 10.96.0.0/12
kublrAgentConfig:
cluster:
network:
cilium:
helm_values: |
cluster:
id: 1
name: my-cluster
encryption:
enabled: true
nodeEncryption: true
type: wireguard
hubble:
enabled: true
peerService:
clusterDomain: cluster.local
ui:
enabled: true
relay:
enabled: true
dashboards:
enabled: false
NOTE
cluster.idmust be a unique integer in the range 1-255 across all clusters if ClusterMesh is planned. Use0to disable ClusterMesh.
NOTE If the cluster DNS domain is not the default
cluster.local(i.e.spec.network.dnsDomainis set to a custom value), you must sethubble.peerService.clusterDomainto match. Otherwise the Hubble relay will fail to resolve the peer service and enter a crash loop.
Refer to the Cilium Helm chart values reference for full documentation of specific values that can be set.
Kublr enables kube-proxy replacement automatically when provider: cni-cilium is set. No additional configuration is required.
Cilium provides an eBPF-based alternative to the iptables/IPVS mechanisms implemented by kube-proxy, with lower CPU utilization, reduced latency, improved throughput, and better scalability.
encryption:
enabled: true
type: wireguard
nodeEncryption: true
Encrypts all node-to-node traffic transparently, with no application changes or additional proxies required. Cilium handles automatic key rotation with overlapping keys. All traffic is encrypted including non-standard protocols such as UDP.
Requirements: Linux kernel ≥ 5.6 with the wireguard module, or kernel ≥ 5.15 where WireGuard is built in.
hubble:
enabled: true
peerService:
clusterDomain: cluster.local # set to your cluster DNS domain
ui:
enabled: true
relay:
enabled: true
dashboards:
enabled: false # set to true only if Grafana is configured with sidecar dashboard discovery
Hubble provides deep visibility into service communication and networking behavior. When enabled, the Hubble UI is accessible via port-forward:
kubectl port-forward -n kube-system svc/hubble-ui 12000:80
Then open http://localhost:12000 in a browser.
Hubble Grafana dashboards (IDs: 16611–16614) can be imported manually from grafana.com.
This section describes how to migrate a running Kublr cluster from Calico (or Canal) CNI to Cilium. The migration replaces the CNI without requiring cluster recreation. Some brief downtime is expected while traffic routing transitions from Calico to Cilium.
Before starting, verify:
All nodes run Linux kernel ≥ 5.6 (for WireGuard; ≥ 5.15 recommended for built-in support).
No Calico-specific resources are in use that have no Cilium equivalent:
kubectl get globalnetworkpolicies.crd.projectcalico.org
kubectl get hostendpoints.crd.projectcalico.org
kubectl get bgppeers.crd.projectcalico.org
Standard NetworkPolicy objects are fully supported by Cilium without changes.
Take note of your current pod CIDR and service CIDR — these are preserved during migration.
In the Kublr Control Platform, navigate to the cluster and edit its specification. Change spec.network.provider from cni-canal (or cni-calico) to cni-cilium, and add the kublrAgentConfig section with your desired Cilium Helm values:
spec:
network:
provider: cni-cilium # was: cni-canal or cni-calico
# all other network parameters remain unchanged
kublrAgentConfig:
cluster:
network:
cilium:
helm_values: |
cluster:
id: 1
name: my-cluster
encryption:
enabled: true
nodeEncryption: true
type: wireguard
hubble:
enabled: true
peerService:
clusterDomain: cluster.local
ui:
enabled: true
relay:
enabled: true
dashboards:
enabled: false
After saving, the Kublr agent propagates the change to all nodes. It will:
kube-proxy static pod manifest from each node.cni-cilium-chart.yaml addon file on master nodes.NOTE The Calico Helm release is not automatically removed when the CNI provider changes. Calico and Cilium will run simultaneously until Calico is explicitly removed in a later step.
Wait for all Cilium pods to reach Running state:
kubectl get pods -n kube-system -l k8s-app=cilium -w
Verify Cilium is healthy using the Cilium CLI:
kubectl -n kube-system exec ds/cilium -- cilium status
Expected output shows all components OK, encryption enabled, and all nodes reachable:
/¯¯\
/¯¯\__/¯¯\ Cilium: OK
\__/¯¯\__/ Operator: OK
/¯¯\__/¯¯\ Envoy DaemonSet: OK
\__/¯¯\__/ Hubble Relay: OK
\__/ ClusterMesh: disabled
Cluster health: 9/9 reachable
Also verify encryption is active:
kubectl -n kube-system exec ds/cilium -- cilium status --verbose | grep -A4 Encryption
Once Cilium is healthy, remove Calico completely.
3a. Uninstall the Calico Helm release:
If the tigera-operator Helm release exists (check with helm list -n tigera-operator):
helm uninstall tigera-operator -n tigera-operator --no-hooks
The --no-hooks flag is required if any pre/post-delete Jobs from a previous operation are still present in a completed state.
3b. Delete all Calico and Tigera CRDs:
kubectl get crd | grep -E 'projectcalico\.org|tigera\.io' | awk '{print $1}' | xargs kubectl delete crd
3c. Delete the Calico namespaces:
kubectl delete namespace calico-system tigera-operator calico-apiserver --ignore-not-found
If any namespace gets stuck in Terminating, it is likely due to tigera.io/cni-protector finalizers on service accounts inside the namespace. Remove them:
# Example for calico-system namespace
for sa in calico-cni-plugin calico-node; do
kubectl patch serviceaccount $sa -n calico-system \
-p '{"metadata":{"finalizers":[]}}' --type=merge
done
Similarly, if the installations.operator.tigera.io CRD itself is stuck deleting:
kubectl patch crd installations.operator.tigera.io \
-p '{"metadata":{"finalizers":[]}}' --type=merge
After Calico is removed, some pods (particularly DaemonSets that were not restarted during the migration) may still hold IP addresses from the old CNI. Check the count of Cilium-managed pods:
cilium status | grep "Cluster Pods"
If the managed count is less than the total running pod count, identify the unmanaged pods and restart their controllers:
# Restart all DaemonSets in all namespaces to pick up new Cilium networking
kubectl get ds -A --no-headers | awk '{print $1, $2}' | while read ns name; do
kubectl rollout restart daemonset/$name -n $ns
done
Wait for the rollout to complete and re-verify cilium status.
Run a full connectivity test using the Cilium CLI:
cilium connectivity test
Verify node-to-node encryption (WireGuard peers should equal the number of other nodes):
kubectl -n kube-system exec ds/cilium -- cilium status --verbose | grep -A10 Encryption
Check Hubble is receiving flows:
cilium hubble observe --last 20
Use the Cilium CLI to inspect cluster state:
# Overall status
cilium status
# Verbose status including encryption peers and IPAM
kubectl -n kube-system exec ds/cilium -- cilium status --verbose
# List all Cilium-managed services (eBPF load balancer)
kubectl -n kube-system exec ds/cilium -- cilium service list
The Cilium CLI includes a built-in network performance test:
cilium connectivity test --perf
Hubble enables deep visibility into service communication, network flows, and security events. It operates at the node level and, when ClusterMesh is configured, across clusters.
Access the Hubble UI via port-forward:
kubectl port-forward -n kube-system svc/hubble-ui 12000:80
Observe live network flows from the CLI:
cilium hubble observe --follow
cilium hubble observe -n my-namespace --last 50
See the Introduction to Cilium & Hubble for full documentation.
This documentation:
Cilium documentation:
MS Azure documentation: Bring your own Container Network Interface (CNI) plugin with Azure Kubernetes Service (AKS)