Skip to main content

Sidecar Injection

The automatic process by which a service mesh adds a proxy container to every new pod created in a labeled namespace. Triggered by a Kubernetes mutating admission webhook - no changes to application manifests are required.

What is Sidecar Injection

Sidecar injection is how the service mesh gets its proxy container into every pod automatically. You do not add the sidecar to your Deployment YAML. You label the namespace, and Kubernetes does the rest.

TEXT
Developer creates a Deployment
|
v
Pod creation request sent to Kubernetes API server
|
v
Mutating Admission Webhook intercepts the request
(installed by the service mesh during setup)
|
v
Webhook adds the sidecar proxy container to the pod spec
|
v
Pod starts with two containers: app + sidecar

Enabling Injection

Injection is controlled at the namespace level with a label:

Bash
## Enable automatic sidecar injection for the production namespace
kubectl label namespace production istio-injection=enabled
## Verify the label is applied
kubectl get namespace production --show-labels

After labeling, every new pod created in that namespace automatically gets the sidecar. Existing pods are not affected - they must be restarted to get the sidecar injected.

Verifying Injection Worked

After deploying a pod to a labeled namespace, check the container count:

Bash
kubectl get pods -n production
## Correct output after injection:
## NAME READY STATUS RESTARTS
## orders-api-abc-xyz 2/2 Running 0
## 2/2 means: app container + sidecar both running
## 1/1 means: injection did not happen - check namespace label

Manual Injection

You can also inject the sidecar manually for specific pods without labeling the namespace:

Bash
## Inject sidecar into a specific deployment manifest
istioctl kube-inject -f deployment.yaml | kubectl apply -f -

Injection and mTLS

Sidecar injection is a prerequisite for mTLS. If a pod does not have a sidecar, it cannot participate in mTLS. This is why you must use PERMISSIVE mode during migration - pods without sidecars would fail all communication in STRICT mode.

◈ DIAGRAM
Namespace with label → pods get sidecars → mTLS capable
Namespace without label → pods have no sidecars → mTLS not possible
Remember

Labeling a namespace only affects NEW pods. If you label a namespace and existing pods are already running, those pods still have no sidecar. You must delete and recreate them (or roll the deployment) to trigger injection.

Common Mistake

Labeling kube-system, istio-system, or kube-public for sidecar injection. These namespaces contain core cluster components that will break if their traffic is intercepted by mesh proxies. Only label application namespaces.

Frequently Asked Questions

How does sidecar injection actually add a container without editing my deployment YAML?

It relies on a Kubernetes mutating admission webhook: when you label a namespace (e.g., `istio-injection=enabled`), the mesh's control plane registers a webhook that intercepts every pod creation request in that namespace and rewrites the pod spec on the fly, adding the proxy container before the pod is actually scheduled. You never touch your Deployment or application manifest — the mutation happens at the API server admission stage, invisible to `kubectl apply`.

What's a common gotcha with automatic sidecar injection?

Init containers or jobs that run and exit quickly can finish before the sidecar proxy is ready, or the pod can hang because the sidecar container never terminates on its own (a known Istio issue with Kubernetes Jobs prior to native sidecar support). Also, injecting a whole namespace means you can't selectively skip individual pods without an explicit `sidecar.istio.io/inject: false` annotation on each one — an easy thing to forget for debug or one-off pods.