Installing the Sidecar

Injection

In order to take advantage of all of Istio’s features, pods in the mesh must be running an Istio sidecar proxy.

The following sections describe two ways of injecting the Istio sidecar into a pod: manually using the istioctl command or by enabling automatic Istio sidecar injection in the pod’s namespace.

Manual injection directly modifies configuration, like deployments, and injects the proxy configuration into it.

When enabled in a pod’s namespace, automatic injection injects the proxy configuration at pod creation time using an admission controller.

Injection occurs by applying a template defined in the istio-sidecar-injector ConfigMap.

Manual sidecar injection

To manually inject a deployment, use istioctl kube-inject:

Zip

  1. $ istioctl kube-inject -f @samples/sleep/sleep.yaml@ | kubectl apply -f -
  2. serviceaccount/sleep created
  3. service/sleep created
  4. deployment.apps/sleep created

By default, this will use the in-cluster configuration. Alternatively, injection can be done using local copies of the configuration.

  1. $ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.config}' > inject-config.yaml
  2. $ kubectl -n istio-system get configmap istio-sidecar-injector -o=jsonpath='{.data.values}' > inject-values.yaml
  3. $ kubectl -n istio-system get configmap istio -o=jsonpath='{.data.mesh}' > mesh-config.yaml

Run kube-inject over the input file and deploy.

Zip

  1. $ istioctl kube-inject \
  2. --injectConfigFile inject-config.yaml \
  3. --meshConfigFile mesh-config.yaml \
  4. --valuesFile inject-values.yaml \
  5. --filename @samples/sleep/sleep.yaml@ \
  6. | kubectl apply -f -
  7. serviceaccount/sleep created
  8. service/sleep created
  9. deployment.apps/sleep created

Verify that the sidecar has been injected into the sleep pod with 2/2 under the READY column.

  1. $ kubectl get pod -l app=sleep
  2. NAME READY STATUS RESTARTS AGE
  3. sleep-64c6f57bc8-f5n4x 2/2 Running 0 24s

Automatic sidecar injection

Sidecars can be automatically added to applicable Kubernetes pods using a mutating webhook admission controller provided by Istio.

While admission controllers are enabled by default, some Kubernetes distributions may disable them. If this is the case, follow the instructions to turn on admission controllers.

When you set the istio-injection=enabled label on a namespace and the injection webhook is enabled, any new pods that are created in that namespace will automatically have a sidecar added to them.

Note that unlike manual injection, automatic injection occurs at the pod-level. You won’t see any change to the deployment itself. Instead you’ll want to check individual pods (via kubectl describe) to see the injected proxy.

Deploying an app

Deploy sleep app. Verify both deployment and pod have a single container.

Zip

  1. $ kubectl apply -f @samples/sleep/sleep.yaml@
  2. $ kubectl get deployment -o wide
  3. NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
  4. sleep 1/1 1 1 12s sleep curlimages/curl app=sleep
  1. $ kubectl get pod
  2. NAME READY STATUS RESTARTS AGE
  3. sleep-8f795f47d-hdcgs 1/1 Running 0 42s

Label the default namespace with istio-injection=enabled

  1. $ kubectl label namespace default istio-injection=enabled --overwrite
  2. $ kubectl get namespace -L istio-injection
  3. NAME STATUS AGE ISTIO-INJECTION
  4. default Active 5m9s enabled
  5. istio-system Active 4m58s disabled
  6. kube-node-lease Active 5m10s
  7. kube-public Active 5m10s
  8. kube-system Active 5m10s
  9. local-path-storage Active 5m7s

Injection occurs at pod creation time. Kill the running pod and verify a new pod is created with the injected sidecar. The original pod has 1/1 READY containers and the pod with injected sidecar has 2/2 READY containers.

  1. $ kubectl delete pod -l app=sleep
  2. $ kubectl get pod -l app=sleep
  3. pod "sleep-776b7bcdcd-7hpnk" deleted
  4. NAME READY STATUS RESTARTS AGE
  5. sleep-776b7bcdcd-7hpnk 1/1 Terminating 0 1m
  6. sleep-776b7bcdcd-bhn9m 2/2 Running 0 7s

