TT Lab
Get started
Learn Learning paths Courses

Istio Service Mesh

How to make a server outside Kubernetes a mesh member

Continue in TT Lab

In one line

Mesh expansion is giving identity to servers outside Kubernetes and putting them on the mesh's service map, and it is expressed with three objects: WorkloadGroup (the template for a group), WorkloadEntry (one server), and ServiceEntry (the name to call).

Why this problem remains

What remains to the very end in an organization that has adopted a mesh is the servers that could not be moved. A payment system that would have to be recertified, software whose license is tied to hardware, an old service that nobody knows how to build. If you leave them outside the mesh, on the surface there is no problem at all — calls work and the screens look fine. The problem is that from there the things the mesh gives are cut off. That segment has no mTLS, no authorization based on caller identity applies, and it does not appear in the mesh's service map or metrics either. When an incident happens, it becomes "from here on, we cannot see."

This is different from registering outgoing calls (writing an external API in a ServiceEntry). The former guides a guest to the door, and the latter puts that server on the member roster.

What the three objects split between them

Object Kubernetes counterpart What you write
WorkloadGroup A Deployment's Pod template The labels, service account, network, ports, and health check common to the group
WorkloadEntry One Pod That server's address, network, identity, locality, and ports
ServiceEntry Service The host name to call inside the mesh, and the selector that chooses the workloads that stand behind it

The one most often left out here is the ServiceEntry. If you create only a WorkloadEntry, it is registered but there is no name to call it by. The workloadSelector of a ServiceEntry selects WorkloadEntries by label and places them behind that name. At this point what the selector looks at is the WorkloadEntry's metadata.labels — if you write labels inside spec, nothing is selected.

location matters a lot too. With MESH_INTERNAL it is treated as a mesh member and becomes a target of mTLS and policies, and with MESH_EXTERNAL it is treated as an outside service. Even for the same ServiceEntry, this one value splits the security model.

resolution decides how to find the destination, and each value has different endpoint rules, and the CRD schema enforces those rules. NONE uses the original destination address as it is, so writing an endpoint is rejected. DNS_ROUND_ROBIN is a way of resolving one name once and reusing the result, so there must be 0 or 1 endpoints. STATIC uses the endpoints you wrote or the WorkloadEntries the selector picks up.

How identity reaches that server

Inside Kubernetes, the kubelet puts a token into the Pod and the proxy proves itself with it. A VM has no kubelet, so a person must put it in. The server needs three things.

istioctl x workload entry configure gathers these three into one directory. If you open the resulting cluster.env, you can see that values such as SERVICE_ACCOUNT, ISTIO_META_NETWORK, and ISTIO_INBOUND_PORTS come down from the WorkloadGroup as they are. That is, the WorkloadGroup is not a declaration but the source of the real boot configuration.

The network value also gains meaning here. The mesh judges that workloads with the same network name communicate directly, and if they differ they must go through a gateway. If the value is wrong, it is not that the connection fails but that it goes by an unexpected path.

What it looks like in the field

The most common report is "I registered it but it does not show up anywhere." Most of the causes are label mismatches. If a WorkloadEntry's label and a ServiceEntry's selector differ by one character, there is no error and simply nothing is selected. That is why many teams attach to the registration procedure a script that counts how many the selector actually selects.

The second is an address typo. The address of a WorkloadEntry can be an IP or an FQDN, so the CRD schema does not enforce the format. So even a value with spaces in it is created as is. What catches such things is not the API server but istioctl analyze — schema checking and configuration analysis are different nets, and you need both to close the holes.

Limits of this lab environment

In the lab Pod you cannot actually bring up a VM. So you cannot see the scene of putting the generated configuration bundle onto a server, starting the proxy, and joining the mesh, and you cannot confirm auto-registration (the VM creating its own WorkloadEntry) either. Instead, the schema enforcement of the three objects, what the selector actually selects, and how the configuration bundle is made from a WorkloadGroup can all be confirmed against a real API server.

What you will do in the next lab

You first write the identity string the server will receive, and create a WorkloadGroup, a WorkloadEntry, and a ServiceEntry in turn. You take directly the values the schema rejects (writing both probes, leaving out the template, and the endpoint rules per resolution), and at the end you actually create the configuration bundle the VM would receive and leave a report that counts how many servers the selector selects.