Cilium in AKS is surprisingly more about optimizing network policy enforcement than it is about basic pod networking.

Let’s see it in action. Imagine you have a simple AKS cluster and you want to deploy an application.

# First, ensure you have the Azure CLI and kubectl installed and configured
az login
az account set --subscription <your-subscription-id>
az aks get-credentials --resource-group <your-resource-group> --name <your-aks-cluster-name>

# Now, let's install Cilium using Helm. We'll enable the Azure integration.
helm repo add cilium https://helm.cilium.io/
helm repo update

helm install cilium cilium/cilium --version 1.14.0 \
  --namespace kube-system \
  --set azure.enabled=true \
  --set ipam.mode=azure \
  --set kubeProxyReplacement=strict \
  --set k8sServiceHost=<aks-api-server-address> \
  --set k8sServicePort=443 \
  --set cluster.name=<your-cluster-name> \
  --set autoDirectNodeRoutes=true \
  --set enableIPv4=true \
  --set enableIPv6=false

This command installs Cilium into the kube-system namespace. The --set azure.enabled=true and --set ipam.mode=azure flags are critical for AKS, telling Cilium to leverage Azure’s native networking capabilities for IP address management and integration. kubeProxyReplacement=strict means Cilium will handle all service routing, bypassing the traditional kube-proxy. autoDirectNodeRoutes=true optimizes routing between nodes.

Once installed, Cilium pods will run on each node. You can verify this:

kubectl get pods -n kube-system -l app.kubernetes.io/part-of=cilium

You should see pods like cilium-XXXXX running. These are the core agents. Cilium replaces kube-proxy and also acts as the CNI plugin, managing pod network interfaces and routing.

The primary problem Cilium solves in AKS, beyond basic pod-to-pod connectivity, is granular, identity-aware network policy enforcement. Instead of relying solely on CIDR blocks, Cilium can use Kubernetes labels and even identity information derived from network flows to define policies.

Consider a scenario where you want to restrict communication between your frontend and backend pods. With standard Kubernetes NetworkPolicies, you’d typically use label selectors.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: frontend-to-backend
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 8080

This is standard. But Cilium’s power comes from its eBPF-based implementation. It intercepts network packets at the kernel level. This allows it to make decisions much earlier and more efficiently than traditional methods. It can enforce policies based on service identity, not just IP addresses.

Let’s look at a Cilium NetworkPolicy, which offers more advanced features.

apiVersion: cilium.io/v1alpha1
kind: CiliumNetworkPolicy
metadata:
  name: frontend-to-backend-cilium
  namespace: default
spec:
  endpointSelector:
    matchLabels:
      app: frontend
  egress:
  - toEndpoints:
    - matchLabels:
        app: backend
    toPorts:
    - ports:
      - protocol: TCP
        port: 8080

This looks similar, but CiliumNetworkPolicy can leverage io.cilium.network-policy.k8s.io/default or io.cilium.network-policy.k8s.io/strict annotations for more advanced behavior. Crucially, Cilium’s eBPF datapath means policy enforcement happens directly in the kernel for each pod, minimizing overhead and maximizing performance. It can also enforce policies on ingress traffic and provide L7 awareness if needed, by inspecting application-level protocols like HTTP.

The most surprising thing about Cilium in AKS is how it decouples network policy from IP address management. By default, AKS assigns IP addresses from a VNet subnet to pods. Cilium, when configured with ipam.mode=azure, integrates with this. However, its policy enforcement engine operates on identities (Kubernetes labels, service names, etc.), not just IP addresses. This means policies remain stable even if pod IPs change, which is a common occurrence in dynamic Kubernetes environments.

When you use Cilium, especially with kubeProxyReplacement=strict, you’re essentially handing over all service routing and network policy enforcement duties to Cilium’s eBPF programs. This means the traditional kube-proxy service is no longer managing your Kubernetes Services. Cilium implements its own Service handling logic directly in the kernel.

If you encounter issues after initial installation, the most common next step is to check the Cilium agent logs for errors related to CNI plugin registration or BGP peering if you’re using advanced routing.

Want structured learning?

Take the full Aks course →