The request path, layer by layer

One diagram, two planes. The data plane (bottom, solid arrows) is where your actual bytes travel — client → ingress → sidecar → app. The control plane (top, dashed arrows) never touches a single request; it only pushes configuration and certificates down into every proxy ahead of time.

Full path — client to application container

Follow the numbers. Solid coral/teal = actual request bytes. Dashed purple = config/cert push from the control plane, happening continuously in the background, not per-request.

CONTROL PLANE — config & identity, never touches traffic istiod mesh brain Mesh CA issues + rotates certs K8s Secrets tls.crt / tls.key store PeerAuthentication CRD: mtls mode istiod watches CRDs + Secrets, compiles them into proxy config, pushes over xDS (gRPC) to EVERY Envoy xDS push ↓ (continuous, not per-request) DATA PLANE — where request bytes actually flow ↓ Client browser / mobile / service 1 TLS — public internet Cloud Load Balancer L4 — routes by IP:port, TLS untouched 2 Istio Ingress Gateway (Envoy) TLS terminated here · edge of the mesh holds cert from Secret, config from istiod 3 re-encrypted · mTLS inside mesh Kubernetes Node iptables / CNI redirect transparently routes into sidecar 4 Pod (shared network namespace) Envoy sidecar (istio-proxy) terminates mTLS, verifies peer cert against mesh CA enforces PeerAuthentication + AuthorizationPolicy 5 plaintext · localhost only Application container receives plain HTTP on localhost — no TLS code here 6 response reverses 6→1, re-encrypted at each hop sidecar also intercepts + re-encrypts OUTBOUND calls this pod makes to other services
request bytes / plaintext hop mTLS-encrypted inside mesh control-plane config/cert push (dashed) kernel-level redirect

Decode, step by step

Matches the numbered circles above.

1

Client sends HTTPS request

Standard TLS handshake with the public endpoint. Client only ever talks to the load balancer's public certificate — it has no idea a mesh exists behind it.

2

Cloud load balancer (L4)

Routes by IP and port only. It doesn't open the TLS envelope — just forwards encrypted bytes to the ingress gateway. Not part of Istio.

3

Istio Ingress Gateway — TLS terminates

This is an Envoy process, configured by a Kubernetes Gateway resource. It holds the public cert (from a Secret), decrypts the client's request, and re-encrypts it with mTLS to talk to the destination sidecar. This is the actual "edge" of the mesh.

4

iptables redirect (kernel level)

Istio's init-container installs iptables rules in the pod's network namespace so ALL inbound and outbound traffic is transparently forced through the sidecar — the app never has to be coded to know this is happening.

5

Envoy sidecar — mTLS terminates, policy enforced

Verifies the peer's certificate against the mesh CA, checks it against any AuthorizationPolicy (is this caller allowed to reach this service at all), then decrypts to plaintext.

6

Application container

Receives plain HTTP over localhost. It contains zero TLS logic — it just reads a normal HTTP request, same as if mTLS didn't exist.

Control plane vs data plane — the core distinction

This is the single most-asked interview framing for this stack.

Control plane (istiod) reads CRDs (PeerAuthentication, AuthorizationPolicy, Gateway…) talks to the mesh CA, issues certs pushes compiled config via xDS never sees a single request Data plane (every Envoy) ingress gateway + every sidecar carries the actual request bytes terminates/originates TLS just enforces what control plane said has zero opinions of its own

If istiod crashes, existing traffic keeps flowing fine — the last config each Envoy received stays cached locally. Only new config changes stop propagating. That's the whole reason the split exists: control-plane failure never becomes a traffic outage.