View detailed state of the injected pod. You should see the injected istio-proxy container and corresponding volumes. Be sure to substitute the correct name for the Running pod below.

  1. $ kubectl describe pod -l app=sleep
  2. ...
  3. Events:
  4. Type Reason Age From Message
  5. ---- ------ ---- ---- -------
  6. ...
  7. Normal Created 11s kubelet Created container istio-init
  8. Normal Started 11s kubelet Started container istio-init
  9. ...
  10. Normal Created 10s kubelet Created container sleep
  11. Normal Started 10s kubelet Started container sleep
  12. ...
  13. Normal Created 9s kubelet Created container istio-proxy
  14. Normal Started 8s kubelet Started container istio-proxy

Disable injection for the default namespace and verify new pods are created without the sidecar.

  1. $ kubectl label namespace default istio-injection-
  2. $ kubectl delete pod -l app=sleep
  3. $ kubectl get pod
  4. namespace/default labeled
  5. pod "sleep-776b7bcdcd-bhn9m" deleted
  6. NAME READY STATUS RESTARTS AGE
  7. sleep-776b7bcdcd-bhn9m 2/2 Terminating 0 2m
  8. sleep-776b7bcdcd-gmvnr 1/1 Running 0 2s

Understanding what happened

When Kubernetes invokes the webhook, the admissionregistration.k8s.io/v1beta1#MutatingWebhookConfiguration configuration is applied. The default configuration injects the sidecar into pods in any namespace with the istio-injection=enabled label. The istio-sidecar-injector configuration map specifies the configuration for the injected sidecar. To change how namespaces are selected for injection, you can edit the MutatingWebhookConfiguration with the following command:

  1. $ kubectl edit mutatingwebhookconfiguration istio-sidecar-injector

You should restart the sidecar injector pod(s) after modifying the MutatingWebhookConfiguration.

For example, you can modify the MutatingWebhookConfiguration to always inject the sidecar into every namespace, unless a label is set. Editing this configuration is an advanced operation. Refer to the Kubernetes documentation for the MutatingWebhookConfiguration API for more information.

policy

disabled - The sidecar injector will not inject the sidecar into pods by default. Add the sidecar.istio.io/inject annotation with value true to the pod template spec to override the default and enable injection.

enabled - The sidecar injector will inject the sidecar into pods by default. Add the sidecar.istio.io/inject annotation with value false to the pod template spec to override the default and disable injection.

The following example uses the sidecar.istio.io/inject annotation to disable sidecar injection.

  1. $ kubectl apply -f - <<EOF
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: ignored
  6. labels:
  7. app: ignored
  8. spec:
  9. selector:
  10. matchLabels:
  11. app: ignored
  12. template:
  13. metadata:
  14. labels:
  15. app: ignored
  16. annotations:
  17. sidecar.istio.io/inject: "false"
  18. spec:
  19. containers:
  20. - name: ignored
  21. image: governmentpaas/curl-ssl
  22. command: ["/bin/sleep","infinity"]
  23. EOF

It can then be verified that no sidecar was injected.

  1. $ kubectl get pods -l app=ignored
  2. NAME READY STATUS RESTARTS AGE
  3. ignored-b469d6fcf-8dngz 1/1 Running 0 57s
template

The sidecar injection template uses https://golang.org/pkg/text/template which, when parsed and executed, is decoded to the following struct containing the list of containers and volumes to inject into the pod.

  1. type SidecarInjectionSpec struct {
  2. RewriteAppHTTPProbe bool `yaml:"rewriteAppHTTPProbe"`
  3. InitContainers []corev1.Container `yaml:"initContainers"`
  4. Containers []corev1.Container `yaml:"containers"`
  5. Volumes []corev1.Volume `yaml:"volumes"`
  6. DNSConfig *corev1.PodDNSConfig `yaml:"dnsConfig"`
  7. ImagePullSecrets []corev1.LocalObjectReference `yaml:"imagePullSecrets"`
  8. }

The template is applied to the following data structure at runtime.

  1. type SidecarTemplateData struct {
  2. DeploymentMeta *metav1.ObjectMeta
  3. ObjectMeta *metav1.ObjectMeta
  4. Spec *corev1.PodSpec
  5. ProxyConfig *meshconfig.ProxyConfig // Defined by https://istio.io/docs/reference/config/service-mesh.html#proxyconfig
  6. MeshConfig *meshconfig.MeshConfig // Defined by https://istio.io/docs/reference/config/service-mesh.html#meshconfig
  7. }

ObjectMeta and Spec are from the pod. ProxyConfig and MeshConfig are from the istio ConfigMap in the istio-system namespace. Templates can conditionally define injected containers and volumes with this data.

