Site icon Daniel's Tech Blog

Cilium ztunnel – native mTLS for Cilium on Azure Kubernetes Service BYOCNI

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:

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

-> https://learn.microsoft.com/en-us/azure/aks/container-network-security-cilium-mutual-tls-concepts#considerations-and-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.

-> https://docs.cilium.io/en/stable/security/network/encryption-ztunnel/#generating-secrets-for-authentication

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.

-> https://github.com/neumanndaniel/kubernetes/blob/master/cilium/network-performance-testing/00_Summary.md

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/

Exit mobile version