At KubeCon Europe 2026, the Cilium project announced native mTLS support for Cilium via ztunnel.
-> https://cilium.io/blog/2026/03/23/native-mtls-cilium/
Cilium’s ztunnel implementation is a fork of Istio’s ztunnel, reengineered to directly integrate it with the Cilium control plane and SPIRE as a certificate authority. Bringing ztunnel to Cilium is a joint effort by Isovalent and Microsoft.
In today’s blog post, we have a look at enabling native mTLS for Cilium on an Azure Kubernetes Service BYOCNI environment and compare the results of a conducted network performance test.
At the time of writing, Cilium’s ztunnel transparent encryption feature was still a beta feature.
Setup native mTLS in Cilium
Before we start with setting up native mTLS in Cilium, let us have a quick look at the current limitations and what the traffic flow looks like.
The feature state is beta/public preview, or however you would like to call a non-GA version, and hence comes with some limitations:
- mTLS enablement only works on namespace level for all pods.
- Only TCP pod-to-pod traffic is encrypted. No other protocols, like UDP, are currently supported.
- ztunnel interferes with Cilium network policies.
More limitations and known issues are listed in the Cilium and Azure Kubernetes Service documentation.
-> https://docs.cilium.io/en/stable/security/network/encryption-ztunnel/#limitations
When mTLS is enabled for a namespace, the traffic flow changes slightly for pods depending on the mTLS configuration of the source and destination namespace.
| Source | Destination | ztunnel | Status |
|---|---|---|---|
| Enrolled | Enrolled | ✔️ | Encrypted |
| Enrolled | Non-enrolled | ✔️ | Plaintext |
| Non-enrolled | Enrolled | ✔️ | Plaintext |
| Non-enrolled | Non-enrolled | ✖️ | Plaintext (Normal Cilium datapath) |
Native mTLS in Cilium on an Azure Kubernetes Service cluster with BYOCNI requires a set of private keys and certificates to be present in the Kubernetes cluster. Luckily, in the Cilium documentation, we have a ready-to-go script that helps us with it.
Once generated and rolled out, we configure Cilium to have native mTLS enabled.
... encryption: enabled: true type: ztunnel ...
Finally, we check our Cilium installation by running the following command.
❯ kubectl -n kube-system exec -it ds/cilium -- cilium status | grep -E "Encryption" Encryption: Ztunnel
Everything looks good, and namespaces can now be onboarded to native mTLS by setting a specific label on the namespaces.
kubectl label namespace <namespace-name> io.cilium/mtls-enabled=true
Performance comparison
For the performance comparison, we only focus on the TCP part as UDP is not a supported protocol.
In the table below, you find the test summary, which is also available as a Markdown file.
All tests are available in detail as Markdown files, outlining the test setup configuration and which test commands have been executed.
-> https://github.com/neumanndaniel/kubernetes/blob/master/cilium/network-performance-testing/04_Cilium_Native_Routing.md
-> https://github.com/neumanndaniel/kubernetes/blob/master/cilium/network-performance-testing/08_Cilium_Geneve.md
-> https://github.com/neumanndaniel/kubernetes/blob/master/cilium/network-performance-testing/09_zTunnel_Geneve.md
-> https://github.com/neumanndaniel/kubernetes/blob/master/cilium/network-performance-testing/10_zTunnel_Native.md
| Test | Geneve | Geneve + ztunnel | Native Routing + ztunnel | Native Routing |
|---|---|---|---|---|
| TCP Throughput (Gbit/s) | 7.2 | 9.6 | 12.0 | 12.0 |
| Bidirectional Throughput (TX-C/RX-C) (Gbit/s) | 4.0/2.4 | 4.4/3.8 | 10.5/9.1 | 12.0/11.0 |
| TCP Latency (Mean µs/Transaction Rate) | 164/6095 | 330/3030 | 261/3822 | 124/ 8072 |
| TCP Stream (Throughput 10^6bits/sec) | 6809 | 4608 | 6664 | 11927 |
Depending on which tests we are looking at, ztunnel has either zero impact, improves performance, or has an impact.
Generally speaking, ztunnel shows a better performance than WireGuard, and we might see improvements on the TCP Latency and Stream tests in the future with the GA version.
However, to outline it here, WireGuard encryption covers all traffic for encryption, including node-to-node traffic, whereas native mTLS only supports TCP pod-to-pod as of now.
Summary
Cilium’s native mTLS support via ztunnel is a promising new option for transparent traffic encryption and mTLS integration with SPIRE.
All the test results, configurations, and summaries are available on my GitHub repository.
-> https://github.com/neumanndaniel/kubernetes/blob/master/cilium/network-performance-testing/