Istio Istio

Istio Architecture: Sidecars, the Data Plane, and the Control Plane

What istiod actually does, how Envoy sidecars fit in, and why neither your app nor its manifests need to know Istio exists.

9 min Beginner

Istio adds traffic management, security, and observability to a set of microservices without touching their code. That’s only possible because of how its two halves divide the work: a data plane that actually handles traffic, and a control plane that tells the data plane what to do. This guide covers both, and the sidecar model that connects them to your workloads.

The sidecar: a proxy riding alongside your container

In Istio’s default mode, every workload Pod gets a second container injected alongside your application’s own: an Envoy proxy, configured to intercept all of that Pod’s inbound and outbound traffic. Your application still binds to its port and makes outbound calls exactly as if nothing were different; the sidecar sits transparently in the path, which is the entire point. The application never needs to know the proxy is there.

What that buys you: TLS, retries, timeouts, load balancing, and authorization move out of application code and into configuration applied to the proxy. A development team writes business logic; the mesh handles the network concerns uniformly across every service, rather than each team re-implementing (or forgetting to implement) its own version of the same concerns.

The data plane: Envoy, doing the actual work

The data plane is the collection of all those sidecar proxies, actually carrying every request between services. This is where traffic is encrypted, where a request is retried after a timeout, where one version of a service might receive 10% of traffic for a canary release. The data plane doesn’t decide policy on its own; it enforces whatever configuration the control plane has pushed to it.

The control plane: istiod

istiod is Istio’s control plane, running as its own set of Pods in the istio-system namespace. It does three distinct jobs:

  • Configuration distribution. You express intent, in Istio’s own Kubernetes resources, like “split traffic 90/10 between these two versions.” istiod translates that into Envoy’s native configuration format and pushes it to every relevant sidecar, so you never hand-write Envoy configuration directly (the previous “Learn” series on Envoy in this library covers what that underlying configuration actually looks like, for anyone curious what istiod is generating).
  • Certificate authority. istiod issues and rotates the certificates every sidecar uses for mutual TLS, so service-to-service traffic is encrypted and each side can verify the other’s identity, without any application code managing certificates itself.
  • Service discovery and policy. istiod tracks what services exist and where, and distributes authentication and authorization policy to the proxies that need to enforce it.

Sidecar injection: how a Pod actually gets a proxy

Installing Istio by itself changes nothing about your running workloads. Sidecar injection is a separate, explicit step: label a namespace (istio-injection=enabled), and any Pod created in that namespace afterward automatically gets an Envoy sidecar added to its spec at creation time. Existing Pods aren’t retroactively modified; they need to be recreated (deleted and reapplied, or rolled via a Deployment) after the label is in place before they pick up the sidecar.

This opt-in-per-namespace design is deliberate. Automatically meshing every namespace in a cluster, including system namespaces that were never meant to run a sidecar, would add resource overhead and complexity nobody asked for. Labeling gives you control over exactly which workloads are meshed.

A Pod with its sidecar shows two containers where an unmeshed equivalent shows one:

kubectl get pods
# NAME                READY   STATUS
# reviews-v1-abc123   2/2     Running   ← sidecar present
# ratings-v1-def456   1/1     Running   ← no sidecar (unlabeled namespace)

For a workload that needs a sidecar without labeling its whole namespace, manual injection (istioctl kube-inject) adds the sidecar to a single manifest before it’s applied, covered in the next guide along with the rest of installation.

A note on ambient mode

Everything above describes Istio’s original, sidecar-based architecture, which is what the rest of this series covers. Istio also offers an alternative, sidecar-less ambient mode, splitting the data plane into a per-node component (ztunnel) and a per-namespace waypoint proxy instead of injecting a proxy into every Pod, aimed at reducing the resource overhead of running one Envoy per workload. It’s a substantial enough architectural difference that it’s out of scope for this series; what you learn about traffic management and security concepts here still applies conceptually under ambient mode, but the mechanics of how traffic is intercepted differ. Consult Istio’s own documentation if ambient mode is specifically what you’re evaluating.

Popular Guides