For example, the following template

  1. containers:
  2. - name: istio-proxy
  3. image: istio.io/proxy:0.5.0
  4. args:
  5. - proxy
  6. - sidecar
  7. - --configPath
  8. - {{ .ProxyConfig.ConfigPath }}
  9. - --binaryPath
  10. - {{ .ProxyConfig.BinaryPath }}
  11. - --serviceCluster
  12. {{ if ne "" (index .ObjectMeta.Labels "app") -}}
  13. - {{ index .ObjectMeta.Labels "app" }}
  14. {{ else -}}
  15. - "istio-proxy"
  16. {{ end -}}

expands to

  1. containers:
  2. - name: istio-proxy
  3. image: istio.io/proxy:0.5.0
  4. args:
  5. - proxy
  6. - sidecar
  7. - --configPath
  8. - /etc/istio/proxy
  9. - --binaryPath
  10. - /usr/local/bin/envoy
  11. - --serviceCluster
  12. - sleep

when applied over a pod defined by the pod template spec in samples/sleep/sleep.yaml

More control: adding exceptions

There are cases where users do not have control of the pod creation, for instance, when they are created by someone else. Therefore they are unable to add the annotation sidecar.istio.io/inject in the pod, to explicitly instruct Istio whether to install the sidecar or not.

Think of auxiliary pods that might be created as an intermediate step while deploying an application. OpenShift Source to Image Builds, for example, creates such pods for building the source code of an application. Once the binary artifact is built, the application pod is ready to run and the auxiliary pods are discarded. Those intermediate pods should not get an Istio sidecar, even if the policy is set to enabled and the namespace is properly labeled to get automatic injection.

For such cases you can instruct Istio to not inject the sidecar on those pods, based on labels that are present in those pods. You can do this by editing the istio-sidecar-injector ConfigMap and adding the entry neverInjectSelector. It is an array of Kubernetes label selectors. They are OR'd, stopping at the first match. See an example:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: istio-sidecar-injector
  5. data:
  6. config: |-
  7. policy: enabled
  8. neverInjectSelector:
  9. - matchExpressions:
  10. - {key: openshift.io/build.name, operator: Exists}
  11. - matchExpressions:
  12. - {key: openshift.io/deployer-pod-for.name, operator: Exists}
  13. template: |-
  14. initContainers:
  15. ...

The above statement means: Never inject on pods that have the label openshift.io/build.name or openshift.io/deployer-pod-for.name – the values of the labels don’t matter, we are just checking if the keys exist. With this rule added, the OpenShift Builds use case illustrated above is covered, meaning auxiliary pods will not have sidecars injected (because source-to-image auxiliary pods do contain those labels).

For completeness, you can also use a field called alwaysInjectSelector, with similar syntax, which will always inject the sidecar on pods that match that label selector, regardless of the global policy.

The label selector approach gives a lot of flexibility on how to express those exceptions. Take a look at these docs to see what you can do with them!

It’s worth noting that annotations in the pods have higher precedence than the label selectors. If a pod is annotated with sidecar.istio.io/inject: "true/false" then it will be honored. So, the order of evaluation is:

Pod Annotations → NeverInjectSelector → AlwaysInjectSelector → Default Policy

Uninstalling the automatic sidecar injector

  1. $ kubectl delete mutatingwebhookconfiguration istio-sidecar-injector
  2. mutatingwebhookconfiguration.admissionregistration.k8s.io "istio-sidecar-injector" deleted

The above command will not remove the injected sidecars from Pods. A rolling update or simply deleting the pods and forcing the deployment to create them is required.

Optionally, it may also be desirable to clean-up other resources that were modified in this task.

  1. $ kubectl label namespace default istio-injection-
  2. namespace/default labeled

See also

Application Requirements

Requirements of applications deployed in an Istio-enabled cluster.

Demystifying Istio’s Sidecar Injection Model

De-mystify how Istio manages to plugin its data-plane components into an existing deployment.

Install Istio with the Istio CNI plugin

Install and use Istio with the Istio CNI plugin, allowing operators to deploy services with lower privilege.

Expanding into New Frontiers - Smart DNS Proxying in Istio

Workload Local DNS resolution to simplify VM integration, multicluster, and more.

Using MOSN with Istio: an alternative data plane

An alternative sidecar proxy for Istio.

Provision a certificate and key for an application without sidecars

A mechanism to acquire and share an application certificate and key through mounted files.