Open-Source Wikis

/

Istio

/

Applications

/

istiod (pilot-discovery)

istio/istio

istiod (pilot-discovery)

Active contributors: howardjohn, costinm, hzxuzhonghu, keithmattix, stevenctl

Purpose

Istiod is Istio's control plane: a single Go binary that watches Kubernetes resources, builds an in-memory model of the mesh, signs short-lived workload certificates, runs admission webhooks, and serves Envoy/ztunnel configuration over xDS. It bundles what used to be Pilot, Citadel, and Galley into a modular monolith — see Lore for the consolidation history.

The binary is built from pilot/cmd/pilot-discovery/main.go (~30 lines of cobra plumbing) and starts a long-running gRPC + HTTP server defined in pilot/pkg/bootstrap/server.go. The Helm template that deploys it is manifests/charts/istio-control/istio-discovery/templates/deployment.yaml.

Directory layout

pilot/
├── cmd/pilot-discovery/        # binary entry point + CLI flags
│   ├── main.go
│   └── app/
│       ├── cmd.go              # cobra command, flags
│       ├── options.go          # arg validation
│       └── request.go          # `pilot-discovery request` subcommand for ad-hoc xDS
├── pkg/
│   ├── bootstrap/              # the wiring of the server (1400+ line server.go)
│   ├── model/                  # Proxy, Service, PushContext, sidecar scope
│   ├── networking/core/        # Translation: listeners, clusters, routes, gateways
│   ├── xds/                    # The xDS gRPC server, generators, push queue, debug
│   ├── config/                 # ConfigStore (CRD, file, xDS) and analyzers
│   ├── serviceregistry/        # Kubernetes + ServiceEntry + memory + ambient
│   ├── controllers/            # IP allocation, untaint
│   ├── credentials/            # SDS credential providers
│   ├── status/                 # CRD status reporting
│   ├── trustbundle/            # Aggregated cluster CA bundle
│   ├── leaderelection/         # Leader election helpers
│   ├── server/                 # Generic server lifecycle helpers
│   └── features/               # Env-var gated runtime knobs
└── docker/

Key abstractions

Symbol File Description
bootstrap.Server pilot/pkg/bootstrap/server.go Holds every subsystem; constructor wires dependencies.
bootstrap.PilotArgs pilot/pkg/bootstrap/options.go All CLI flags + env-derived options.
model.PushContext pilot/pkg/model/push_context.go Immutable snapshot of mesh state per push.
model.Proxy pilot/pkg/model/context.go xDS client representation: identity, labels, sidecar scope, computed metadata.
model.IstioConfigStore pkg/config/store.go Aggregate config interface (Get, List, Create, Update, …).
serviceregistry.Instance pilot/pkg/serviceregistry/instance.go Common interface every registry implements.
xds.DiscoveryServer pilot/pkg/xds/discovery.go The xDS server: push queue, generators, ADS dispatcher.
core.ConfigGeneratorImpl pilot/pkg/networking/core/configgen.go Builds Envoy listeners/clusters/routes for a Proxy from a PushContext.
inject.Webhook pkg/kube/inject/webhook.go Mutating admission webhook that injects istio-proxy.
validation.Webhook pkg/webhooks/validation/server/server.go Validating admission webhook for Istio CRs.
ca.IstioCA security/pkg/pki/ca/ca.go The CA: signs CSRs, manages root cert lifecycle.

How it works

