The Same Identity for a Machine That Is Not a Container
In one line
A machine outside Kubernetes also enters the mesh if you install a sidecar on it. A WorkloadGroup is the template for such machines (labels, service account, ports), a WorkloadEntry is one machine (an address), and because a Kubernetes Service's selector also picks WorkloadEntries, you can put a VM behind an existing service name. The machine's sidecar receives certificates and configuration from istiod in the same way as a Pod.
Why this was needed
Not everything moves over to containers. An old payment system, the front end of a database tied to a license, a server with special hardware attached remain. If those machines are outside the mesh, two things collapse — when an in-mesh service calls that machine, mTLS and authorization are cut, and when that machine calls into the mesh, it has no identity and is blocked by a STRICT policy. In the end exception rules (PERMISSIVE, wide allows) appear, and the exceptions become holes in security.
VM enrollment is a way of putting that machine into the same identity system by installing the same sidecar on it.
How it works
1. The template — WorkloadGroup. Like a Pod template, you write 'this kind of machine has these labels, this service account, and these ports'. istioctl x workload entry configure reads this and makes five files to hand to the machine.
| File | Place on the machine | Use |
|---|---|---|
| cluster.env | /var/lib/istio/envoy/ | Namespace, service account, labels, and ports to intercept |
| istio-token | /var/run/secrets/tokens/ | The service account token to present when first receiving a certificate |
| mesh.yaml | /etc/istio/config/mesh | Mesh configuration (the istiod address and so on) |
| root-cert.pem | /etc/certs/ | The root to trust |
| hosts | Appended to /etc/hosts | The address to find the istiod name |
2. The sidecar — the istio-sidecar package. The official deb installs pilot-agent, envoy, and istio-start.sh. istio-start.sh plants iptables rules that redirect incoming and outgoing traffic to the sidecar and starts pilot-agent as the istio-proxy user. pilot-agent requests a certificate from istiod with the token, and from then on it receives xDS exactly like a Pod's sidecar.
3. One machine — WorkloadEntry. You write the address, labels, and service account. If the labels match the service selector, istiod pushes this address down to every sidecar as that service's endpoint. If auto-registration is turned on in istiod, a WorkloadEntry is created by itself when the sidecar attaches, but this feature has to be turned on at install time.
The way to istiod. In an installation that spans several networks, the machine reaches istiod through the east-west gateway. If it is a network where the machine can reach cluster Service addresses directly, you can give istiod's address directly.
This lab's 'machine outside the mesh'
There is only one VM per session and the VMs cannot communicate with each other. So we used a network namespace inside the same VM as the second machine. A network namespace is a kernel isolation unit that has its own addresses, routing table, and iptables entirely separately, so the sidecar's interception rules go only inside it. When you actually measure it, the rules go into the iptables-legacy side inside the namespace, and not a single ISTIO rule is created on the host (the side with k3s's kube-proxy rules) — the two do not collide. The only difference from a real VM is that it shares the filesystem with the host.
What it looks like in the field
"The VM's sidecar starts but does not attach to istiod." Usually it is name resolution. The hosts line is missing, or DNS does not know the cluster name. A connection error is left in /var/log/istio/istio.log.
"An hour later a new VM cannot attach." istio-token is a one-hour token by default. After the first certificate is received, it renews with the certificate, but if the token expires before it first attaches, you have to make a new one.
"I put the VM behind a service but the connection sometimes drops." The endpoint remains as long as the WorkloadEntry exists. It is not removed even if the machine dies, so you also keep auto-registration that uses the WorkloadGroup's probe or outlier detection.
Official docs: Virtual Machine Installation · Virtual Machine Architecture · WorkloadEntry · WorkloadGroup
What you will do in the next lab
You first call the 'machine outside the mesh' running in a network namespace inside the same VM from the outside, create a WorkloadGroup and a Service, and pull out the files to hand to the machine. You put the files in place, bring up the sidecar inside the namespace and attach it to istiod, count that the iptables rules do not collide with the host, and put it behind the service with a WorkloadEntry. You confirm from the logs that mTLS is established in both directions, and then apply STRICT and an authorization policy as well.