Skip to main content
Metrics tell you something is slow.
Logs show what happened inside a single service.
But when a request flows through multiple microservices and suddenly takes several seconds, how do you find the service responsible for the delay? Distributed tracing answers that question.
OpenTelemetry (OTel) provides a vendor-neutral way to instrument applications and emit traces and metrics. Jaeger is a popular tracing backend that collects, stores, indexes, and visualizes those traces. In short: OpenTelemetry generates and exports traces; Jaeger collects and displays them. This guide shows how to enable OpenTelemetry in a Kubernetes deployment so traces from your application appear in Jaeger.

What is running in the cluster

Start by confirming the observability components and your application workloads are running:
Example output:
In this example:
  • Jaeger runs in the observability namespace.
  • Four microservices (frontend, order, inventory, payment) run in the workloads namespace.
  • A traffic generator is exercising the services to generate traces.
If you open the Jaeger UI and a running service (for example, frontend-svc) does not appear in the service list, that usually means the application is not configured to emit traces — the OpenTelemetry environment variables are missing or incorrect.

How to configure the frontend deployment to export traces

To export traces from the frontend to Jaeger via OTLP, add the appropriate OpenTelemetry environment variables to the frontend deployment. These variables tell the application’s OTel SDK what the service name is, which protocol and endpoint to use, and which exporter to enable. Use this table to guide the required variables: Important: protocol and port must match the Jaeger collector. gRPC uses port 4317; HTTP/Protobuf uses port 4318. If you choose HTTP/Protobuf, some SDKs require an explicit scheme in the endpoint (for example http://jaeger-collector.observability.svc.cluster.local:4318). Below is the patch fragment you can apply to the frontend deployment (save as frontend-patch.yaml):
Apply the patch and monitor the rollout:
Confirm the Jaeger collector service and the ports it exposes:
Example output showing the relevant ports:
Always ensure the OTEL_EXPORTER_OTLP_PROTOCOL value matches the collector port you set in OTEL_EXPORTER_OTLP_ENDPOINT: use grpc for port 4317 or http/protobuf for port 4318. A mismatch will prevent traces from being delivered.
If your language’s OpenTelemetry SDK exposes protocol-specific variables (for example OTEL_EXPORTER_OTLP_TRACES_PROTOCOL), prefer those over the generic OTEL_EXPORTER_OTLP_PROTOCOL. Check your SDK docs — using the wrong variable is a common cause of silent failures.

Verify traces in Jaeger

After the deployment restarts with the new environment variables:
  1. Open the Jaeger UI (query service typically at the jaeger-query service; many setups provide a UI route or NodePort).
  2. Refresh the service dropdown — frontend-svc should now appear.
  3. Search for recent traces for frontend-svc. Open a trace to inspect the waterfall.
A trace waterfall shows each service as a span (horizontal bar); the bar width corresponds to the duration spent in that span. The widest span is often the best starting point for investigating latency. In this example, the waterfall shows frontend → order → inventory → payment, and the inventory span is the widest (about 5 seconds), revealing a likely bottleneck.
A Jaeger UI trace screenshot showing a "frontend-svc: GET /" trace with multiple nested spans for services like frontend-svc, order-svc, inventory-svc and payment-svc across a ~5.21s timeline. The left panel lists services and operations while the right shows colored horizontal bars indicating each span's timing and duration.
If traces still do not appear, use this checklist:
  • Confirm the environment variables are present on the running pod:
  • Confirm you patched the correct container name (the patch targets the container named frontend-svc in this example).
  • Verify the OTLP endpoint and protocol match the Jaeger collector service and port.
  • Inspect application and OTel SDK logs for errors or warnings that indicate export failures.
  • Ensure network policies or service mesh sidecars (if present) are not blocking export traffic to the collector.

Summary and next steps

You enabled OpenTelemetry tracing for a Kubernetes service and exported traces to Jaeger by:
  • Setting the service name (OTEL_SERVICE_NAME).
  • Pointing the SDK at the Jaeger OTLP endpoint (OTEL_EXPORTER_OTLP_ENDPOINT).
  • Choosing the correct transport protocol (OTEL_EXPORTER_OTLP_PROTOCOL or protocol-specific variables).
  • Enabling the OTLP exporter (OTEL_TRACES_EXPORTER).
With traces visible in Jaeger, use the waterfall view to find latency hotspots and drill into span details to identify where to optimize. Try the same steps for other services (order, inventory, payment) and consider adding instrumentation libraries or auto-instrumentation for richer spans and attributes. Links and references

Watch Video

Practice Lab