Learn Istio - Sidecar Injection & Workload Onboarding
Episode 4 of 23

Learn Istio - Sidecar Injection & Workload Onboarding

Episode 4 brings your first workload into the mesh: automatic injection via namespace labels versus manual injection with istioctl kube-inject, the role of revision labels, limiting traffic scope with the Sidecar CRD, and onboarding VMs with WorkloadEntry and WorkloadGroup.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Istio is installed. The next question: how do we get workloads into the mesh? Episode 4 answers this — from sidecar injection, to controlling traffic scope per Pod, to bringing workloads outside Kubernetes (VMs) into the mesh as members.

This is a very hands-on episode. When you finish, you will be able to enable the mesh for an entire namespace with a single label, verify that the sidecar was truly injected, and understand when to use manual injection.

Automatic vs Manual Injection

Automatic Injection via Namespace Label

The most common approach is to label the namespace. When a new Pod is created, the sidecar injector webhook in istiod automatically adds the istio-proxy container to that Pod.

Enable automatic injection
kubectl label namespace default istio-injection=enabled
kubectl apply -f deploy-aplikasi.yaml
kubectl get pods

kubectl label namespace default istio-injection=enabled changes the namespace label. Note: this label only applies to Pods that are newly created — existing Pods stay unchanged until they are restarted. After deploying, verify that the Pod has two containers:

Check that the sidecar was injected
kubectl get pods -o jsonpath="{.items[*].spec.containers[*].name}"
kubectl get pods -l app=aplikasi -o jsonpath="{.items[0].spec.containers[*].name}"

The output should contain the application name followed by istio-proxy. If there is only one container, injection failed — usually because the namespace is not labeled or the webhook is not running.

Manual Injection with istioctl kube-inject

Sometimes automatic injection is not desired, for example when you want to verify the result explicitly or when you work in a pipeline that uses static manifests:

Manual injection
istioctl kube-inject -f deploy-aplikasi.yaml | kubectl apply -f -

istioctl kube-inject -f deploy-aplikasi.yaml adds the sidecar container directly into the manifest before it is applied. This gives you full control, but it also means the manifest in your repository no longer matches what is actually running — be careful when doing GitOps.

Revision Labels and Multi-Revision

To avoid the istio-injection=enabled label binding all workloads to the default istiod, use revision labels. This is essential to understand for upgrades and canaries:

Inject based on revision
kubectl label namespace default istio-injection- istio.io/rev=1-22-1 --overwrite

kubectl label namespace default istio.io/rev=1-22-1 makes new Pods use the sidecar from the 1-22-1 revision. The big advantage of revision labels: you can run two istiod versions at the same time and move workloads gradually — the pattern we use for canary installs in episode 3.

The Sidecar CRD for Limiting Scope

Without extra configuration, every sidecar captures all egress and ingress traffic of its Pod. When the number of services grows large, this wastes resources. The Sidecar CRD limits a workload's traffic scope:

Limit sidecar egress
apiVersion: networking.istio.io/v1
kind: Sidecar
metadata:
  name: default
  namespace: default
spec:
  egress:
  - hosts:
    - "./*"
    - "istio-system/*"

A Sidecar with hosts: ["./*"] limits egress to the same namespace plus istio-system. The effect: the service map in the sidecar shrinks drastically, xDS configuration decreases, and Envoy uses less memory — a topic we will dive into in episode 14.

WorkloadEntry and WorkloadGroup

WorkloadEntry for VMs

Virtual machines or non-Kubernetes workloads can also join the mesh through WorkloadEntry — a representation of an endpoint outside the cluster:

WorkloadEntry for a VM
apiVersion: networking.istio.io/v1
kind: WorkloadEntry
metadata:
  name: vm-produksi-1
  namespace: default
spec:
  address: 192.168.10.21
  labels:
    app: legacy-service
  serviceAccount: vm-legacy
  network: network-1

The serviceAccount field determines the workload identity, while network matters for the multi-network architecture we will cover in episode 16. This WorkloadEntry can then be a routing target for a VirtualService just like a normal Pod.

WorkloadGroup for Auto-registration

When you have many VM workloads, defining them one by one is tedious. WorkloadGroup lets VMs register themselves automatically:

WorkloadGroup
apiVersion: networking.istio.io/v1
kind: WorkloadGroup
metadata:
  name: vm-pool-prod
  namespace: default
spec:
  template:
    serviceAccount: vm-legacy
    network: network-1

The VM runs istioctl proxy and registers itself with the WorkloadGroup when it joins. This is the foundation of mesh expansion, which we will detail in episode 10.

Tip

For quick experiments, kubectl label namespace default istio-injection=enabled is enough. Use revision labels and the Sidecar CRD as your cluster grows and the cost of xDS configuration starts to be felt.

Summary

Episode 4 truly brought workloads into the mesh: automatic injection via namespace labels, manual injection with istioctl kube-inject, gradual migration with revision labels, configuration savings via the Sidecar CRD, and onboarding workloads outside Kubernetes through WorkloadEntry and WorkloadGroup.

Key takeaways:

  • The istio-injection=enabled label enables injection for new Pods.
  • istioctl kube-inject gives manual control but changes the manifest.
  • Existing Pods are not injected until they are restarted.
  • The istio.io/rev label separates workloads per istiod revision.
  • The Sidecar CRD limits traffic scope and trims xDS configuration.
  • WorkloadEntry represents a single VM; WorkloadGroup enables auto-registration.
  • Always verify by checking the istio-proxy container in the Pod.

In the next episode, episode 5, we will configure core traffic management with VirtualService and DestinationRule — routing based on host and subset, traffic splitting with weights, redirects and rewrites, connection pools, outlier detection, and ready-to-use A/B and traffic splitting examples.