Q: A new Envoy config rollout silently broke mTLS between edge and mesh. What’s your RCA trace?
End-to-end diagnostic RCA runbook for troubleshooting a silent mTLS handshake failure between an edge Ingress Gateway and internal mesh sidecars following a configuration rollout.
#Envoy #mTLS #Istio #RCA #Certificates #OpenSSL #Networking #Incident Response
🎙️ Candidate Opening & Architectural Context
"During a routine mesh configuration rollout, an edge Ingress Gateway begins throwing intermittent 503 Service Unavailable errors (`UC` - Upstream Connection Termination) when routing to internal mesh services. The edge proxy logs show connection resets, while backend services report no incoming HTTP requests. The failure is silent because standard health checks bypass mTLS, leaving the control plane falsely reporting all pods as healthy."
Advertisement
🛠️ Production Runbook & Step-by-Step Resolution
1️⃣
Inspect Envoy Access Log Response Flags
Decode the exact Envoy response flag from the ingress gateway access logs:
kubectl logs -l app=istio-ingressgateway -n istio-system --tail=100 \
| jq -r '.response_flags, .upstream_cluster, .downstream_peer_cert, .response_code'
- Response Flag UC: Upstream Connection failure before request completion, strongly indicating TLS handshake failure.
- Response Flag UF: Upstream connection Failure (connection reset during handshake or certificate rejection).
2️⃣
Verify Secret & SPIFFE Certificate SAN Validation
Compare cryptographic SANs and trust domains between edge and upstream mesh sidecars:
# 1. Inspect Edge Gateway loaded certificates
istioctl proxy-config secret <ingress-pod>.istio-system
# 2. Inspect target service proxy certificates
istioctl proxy-config secret <target-pod>.<namespace>
# 3. Test raw mTLS handshake with OpenSSL s_client using mesh certificates
kubectl exec -it <ingress-pod> -n istio-system -- openssl s_client \
-connect <target-pod-ip>:8443 \
-cert /etc/istio-certs/cert-chain.pem \
-key /etc/istio-certs/key.pem \
-CAfile /etc/istio-certs/root-cert.pem \
-showcerts
- Look for
Verify return code: 19 (self-signed certificate in certificate chain)orcertificate has expired. - Check for SPIFFE identity mismatch: If Ingress Gateway expects
spiffe://cluster.local/ns/prod/sa/paymentbut upstream sends a different trust domain (e.g.cluster.corp), handshake terminates.
3️⃣
Check PeerAuthentication & DestinationRule Conflict
Identify configuration drift between PeerAuthentication (server) and DestinationRule (client):
# Check if server enforces STRICT mTLS while client defaults to DISABLE or PERMISSIVE
kubectl get peerauthentication -A
kubectl get destinationrule -A -o yaml | grep -A 5 "tls:"
4️⃣
Mitigation & Permanent Prevention
Apply immediate traffic remediation and harden future config rollouts:
- Immediate Mitigation: Switch destination rule TLS mode to `ISTIO_MUTUAL` or temporarily relax PeerAuthentication to `PERMISSIVE` to restore customer traffic.
- Root Cause: Rollout updated Istio DestinationRule without specifying `mode: ISTIO_MUTUAL`, causing Ingress to open plaintext HTTP connections to a pod enforcing `STRICT` mTLS.
- Prevention: Enforce CI validation using `istioctl analyze` and automate pre-merge canary validation of mesh manifests.
💡 The Senior SRE Gold Nugget (Key Architectural Takeaway)
"mTLS outages in service meshes almost always stem from policy desynchronization between client DestinationRules (traffic policy) and server PeerAuthentication (enforcement mode)."
⚡ 60-Second Elevator Pitch Talking Points
- I immediately inspect Envoy access logs for response flags: 'UC' (Upstream Connection termination) and 'UF' point directly to a TLS handshake failure.
- I use 'istioctl proxy-config secret' on both the edge ingress and the upstream pod to verify certificate validity, expiration, and SPIFFE trust domain matching.
- I test the raw TLS handshake directly using openssl s_client inside the pod container to observe the exact TLS alert (e.g. unknown CA, cipher mismatch, or SAN rejection).
- In 90% of cases, the root cause is a desync: an upstream service was set to PeerAuthentication STRICT while the newly rolled-out DestinationRule omitted 'mode: ISTIO_MUTUAL'.
- We mitigate by aligning DestinationRule to ISTIO_MUTUAL and prevent recurrence using 'istioctl analyze' in our GitOps deployment pipeline.
Advertisement