istio/istio
Sidecar injection
Active contributors: hzxuzhonghu, ramaraochavali, zirain, keithmattix
Purpose
Sidecar injection is the mutating-admission-webhook flow that adds the istio-proxy container (and supporting init containers, volumes, and probes) to a Pod at admission time. It is how Istio gets Envoy into application pods without requiring users to modify their manifests.
The same library also drives istioctl kube-inject, the offline equivalent used for clusters where webhooks cannot be installed.
Directory layout
pkg/kube/inject/
├── inject.go # Top-level inject logic; ~1000 lines
├── webhook.go # The MutatingAdmission HTTP handler (~1500 lines)
├── template.go # Template rendering (Go text/template + Sprig)
├── validate.go # Validation of injection requests
├── watcher.go # ConfigMap + revision watching
├── initializer.go # Init-container choices (CNI vs istio-init)
├── app_probe.go # Probe rewriting (k8s probe → agent-mediated)
├── openshift.go # OpenShift SCC adjustments
└── monitoring.go
manifests/charts/istio-control/istio-discovery/files/
├── injection-template.yaml # The template the webhook renders
└── ...The actual istio-proxy template lives in the istio-discovery Helm chart at manifests/charts/istio-control/istio-discovery/files/injection-template.yaml. It is a Go text/template that produces the JSON patch the webhook returns.
Key abstractions
| Symbol | File | Role |
|---|---|---|
Webhook |
webhook.go |
The MutatingAdmission HTTP handler |
WebhookConfig |
webhook.go |
Aggregated config: template, mesh config, valuesConfig, revisions |
InjectionConfig |
inject.go |
Parsed inject configuration |
InjectionParameters |
inject.go |
The struct passed to the template |
Watcher |
watcher.go |
Watches the istio-sidecar-injector ConfigMap |
applyAppProberRewrite |
app_probe.go |
Probe translation |
How it works
sequenceDiagram
participant API as kube-apiserver
participant Webhook as Istiod MutatingWebhook
participant Tpl as Template renderer
participant Pod as Original Pod
API->>Webhook: AdmissionReview (Pod create)
Webhook->>Webhook: validate (annotation, namespace label, revision)
Webhook->>Tpl: render with InjectionParameters
Tpl->>Tpl: apply template w/ Sprig + custom funcs
Tpl-->>Webhook: rendered Pod spec
Webhook->>Webhook: diff vs original → JSON patch
Webhook-->>API: AdmissionResponse(patch)
API->>Pod: Pod created with istio-proxy + istio-initSelection: who gets injected
Injection is gated by:
- The namespace label
istio-injection=enabled(legacy default) or the per-namespaceistio.io/rev=<revision>label (revision-based, the modern path). - The pod-level
sidecar.istio.io/injectannotation overrides namespace-level. - Per-pod
istio.io/revoverrides namespace-level revision. - Pods that already have an
istio-proxycontainer (already injected, e.g. byistioctl kube-inject) are skipped. - Pods in the
istio-systemnamespace are not injected.
The selection logic is in webhook.go's injectRequired. The companion command istioctl experimental check-inject pod/<name> walks the same logic offline so users can debug "why didn't this pod get injected".
Revisions and tags
Multiple istiods can run side-by-side, each labeled with a revision (istio.io/rev=<rev>). Each runs a webhook with a namespaceSelector matching that revision. Tags (istioctl tag) let users define stable aliases (default, prod, canary) that point to revisions; switching the tag re-routes new pods to the new control plane without changing namespace labels.
The webhook trees in manifests/charts/istio-control/istio-discovery/templates/mutatingwebhook.yaml define the revision-aware selectors.
Probe rewriting
app_probe.go rewrites Kubernetes-native HTTP/gRPC/TCP probes so they go through the istio-proxy health endpoint (15021) which the agent mediates. Without this, when iptables redirects all traffic, kubelet's probe traffic would be intercepted by Envoy and (for HTTP probes that lack mTLS) rejected.
The rewriter encodes the original probe parameters into agent-readable form via the KUBE_APP_PROBERS env var on the istio-proxy container. The agent (pilot-agent status) decodes that env at startup and translates kubelet's calls back into the original probe.
Init container choice
initializer.go decides what init container to add:
- If
istio-cniis detected (the namespace has the relevant label and the CNI plugin is installed), no init container is needed — CNI handles redirection. - Otherwise, an
istio-initcontainer withpilot-agent istio-iptablesruns. This requiresNET_ADMIN/NET_RAWcapabilities and is therefore the less secure path.
The detection logic looks at the cluster's CNI install (istio-cni-config ConfigMap) and the namespace label k8s.v1.cni.cncf.io/networks.
Template
The template at manifests/charts/istio-control/istio-discovery/files/injection-template.yaml is what produces the actual Pod patch. It renders:
- The
istio-proxycontainer (Envoy + pilot-agent), with image, env, volume mounts, resource requests, security context. - The
istio-initcontainer (when needed). - The
istio-tokenprojected volume. - The
istio-dataemptyDir for SDS UDS. - The
istio-podinfodownward API volume. - Per-pod annotations like
prometheus.io/pathfor stats merging.
Users can override the template via the istio-sidecar-injector ConfigMap (the watcher in watcher.go picks this up live).
Validating webhook (separate)
The companion validating webhook lives in pkg/webhooks/validation/. It validates Istio CRs (VirtualService, DestinationRule, etc.) on admission so misconfigurations fail fast at apply time rather than producing broken Envoy configs.
Integration points
- Reads from: the
istio-sidecar-injectorConfigMap (template, defaults, neverInjectSelector, etc.); theistioConfigMap (mesh config); namespace and pod labels at admission time. - Writes to: HTTP admission response only; never modifies the cluster directly.
- Cluster resources:
MutatingWebhookConfigurationper revision. The CA bundle in the webhook config is patched bypkg/webhooks/webhookpatch.goso istiod's own CA can sign it.
Entry points for modification
- New container/volume → edit
manifests/charts/istio-control/istio-discovery/files/injection-template.yaml. Goldens live inpkg/kube/inject/testdata/. Regenerate withmake refresh-goldens. - New annotation → add a known annotation in
pkg/config/annotation/(the schema), then handle it ininject.goor the template. - New init-container choice →
initializer.go. - Probe handling change →
app_probe.goplus the agent-side decoder inpilot/cmd/pilot-agent/status/.
Key source files
| File | Purpose |
|---|---|
pkg/kube/inject/webhook.go |
The HTTP webhook handler |
pkg/kube/inject/inject.go |
The inject library; entry point for istioctl kube-inject |
pkg/kube/inject/template.go |
Template rendering helpers |
pkg/kube/inject/app_probe.go |
Probe rewriter |
pkg/kube/inject/watcher.go |
ConfigMap watcher |
pkg/kube/inject/initializer.go |
Init-container choice |
manifests/charts/istio-control/istio-discovery/files/injection-template.yaml |
The template itself |
manifests/charts/istio-control/istio-discovery/templates/mutatingwebhook.yaml |
The webhook config |
pkg/webhooks/validation/server/server.go |
The companion validating webhook |
pkg/webhooks/webhookpatch.go |
Webhook caBundle patcher |
See also
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.