ICA — Istio Certified Associate
Why istiod Was Collapsed Into One
In one line
Istio completely separated "the side that produces configuration (istiod)" from "the side that touches packets (Envoy)." Thanks to this separation, traffic keeps flowing even if the control plane dies, and conversely, changing only the control plane changes the behavior of the entire mesh.
Why this was needed
Before Istio 1.5, Pilot (traffic), Citadel (certificates), Galley (configuration validation), and Mixer (policy and telemetry) each ran as a separate Pod. The problem was the operating cost that arose from these four calling one another. When one component died, it was hard to tell which function stopped, and Mixer in particular was a structure that called the control plane on every request, so latency and failures on the data path were tied directly to the control plane.
So in 1.5, Pilot, Citadel, and Galley were merged into a single binary called istiod, and Mixer was removed altogether in 1.8. Telemetry changed to being generated directly by filters inside Envoy. The point is not that "components were reduced" but that control plane calls were completely removed from the data path.
How it works
istiod watches the Kubernetes API, reads changes to Services, Endpoints, Pods, and Istio CRDs, translates them into configuration that Envoy understands, and pushes it over a gRPC stream. This protocol is xDS.
| API | What it sends down |
|---|---|
| LDS | Listeners — which port is listened on, with which protocol |
| RDS | Routes — which request is sent to which cluster |
| CDS | Clusters — the definition of a destination group (LB, circuit breaker, TLS) |
| EDS | Endpoints — the Pod IPs actually inside that cluster |
| SDS | Certificates and keys |
Istio bundles these five into a single gRPC stream called ADS (Aggregated Discovery Service). The reason is ordering, not bandwidth. If an endpoint (EDS) arrives before the cluster (CDS) is defined, Envoy receives an address with nowhere to go, and if a route (RDS) comes before its listener (LDS), there is nothing to attach it to. With a single stream, the order is guaranteed and the configuration is swapped in atomically.
Inside Envoy, a destination exists under a name like this.
outbound|9080|v2|reviews.default.svc.cluster.local
방향 포트 subset FQDN
If you can read this string in istioctl proxy-config cluster, you are halfway there. If the subset position is empty, it means there is no DestinationRule, and if the name is missing altogether, it means that service is outside this proxy's field of view.
Inside a Pod, the istio-init container plants iptables rules that bend traffic to the proxy. Inbound goes to 15006 and outbound goes to 15001. At this point only traffic with UID 1337 is excluded from the redirect, because that UID is istio-proxy itself. If it were not excluded, packets sent out by the proxy would come back to the proxy and form an infinite loop. If you also memorize 15008 (the HBONE tunnel), 15020 (the agent's merged health and metrics), 15021 (health check), and 15090 (Prometheus metrics), you will not miss port questions on the exam.
One last important property. Even if istiod dies completely, an Envoy that is already running keeps handling traffic with the last configuration it received. What stops is propagation of new configuration and certificate renewal, not the data path. So an istiod outage is not an "immediate total outage" but a "state with a deadline," and the certificate lifetime (24 hours by default) becomes the real timer.
What it looks like in the field
The author's homelab has 7 nodes (cp-1/2/3 + gpu-a/b/c/d) and stands on Kubernetes v1.34.10, containerd 1.7.27, and kernel 6.14 with Cilium 1.20.1. No sidecar mesh is running on it, and this contrast actually helps in understanding Istio.
This cluster was built with kubeadm init --skip-phases=addon/kube-proxy, without ever installing kube-proxy. A kube-proxy that has run even once etches KUBE-SERVICES / KUBE-SVC-* / KUBE-SEP-* chains onto the node, and even if you delete the DaemonSet, those rules remain and conflict with the eBPF datapath. In measurement there were 0 kube-proxy Pods and 0 iptables KUBE- chains.
The lesson here applies equally to Istio. Sidecar injection is the act of etching iptables rules inside the Pod's network namespace, and even if you remove the injection label later, the rules of a Pod that is already running stay as they are until the Pod is restarted. This is the answer to the question "I removed the label, so why is it still going through the proxy?" The configuration is declarative, but the traces left on nodes and Pods are imperative.
What to check in the next quiz
This module covers concepts only. After checking your sense of the architecture with the quiz, in the next module you write a VirtualService and a DestinationRule yourself and confirm by hand how the outbound|포트|subset|FQDN seen above (the second field is the port) is created.