Mutual TLS, or mTLS, is a hot topic in the Kubernetes world, especially for anyone tasked with getting “encryption in transit” for their applications. But what is mTLS, what kind of security does it provide, and why would you want it?
In this article, I’ll cover what mTLS is, how it relates to regular TLS, and why it’s relevant to Kubernetes. I’ll also talk about some of the pros and cons of mTLS and its alternatives.
What Is mTLS and How Does It Relate to TLS
TLS and mTLS are similar, but in a nutshell, mTLS takes one step further by authenticating both the client and the server when requests are made.
When looking at TLS, the authentication happens only on the server side. The server authenticates itself by providing the certificate for the domain that the client is requesting. If the certificate comes from a valid certificate authority, the client can be sure that the server is who it says it is.
Of course, TLS does more than authentication. It also ensures the confidentiality and integrity of the data in transit. No one else can see what data is being exchanged, and the data received is the same data that was sent.
As already mentioned, mTLS goes one step further, specifically in the authentication step. With mTLS, both the client and the server have their own TLS certificates. When a client makes a request to the server, the authentication is bidirectional. Both the server and the client check the authenticity of the other party.
When Is mTLS Useful
Of course, not validating client identity makes sense for serving web pages, but there are plenty of types of communication where the identity of the client is important. API calls are one example: if you’re calling a service like Twilio, then Twilio needs to know who you are—among other reasons, so that they can send you the bill. You can’t make a Twilio API call without providing it with some kind of client identity.
But Twilio doesn’t use mTLS. Instead, you authenticate yourself to Twilio by giving it a secret API key that you were assigned when you created your account. Twilio could use mTLS, but mTLS is complicated and frankly annoying to set up, so if you offer a public API like Twilio you will probably use an API key.
Authentication with mTLS, however, has some powerful characteristics that our API key approach does not. For one, mTLS authentication can be entirely done outside of the application without requiring an app-level feature for creating, registering, or managing identities. Before you can make your first Twilio call, you need to log into the website, create your account, and get your API key. The Twilio API needs to know about this API key and provide ways to pass it to API calls and to manage it.
But with mTLS, a brand-new client can authenticate itself right off the bat, even if no one has seen it before. And the application doesn’t need to know anything about authentication or provide endpoints to manage it.
Putting that all together, we see that mTLS is great for situations where a) you need secure communications; b) you care about client identity; and c) you don’t want to build app-level flows for managing identities.
One situation with all those characteristics is… microservices!
Using mTLS to Secure Microservices
mTLS is a great way to secure the cross-service communication between microservices for all the reasons we outlined above.
First, you want secure communication. When we implement our application as multiple services, we end up sending sensitive customer data across the network between these services. Anyone who gets access to the network can potentially read this sensitive data and forge requests.
Second, you care about client identity. For one, you want to make sure that you can tell where your calls are coming from for diagnostic purposes and so that things like metrics are recorded properly. Moreover, you probably want to do authorization with those identities (is B even allowed to call A?).
Third, mTLS is relatively easy to implement in a Kubernetes cluster using a service mesh. A service mesh is responsible for controlling, securing, and observing service-to-service communication within the cluster. It primarily operates at Layer 7 (the application layer) of the OSI model, although it also influences Layer 4 traffic by managing TCP connections.
The two most popular service meshes for Kubernetes are Linkerd and Istio. Linkerd is a lightweight, simple, and easy-to-operate solution that is well suited for teams that want secure service-to-service communication with minimal configuration. Istio provides a richer feature set, including advanced traffic management, security policies, observability, and integrations, making it a better choice for more complex environments.
Both Linkerd and Istio can automatically enforce mutual TLS (mTLS) by injecting a sidecar proxy alongside each application container (although newer “sidecarless” modes are also becoming available). The sidecar proxies handle certificate exchange, encryption, authentication, and decryption transparently, allowing applications to communicate securely without requiring changes to the application code.
The service mesh is also responsible for managing the certificates used for mTLS. By default, both Linkerd and Istio include their own certificate authority (CA) and automatically rotate workload certificates. However, they can also integrate with external certificate authorities, including cert-manager, when organizations require centralized certificate management or integration with an enterprise PKI.