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.

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.
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.
kubectl label namespace default istio-injection=enabled
kubectl apply -f deploy-aplikasi.yaml
kubectl get podskubectl 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:
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.
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:
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.
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:
kubectl label namespace default istio-injection- istio.io/rev=1-22-1 --overwritekubectl 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.
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:
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.
Virtual machines or non-Kubernetes workloads can also join the mesh through WorkloadEntry — a representation of an endpoint outside the cluster:
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-1The 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.
When you have many VM workloads, defining them one by one is tedious. WorkloadGroup lets VMs register themselves automatically:
apiVersion: networking.istio.io/v1
kind: WorkloadGroup
metadata:
name: vm-pool-prod
namespace: default
spec:
template:
serviceAccount: vm-legacy
network: network-1The 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.
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:
istio-injection=enabled label enables injection for new Pods.istioctl kube-inject gives manual control but changes the manifest.istio.io/rev label separates workloads per istiod revision.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.