sequenceDiagram
    participant K8s as Kubernetes API
    participant Reg as ServiceRegistry<br/>(serviceregistry/*)
    participant CS as ConfigStore<br/>(config/kube/crdclient)
    participant Push as PushContext<br/>(model)
    participant Q as PushQueue<br/>(xds)
    participant Gen as Generators<br/>(networking/core, xds/*.go)
    participant Cache as XDS cache
    participant Stream as ADS stream

    K8s->>Reg: Service / Endpoint / Pod events
    K8s->>CS: VirtualService / DestinationRule / Gateway / ...
    Reg->>Push: incremental updates
    CS->>Push: incremental updates
    Push->>Q: configsUpdated, full=false
    Q->>Gen: pop (Proxy, PushRequest)
    Gen->>Cache: lookup encoded.Any
    Cache-->>Gen: hit (or compute + store)
    Gen->>Stream: Resources (CDS / EDS / LDS / RDS / SDS)

The bootstrap initializer in pilot/pkg/bootstrap/server.go runs in this rough order:

  1. Mesh config and networks — load from file watcher (mounted ConfigMap) or defaults.
  2. Kube clients — primary kubelib.Client, multicluster.Controller for secondary clusters.
  3. CA / Citadel — build the root cert chain, start the CA server. Code in security/pkg/pki/.
  4. ConfigStore — wire CRD, file, and xDS clients into an aggregate store. pilot/pkg/config/aggregate/.
  5. Service registry — Kubernetes controller, ServiceEntry controller, ambient registry, MCS controller.
  6. Trust bundle — collect CA roots from the cluster (cert-manager, Spire, additional roots).
  7. xDS serverpilot/pkg/xds/discovery.go. Register every generator type.
  8. Sidecar injectorpkg/kube/inject/. Build the template renderer, register the webhook handler.
  9. Validation webhookpkg/webhooks/validation/. Validate Istio CRs.
  10. Status reporterpilot/pkg/status/. Publish per-resource sync state.
  11. Leader electionpilot/pkg/leaderelection/. Claim leases for the writer-only roles (status, namespace controller, autoregistration).
  12. HTTP / HTTPS / gRPC servers start on their respective ports.

The push pipeline is the heart of istiod's hot path. A single Server instance handles many proxies; per-proxy work is queued in pilot/pkg/xds/pushqueue.go so a slow client cannot block the rest of the mesh. proxy_dependencies.go filters out proxies that the change cannot affect.

xDS surfaces served

Surface Type URL prefix Generator
CDS type.googleapis.com/envoy.config.cluster.v3.Cluster cds.go, networking/core/cluster*.go
EDS ...endpoint.v3.ClusterLoadAssignment eds.go, endpoints/
LDS ...listener.v3.Listener lds.go, networking/core/listener*.go
RDS ...route.v3.RouteConfiguration rds.go, networking/core/route/
SDS ...auth.v3.Secret sds.go (also served by the per-pod agent)
ECDS ...core.v3.TypedExtensionConfig ecds.go
NDS Istio name table for DNS nds.go, pkg/dns/
wDS (workload) istio.io/...workloadapi/Workload workload.go, pkg/workloadapi/ (ztunnel)
Debug istio.io/debug/... debuggen.go

Note that ztunnel, while still using the xDS framing, gets the Istio-specific workload API instead of Envoy CDS/EDS.

Ports

Default ports configured in pilot/cmd/pilot-discovery/app/cmd.go:

Port Purpose
:8080 Debug HTTP (configz, syncz, edsz, …). Disabled in production by --httpAddr="".
:15010 Plain-text gRPC ADS (legacy / in-cluster only)
:15012 mTLS gRPC ADS (the production endpoint)
:15014 Prometheus metrics + /healthz
:15017 Mutating + validating webhook HTTPS

ControlZ is bound separately (default :9876).

Integration points

  • Reads: Kubernetes API (Services, Endpoints/EndpointSlices, Pods, Nodes, Namespaces), Istio CRs (VS, DR, Gateway, SE, WE, Sidecar, EnvoyFilter, PeerAuth, RequestAuth, AuthZ, Telemetry, WasmPlugin, ProxyConfig), Kubernetes Gateway API (Gateway, HTTPRoute, …), MCS (ServiceImport, ServiceExport), IstioOperator for runtime info.
  • Writes: status conditions on Istio and Kubernetes Gateway resources (pilot/pkg/status/), pod label service.istio.io/canonical-revision via the namespace-untaint controller.
  • Outbound: gRPC ADS to every connected sidecar / gateway / ztunnel / waypoint; gRPC CSR endpoint for the agent CA client.
  • Webhooks: mutating-ns named after the revision, plus validating webhook for Istio CRs.
  • Multi-cluster: secrets in istio-system with the istio/multiCluster=true label trigger pkg/kube/multicluster/ to spawn a per-secondary-cluster set of controllers — those forward services and endpoints into the primary's registry.

Entry points for modification

  • To add a new xDS surface, register a Generator in pilot/pkg/xds/<name>.go and wire it into the XdsServer constructor in bootstrap/server.go. Don't forget to add a debug endpoint.
  • To support a new config kind, add a schema entry to pkg/config/schema/, run make gen, and extend the relevant generator. The CRD client picks up new kinds automatically once they're in the schema.
  • To change generator output for an existing kind, the right place is almost always pilot/pkg/networking/core/. Watch for cache key correctness — the cache is the single biggest source of Pilot CVEs, and -tags=assert will catch most key-mismatch bugs in unit tests.
  • Bootstrap-time initialization order matters. If your subsystem needs the Kubernetes client and the mesh config, register it after both are constructed in server.go.

Key source files

File Purpose
pilot/cmd/pilot-discovery/main.go Cobra entry point
pilot/cmd/pilot-discovery/app/cmd.go All CLI flags and the discovery subcommand
pilot/pkg/bootstrap/server.go Server struct and the wire-everything-up constructor
pilot/pkg/bootstrap/configcontroller.go ConfigStore wiring
pilot/pkg/bootstrap/servicecontroller.go Service registry wiring
pilot/pkg/bootstrap/istio_ca.go CA setup
pilot/pkg/xds/discovery.go XdsServer struct
pilot/pkg/xds/ads.go ADS stream dispatcher (state ofworld, delta variant in delta.go)
pilot/pkg/xds/debug.go Debug HTTP endpoints (~1200 lines)
pilot/pkg/model/push_context.go Snapshot of mesh state
pilot/pkg/model/context.go Proxy and supporting types
pilot/pkg/networking/core/configgen.go Top of the translation pipeline
pilot/pkg/features/pilot.go Env-var-gated feature flags

See also

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

istiod (pilot-discovery) – Istio wiki | Factory