Istio’s ServiceEntry resource allows you to configure Istio to manage traffic to services outside of your Kubernetes cluster.
Let’s see it in action. Imagine you have a Kubernetes cluster running an application that needs to call an external REST API, say, a weather service at api.weather.com on port 443.
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: external-weather-api
spec:
hosts:
- api.weather.com
ports:
- number: 443
name: https
protocol: HTTPS
resolution: DNS
location: MESH_EXTERNAL
When Istio sees this ServiceEntry, it tells its sidecar proxies (Envoy) that api.weather.com is a valid destination. Now, if your application’s pod tries to make an HTTPS request to api.weather.com, the Envoy sidecar intercepts it. It knows to route this traffic outside the mesh, to the actual api.weather.com endpoint, rather than trying to resolve it as a service within Kubernetes. This is crucial because without it, Istio wouldn’t know how to handle traffic destined for non-Kubernetes services.
The core problem ServiceEntry solves is making external services discoverable and manageable by the Istio mesh. Normally, Istio only knows about services defined as Kubernetes Services. By defining a ServiceEntry, you’re essentially creating a placeholder within Istio’s internal service registry for an external endpoint. This allows you to apply Istio’s traffic management policies, such as routing rules, timeouts, and circuit breakers, to these external services, just as you would for services running within your cluster.
Internally, when an Envoy proxy receives a request destined for a host listed in a ServiceEntry, it consults its configuration. If the host matches, and the resolution is set to DNS, Envoy will perform a DNS lookup for that host. For MESH_EXTERNAL services, Envoy will then forward the traffic to the resolved IP address of the external service. The location: MESH_EXTERNAL field explicitly tells Istio that this service resides outside the mesh.
The resolution field is key here. DNS is the most common for external services, meaning Envoy will perform a DNS lookup at runtime. STATIC would mean you’re providing explicit IP addresses in the addresses field of the ServiceEntry, which is less common for dynamic external services.
You have precise control over how Istio treats these external services. For instance, you can specify the protocol (HTTP, HTTPS, TCP, GRPC, etc.) and the port number. This ensures that Envoy correctly establishes connections and applies appropriate security policies. You can even define multiple ports for a single ServiceEntry, allowing a single external host to serve different protocols on different ports.
Consider a scenario where api.weather.com has multiple IP addresses for load balancing. Istio, by using resolution: DNS, will leverage the standard DNS resolution mechanism to discover these IPs. If you wanted more granular control or to simulate an external service for testing, you could use resolution: STATIC and provide specific IPs in the addresses field, but this is generally for specific use cases and less common for real-world external dependencies.
By default, if you don’t specify location, Istio assumes MESH_INTERNAL. If you’re trying to route traffic to an external service and haven’t set location: MESH_EXTERNAL, Istio might incorrectly try to resolve it as an internal Kubernetes service, leading to connectivity issues or unexpected behavior.
The most surprising thing about ServiceEntry is that it doesn’t actually create any network endpoints; it merely informs the Istio control plane and its sidecar proxies about the existence and characteristics of an external service, enabling Istio’s traffic management capabilities to be extended beyond the cluster boundaries.
The next step after integrating external services is often to implement sophisticated traffic routing and resilience patterns for them, such as defining specific routing rules based on request headers or implementing circuit breakers for MESH_EXTERNAL services.