Skip to main content
In this lesson we demonstrate how to use an Istio ServiceEntry to register an external workload with the mesh (by static IP) and then route mesh traffic to that external endpoint using a VirtualService. This pattern is useful when you must bring externally-resolved services into the mesh without changing an outbound registry-only policy. It matches a common scenario in the Prep Course - Istio Certified Associate (ICA) Certification.

What you’ll accomplish

  • Register an external host (myapp.com) and a static endpoint with a ServiceEntry.
  • Configure a VirtualService so the mesh routes HTTP traffic to that external endpoint.
  • Verify traffic is intercepted by the Istio sidecar and routed correctly.

Prerequisites / quick checks

  • Istio is already installed and running.
  • An external NGINX server is reachable at myapp.com. In this lab environment this hostname is mapped to a local IP via /etc/hosts.
Recommended verification commands:
Confirm the external web app is resolvable and responding from the control-plane host:
A successful response will look like the NGINX welcome page (truncated):
Verify the /etc/hosts mapping:
Example entry:

Why use a ServiceEntry?

A ServiceEntry tells Istio how to resolve and route traffic for hosts that are outside the mesh. Use MESH_EXTERNAL for workloads outside the cluster and resolution: STATIC when you want to bind a fixed IP endpoint to a hostname.
We use MESH_EXTERNAL because the workload is outside the mesh. Use resolution: STATIC for fixed IPs; use resolution: DNS for externally resolved hostnames.

1) Create a ServiceEntry

Create a file named se.yaml. Replace the address value with the IP you observed from /etc/hosts.
Apply and verify the ServiceEntry:
Expected output:

2) Run a test pod and try to curl

Start a simple test pod. The nginx image often includes curl; if not, use a curl-specific image (e.g., curlimages/curl).
Exec into the pod and attempt to curl the host:
You might see a redirect or unexpected HTML (e.g., 302 Found). This indicates the ServiceEntry is present but Istio is not yet performing HTTP routing for the host — a VirtualService is required.

3) Create a VirtualService

Create vs.yaml to capture HTTP traffic for myapp.com and forward it to the destination that matches the ServiceEntry.
Apply and check the VirtualService:
Expected output:

4) Re-test from the test pod

Try curling again from the test pod:
If the response is still incorrect, confirm whether the test pod has an Istio sidecar. Istio must intercept the pod’s traffic for the ServiceEntry + VirtualService routing to work. Check pod readiness and namespace labels:
Run istioctl analyze for hints:
Sample analyzer message when namespace injection is disabled:

5) Enable automatic sidecar injection and recreate the test pod

Label the namespace for injection so new pods receive the Envoy sidecar. Then recreate the test pod.
The test pod should now show 2/2 (application container + sidecar):

Final curl — success

From the injected test pod, curl the external host again:
You should now receive the expected NGINX default page served from the externally-registered endpoint. This confirms the mesh intercepted the traffic, the VirtualService matched and routed it to the ServiceEntry endpoint.

Summary / Key takeaways

  • ServiceEntry registers external hosts and endpoints with the mesh.
  • VirtualService captures and routes HTTP traffic for hosts — including external hosts defined by ServiceEntry.
  • Pods must have the Istio sidecar (injected) for the mesh to intercept and route their traffic.
  • Label namespaces for automatic injection before creating pods that need to be part of the mesh.

Quick reference table

Give this a try in the labs to get hands-on experience bringing external workloads into the mesh.

Watch Video

Practice Lab