Istio’s automatic TLS encryption, the bedrock of its secure service mesh, is fundamentally a certificate management problem.
Here’s how Istio and cert-manager can be set up to automate this, giving you a concrete example of a multi-cluster setup where certificates are issued and distributed.
Imagine a scenario with two Kubernetes clusters, cluster-a and cluster-b, both running Istio. We want cluster-a’s Istio ingress gateway to be able to securely communicate with services in cluster-b, and vice versa. This requires each gateway to trust the other’s root CA.
First, we need a ClusterIssuer in cluster-b that cert-manager will use to obtain certificates for cluster-a’s gateway. Let’s assume we’re using Let’s Encrypt for this example.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging-cluster-b
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: your-email@example.com
privateKeySecretRef:
name: letsencrypt-staging-cluster-b-private-key
solvers:
- http01:
ingress:
class: nginx # Or your ingress class
Now, in cluster-a, we’ll create a Certificate resource that requests a certificate for cluster-a’s ingress gateway. This certificate will be issued by the ClusterIssuer in cluster-b.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: istio-ingress-gateway-cert
namespace: istio-system
spec:
secretName: istio-ingressgateway-certs
dnsNames:
- istio-ingressgateway.cluster-a.example.com # Your gateway's external DNS
issuerRef:
name: letsencrypt-staging-cluster-b # Reference the issuer in cluster-b
kind: ClusterIssuer
group: cert-manager.io
This Certificate resource will trigger cert-manager in cluster-b to issue a certificate. The challenge-response (e.g., HTTP01) will need to be solvable from cluster-b’s perspective, meaning cluster-a’s ingress gateway must be reachable from cluster-b for this verification. Once issued, the certificate and its private key will be stored in a Kubernetes Secret named istio-ingressgateway-certs in the istio-system namespace of cluster-a.
Istio’s ingress gateway is typically configured to automatically pick up certificates from a secret named istio-ingressgateway-certs in its own namespace. You’d ensure your IstioOperator or istioctl install configuration includes a reference to this secret for the ingress gateway.
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
components:
ingressGateways:
- name: istio-ingressgateway
enabled: true
k8s:
env:
- name: PILOT_CERT_PROVIDER
value: "istiod" # Or the appropriate value for your Istio version
# This section might vary slightly based on Istio version and installation method.
# The key is ensuring Istio knows to look for the gateway's certificate.
# Often, Istio automatically picks up secrets named 'istio-ingressgateway-certs'
# or similar in the ingress gateway's namespace.
The magic here is that cert-manager in cluster-b is acting as the Certificate Authority (CA) for cluster-a’s gateway. The ClusterIssuer in cluster-b is configured to use a specific ACME server (like Let’s Encrypt staging) and stores its private key securely. The Certificate resource in cluster-a acts as a request, specifying the desired hostnames and pointing to the remote ClusterIssuer.
To make this truly work across clusters, you’d repeat this process in reverse: create an issuer in cluster-a and a certificate in cluster-b for cluster-b’s ingress gateway. Then, you’d need to configure Istio’s trust domain to trust certificates issued by the CA of the other cluster. This often involves manually importing the root CA certificate of each cluster into the other’s Istio configuration.
A common pattern is to have a dedicated CA in one cluster (or even outside Kubernetes) and use that single CA to issue certificates for all ingress gateways across your mesh. This centralizes trust and simplifies management.
The most surprising part of managing Istio TLS with cert-manager is how seamlessly cert-manager can operate across cluster boundaries, provided network connectivity for the ACME challenge and that the ClusterIssuer references are correctly configured. It’s not just about issuing certificates within a cluster but orchestrating certificate issuance between clusters.
This automation extends to internal Istio communication as well. Istio’s istiod (the control plane) can itself be configured to use cert-manager for its own signing certificate. When istiod uses cert-manager, it means that all workload certificates (for East-West traffic between pods) are also managed by cert-manager, leveraging the same automation for internal service-to-service encryption.
The ca section of the IstioOperator configuration is where you’d point istiod to use cert-manager for its root CA. This often involves creating a Certificate resource for istiod itself and then referencing the Secret containing that certificate in the IstioOperator.
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
meshConfig:
caCertificates:
- certs:
- certs.istio-system.svc.cluster.local # Example, may need adjustment
- istiod.istio-system.svc.cluster.local # Example, may need adjustment
name: cacerts # Name of the secret containing the CA bundle
This cacerts secret would be populated by cert-manager, which would be managed by a Certificate resource requesting a CA certificate. The ClusterIssuer for this CA certificate would typically be a self-signed issuer or a managed CA service.
The next logical step after automating ingress gateway certificates is to explore how to integrate cert-manager with Istio’s istiod for managing the mesh’s root CA, which then automates workload identity certificates.