REGISTRY_ONLY) and register an external workload so in-cluster pods can reach it. We’ll use a host-run nginx as the external workload and show how WorkloadEntry and ServiceEntry allow pods to access it when the mesh denies unregistered outbound destinations.
Prerequisites
- A Kubernetes cluster with kubectl access.
- curl and apt (for the control-plane host demo steps).
- istioctl (we’ll download it as part of the demo).
Verify Kubernetes is running
List all pods across namespaces to confirm your cluster is healthy:Download and install Istio (demo: v1.18.2)
Download Istio and makeistioctl available:
demo profile so we can modify mesh settings:
demo.yaml to set the mesh outbound traffic policy to REGISTRY_ONLY. Add or update the following under meshConfig:
Setting
outboundTrafficPolicy.mode to REGISTRY_ONLY blocks traffic to any destination not registered in the mesh registry. Apply this carefully in production; it can break external integrations unless those endpoints are explicitly added via ServiceEntry/WorkloadEntry.Simulate an external application (nginx on the host)
For this demo we simulate an external workload by running nginx on the control plane host. (In production, this would typically be a VM or cloud instance.) Install nginx on the host:10.50.0.1):
Create a test pod inside the cluster (with sidecar injection enabled)
Enable Istio sidecar injection for the namespace (we usedefault here):
REGISTRY_ONLY the sidecar blocks traffic to unregistered IPs and typically returns a 502:
Setting
meshConfig.outboundTrafficPolicy.mode to REGISTRY_ONLY requires that any external service you want pods to access must be registered with Istio (via ServiceEntry and/or WorkloadEntry). Otherwise the sidecar will reject the outbound traffic.Register the external workload with WorkloadEntry
Create a WorkloadEntry that represents the host-run nginx. Save the following asworkload-entry.yaml:
Create a ServiceEntry that maps a hostname to the WorkloadEntry
Createservice-entry.yaml to define a logical hostname and connect it to the WorkloadEntry via a selector:
hostsis the logical hostname clients will use, e.g.app.internal.com.resolution: STATICis required when the ServiceEntry is paired with WorkloadEntry(s).workloadSelector.labelspicks the WorkloadEntry(s) (or pods) with matching labels.
Test access from the test pod via the registered hostname
From inside thetest pod, curl the logical hostname:
app.internal.com via the ServiceEntry/WorkloadEntry registration.
Add an in-cluster pod to the same workload (WorkloadEntry label)
To show that aWorkloadEntry can represent multiple endpoints, create an in-cluster pod with the same label as the WorkloadEntry:
app.internal.com from the test pod may be served by either the external host (WorkloadEntry IP) or the in-cluster nginx pod, since they share the label and are part of the same logical service:
Quick reference: WorkloadEntry vs ServiceEntry
Practical notes and reference
- WorkloadEntry lets Istio manage non-Kubernetes endpoints. Use it for VMs, bare metal, and external IPs.
- ServiceEntry maps DNS names into the mesh and describes ports/protocols and resolution. Use
workloadSelectorto attach WorkloadEntry(s). - Common WorkloadEntry fields:
address(IP or DNS),serviceAccount(if mTLS is required),network,labels, andports. - If
locationis not set in a ServiceEntry, the default isMESH_EXTERNAL. Uselocation: MESH_INTERNALwhen the service should be considered internal to the mesh. - When using
REGISTRY_ONLY, ensure every external dependency is added to the registry; otherwise application traffic will be blocked.
- Istio: WorkloadEntry reference: https://istio.io/latest/docs/reference/config/networking/workload-entry/
- Istio: ServiceEntry reference: https://istio.io/latest/docs/reference/config/networking/service-entry/
- Istio Traffic Management: https://istio.io/latest/docs/concepts/traffic-management/
REGISTRY_ONLY.