Istio doesn’t just gather telemetry; it actively rewrites your application’s network traffic to inject it.

Let’s see it in action. Imagine a simple request from a frontend service to a backend service.

# Simulate a request to the frontend service
curl http://frontend.default.svc.cluster.local/api/users

# On the frontend pod, this is what Envoy sees (simplified)
# Envoy proxy for frontend receives the request.
# It adds Istio headers (like x-request-id) and forwards it to the backend.
# Before forwarding, it sends metrics and trace spans to the telemetry collector.
# It also logs the request.

# Envoy proxy for backend receives the request from frontend's Envoy.
# It adds its own spans and metrics, logs the request, and forwards to the actual backend application container.

# The backend application processes the request.
# Its logs (if instrumented) will appear.

# The response travels back through the same Envoy proxies, generating more telemetry.

The magic here is that your application code doesn’t need to know anything about Istio’s telemetry. The sidecar proxy (Envoy) intercepts all inbound and outbound traffic for your pods. It automatically generates metrics (request volume, latency, success rates), traces (the path and duration of a request across services), and logs (details of each request/response). This data is then forwarded to your chosen observability backend (Prometheus for metrics, Jaeger/Tempo for traces, Fluentd/Loki for logs).

The Problem Istio Solves: The Distributed Observability Gap

Before service meshes, getting a unified view of distributed systems was a nightmare. Each service had its own logging format, its own metric exporters, and often, no tracing at all. When a request failed, tracing it across multiple microservices involved manually correlating logs, hoping they used a common ID, and praying you had enough instrumentation. Istio’s sidecar proxy acts as a universal telemetry agent, abstracting away the complexities of individual service instrumentation. It provides a consistent, system-wide view of your services’ behavior.

How it Works Internally: The Sidecar’s Role

Every pod in your Istio service mesh gets an Envoy proxy as a sidecar container.

  1. Traffic Interception: Envoy is configured via Istio’s control plane (Pilot) to intercept all incoming and outgoing network traffic for the application container within the pod. This is typically done using iptables rules injected into the pod’s network namespace.
  2. Telemetry Generation:
    • Metrics: Envoy emits a rich set of metrics in Prometheus format (e.g., istio_requests_total, istio_request_duration_milliseconds). These include request counts, latencies, success/error rates, and more, tagged with dimensions like source service, destination service, HTTP method, and response code.
    • Tracing: For distributed tracing, Envoy can automatically generate and forward trace spans. It propagates trace context headers (like x-request-id, x-b3-traceid, x-b3-spanid) between services. When a request enters an Envoy proxy, it can start a new span or continue an existing trace. It then sends these spans to a configured tracing backend (like Jaeger or Tempo).
    • Access Logs: Envoy generates detailed access logs for every request it handles. These logs can be configured to include a wealth of information, such as source/destination IPs, ports, request duration, URL, HTTP method, response code, and bytes transferred. These logs are typically sent to a log aggregation system.
  3. Data Forwarding: Envoy is configured to send its generated metrics, trace spans, and access logs to specified telemetry backends. Istio itself doesn’t store this data; it relies on external systems like Prometheus, Jaeger, and Loki/Fluentd.

The Levers You Control

When configuring Istio’s telemetry, you’re primarily adjusting how Envoy behaves and where it sends data:

  • Enable/Disable Telemetry: You can selectively enable or disable metrics, tracing, and access logging for specific services or the entire mesh. This is often done via Istio’s MeshConfig or per-namespace annotations.
  • Tracing Sampling Rate: Distributed tracing can generate a massive amount of data. You can configure a sampling rate (e.g., 1% of requests) to reduce the overhead while still getting representative traces. This is typically set in the MeshConfig or on the ServiceEntry for external services.
  • Access Log Format: You can customize the fields included in Envoy’s access logs to capture exactly the information you need for debugging. This is done via MeshConfig.accessLogFile and MeshConfig.accessLogEncoding.
  • Telemetry Backend Configuration: You tell Istio (via MeshConfig or specific operator configurations) where to send the telemetry data – the addresses of your Prometheus, Jaeger, or logging agents.
  • Custom Metrics: While Envoy provides many built-in metrics, you can also configure Envoy HTTPFilters or use Istio’s Telemetry API to generate custom metrics based on request attributes or application-specific logic.

The One Thing Most People Don’t Realize

Istio’s tracing capabilities are so granular that if you enable tracing with a 100% sampling rate, you’ll get a trace span for every single network hop a request makes, including the internal routing decisions within the Envoy proxy itself. This means you can observe not just the time spent in your application code, but also the time spent in the sidecar proxy’s processing, network traversal between services, and even the iptables hops. This level of detail is invaluable for pinpointing performance bottlenecks that might not be solely within your application logic but in the underlying infrastructure or the proxy’s efficiency.

Once you have metrics, logs, and traces working, your next step will be to integrate Istio’s traffic management features to actively control and observe traffic flow.

Want structured learning?

Take the full Istio course →