How to call the services within a mesh in ISTIO?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
In Istio, you generally call an in-mesh service the same way you would call a normal Kubernetes service: by its service DNS name and port. The mesh does not require a special API for ordinary service-to-service calls; Istio's sidecars intercept that traffic and apply routing, mTLS, telemetry, and policy automatically.
Start with normal Kubernetes service names
Suppose you have a service named reviews in the default namespace listening on port 9080. From another pod in the same namespace, a normal HTTP call is enough:
From a different namespace, use the namespace-qualified service name:
And the fully qualified service name also works:
This is the most important point: you do not call the Envoy sidecar directly. You call the Kubernetes service, and the sidecar captures outbound traffic on the way out.
What Istio adds to that call
When both workloads are in the mesh with sidecars injected, the call path looks like this:
- Your application sends a normal HTTP, gRPC, or TCP request.
- The source sidecar intercepts the outbound traffic.
- Istio routing, retries, timeouts, and mTLS rules are applied.
- The destination sidecar receives the request and forwards it to the service container.
That means the application code remains simple. Service discovery still uses Kubernetes DNS, while Istio layers traffic management and security on top.
Test from inside the mesh
A very practical way to verify connectivity is to exec into a pod that has an injected sidecar and call the target service:
If DNS, service selectors, and mesh config are correct, that call should succeed without any service-mesh-specific code in the application.
If you need to call by host header or match routing rules that depend on HTTP hosts, make sure the host matches the service name expected by your VirtualService.
Use VirtualService and DestinationRule only for routing behavior
Calling the service and controlling how traffic is routed are separate concerns. The call target stays the same, but Istio resources can steer it to subsets, versions, or canary paths.
Example:
The application still calls http://reviews:9080/.... Istio decides whether the request lands on v1 or v2.
Calling across namespaces and external services
Within the same cluster, cross-namespace calls use the normal Kubernetes DNS form. If the service lives outside the mesh or outside the cluster, that is a different problem. For external services, Istio may need a ServiceEntry depending on your outbound traffic policy.
For in-mesh traffic, though, service calling is intentionally boring. If you find yourself inventing a special istio:// address pattern, you are probably overcomplicating it.
Common Pitfalls
The biggest mistake is trying to call the sidecar proxy directly instead of the Kubernetes service. Applications should target service DNS names and let Istio intercept the traffic.
Another common issue is using the short service name across namespaces. reviews works only within the same namespace. Across namespaces, use reviews.default or the full cluster DNS name.
Developers also confuse routing configuration with service discovery. VirtualService does not change how the app finds the service; it changes what Istio does with traffic after the app sends it.
Finally, if calls fail unexpectedly, check the basics first: sidecar injection, service selectors, ports, DNS resolution, and authorization policies. Not every failure is an Istio routing problem.
Summary
- Call in-mesh services by normal Kubernetes service DNS name and port.
- You do not call the Envoy sidecar directly from application code.
- Istio transparently intercepts the traffic and applies routing, security, and observability.
- Use
VirtualServiceandDestinationRuleto control versions and traffic policy, not to invent a new calling convention. - For cross-namespace traffic, use namespace-qualified or fully qualified service names.
Related reading
- How to change --horizontal-pod-autoscaler-sync-period field in kube-controller-manager to 5sec in gke
- How to change a running pod name?
- How to change control-plane-endpoint option in a live cluster?
- How to change default K8s cluster registry?
- How to check the actual number of incremental fetch session cache slots used in Kafka cluster?
- How to choose Kafka transactional.id in a Kubernetes (Producer side only transaction) set up
- How to change the default port of microk8s?
- How to check if Kubernetes cluster is running fine

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.