Linkerd 2.19 and later can export a span for every proxied request directly from the mesh sidecar, with no extra tracing backend or cert-manager setup required. Combined with instrumented application pods, these proxy spans connect into end-to-end traces that show exactly how a request moved through your mesh.
How it works
Enabling tracing has two parts:
Mesh-level trace export: The Linkerd proxies export a span per request to your OTel Collector. This alone gives you proxy-level traces (retries, mTLS handshakes, latency per hop) without touching your application.
Application instrumentation: Your app pods propagate the same W3C trace context the proxies use, and export their own spans. Combining both gives you a full waterfall in the same trace: from the client app, through the Linkerd proxy, to the backend app.
Before you begin
Ensure you have:
Linkerd edge-26.7.0 or later (2.19+). Proxy tracing on earlier releases required a separate collector service and cert-manager integration, which this guide doesn't cover. See the Linkerd getting started guide if you need to upgrade.
NRDOT or OTel Collector Contrib up and running for your Linkerd instance:
transform/linkerd_service_name makes each meshed deployment's name its APM service.name. Use unique deployment names across every cluster reporting to the same account. A name that also exists in another cluster resolves to the same entity there, so their data gets merged rather than showing up as two separate services.
2. Mark the collector's OTLP port as gRPC. The chart's nr-k8s-otel-collector-gateway Service doesn't declare appProtocol on its gRPC port. Without it, Linkerd's own protocol detection can misidentify traffic to the collector and silently drop the proxies' trace exports:
transform/linkerd_service_name makes each meshed deployment's name its APM service.name. Use unique deployment names across every cluster reporting to the same account. A name that also exists in another cluster resolves to the same entity there, so their data gets merged rather than showing up as two separate services.
Re-apply the ConfigMap above, then complete these one-time steps:
1. Mesh the collector. Linkerd proxies can only export traces to a collector that is itself inside the mesh:
2. Mark the collector's OTLP port as gRPC. The rendered nr-k8s-otel-collector-gateway Service doesn't declare appProtocol on its gRPC port. Without it, Linkerd's own protocol detection can misidentify traffic to the collector and silently drop the proxies' trace exports:
As of Linkerd 2.19, proxy trace export is configured directly in the control plane, with no cert-manager or separate port required. Two steps are required: make the collector able to receive traces, then turn on trace export from the proxies.
Step 1: Add trace ingestion to the collector
Unlike the NRDOT chart, the community open-telemetry/opentelemetry-collector chart doesn't include an otlp receiver by default. Add it explicitly, along with the same processors used on the NRDOT tab.
Add the same three blocks above (Receivers, Processors, Pipelines) to the config key of the ConfigMap in your otel-collector.yaml from OTel Collector Contrib with manifest. The Service in that manifest already exposes port 4317 (grpc) and 4318 (http), so no port changes are needed. Re-apply and restart. Re-applying the ConfigMap alone doesn't restart the running collector pod, so it won't pick up the new config without the second command:
1. Mesh the collector. Linkerd proxies can only export traces to a collector that is itself inside the mesh. Unlike the NRDOT chart's nr-k8s-otel-collector-gateway, nothing in the OTel Collector Contrib manifest or Helm chart injects the collector pod into the mesh by default:
The meshIdentity stanza below is mandatory. Linkerd can only export traces to a collector that is inside the mesh, which is what the command above just did.
Add the OTel Java agent (or the agent for your language) to propagate trace context headers. Linkerd supports both W3C Trace Context and B3 formats. The OTel agent handles this automatically.
Dica
spec.exporter.endpoint below points at the OTel Collector Contrib with manifest page's Service. If you deployed the NRDOT collector, use http://nr-k8s-otel-collector-gateway.newrelic.svc.cluster.local:4317 instead.
For other languages (Python, .NET, Node.js, Go) and advanced Operator configuration, such as sidecar vs. init-container injection, resource limits, or multi-container pods, see the OpenTelemetry Operator automatic instrumentation docs.
Correlate app metrics with APM (optional)
If your app also exports OTel SDK metrics (not just traces) to the collector, add the following to route them into an APM-compatible metrics pipeline.