Microservices often use TCP for inter-service communication, but the "mesh" versus "direct" debate is a classic.
Let’s see a service mesh in action. Imagine two services, frontend and backend. Without a mesh, frontend directly connects to backend’s IP and port.
With a service mesh like Istio, we inject a "sidecar" proxy (Envoy) into each service’s pod. The frontend service now thinks it’s talking to backend on its normal port, but the traffic is intercepted by the frontend sidecar. This sidecar then establishes a new TCP connection to the backend sidecar. The backend sidecar receives this connection and forwards the request to the actual backend application.
# Example Istio VirtualService configuration
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: backend
spec:
hosts:
- backend.default.svc.cluster.local # The "virtual" host the frontend sees
http:
- route:
- destination:
host: backend.default.svc.cluster.local # The actual service name
weight: 100
This indirection, while seemingly adding overhead, unlocks powerful capabilities. The primary problem it solves is abstracting away the complexities of network communication from the application developer. Instead of worrying about retries, load balancing, TLS encryption, or circuit breaking within the frontend code, these concerns are handled by the sidecar proxies.
Internally, the mesh intercepts all inbound and outbound traffic for a given pod. When frontend sends a request, the frontend Envoy proxy intercepts it. It consults its configuration (often managed by Istio’s control plane) to determine where to send the request. This might involve a load balancer that selects an available backend instance, automatically retries failed connections, or applies circuit breakers to prevent cascading failures. The traffic is then routed to the backend Envoy proxy, which forwards it to the backend application.
The exact levers you control are primarily through the control plane’s configuration. For Istio, this means defining VirtualService resources to route traffic, DestinationRule resources to configure load balancing and connection pooling, and Gateway resources to manage ingress and egress traffic. You can define sophisticated routing rules based on headers, weights for A/B testing, and fault injection for chaos engineering.
The most surprising true thing about service meshes is how much of the networking logic they move out of the application and into the infrastructure, often without requiring any code changes in your microservices. This allows developers to focus purely on business logic, while network engineers can manage policies and observability across the entire distributed system.
The next concept you’ll run into is how the service mesh handles observability, specifically distributed tracing and metrics, by leveraging the intercepted traffic.