This page covers how to point an existing Ingress-NGINX deployment at Odigos. It is not a guide to installing or operating the controller. For controller setup, see the Ingress-NGINX installation guide.
Tracing happens at the Ingress-NGINX Controller, not in your application’s nginx pods. Stock
nginx images lack the OpenTelemetry module, but the controller bundles it and turns a few ConfigMap keys into the right OTel directives. Put the workloads you want traced behind an Ingress and enable OTel on the controller.Prerequisites
Kubernetes 1.26 or newer
The
odigos-data-collection-local-traffic service depends on internalTrafficPolicy: Local, which became GA in 1.26.A running Ingress-NGINX Controller
The Ingress-NGINX Controller must be installed in your cluster, with the OpenTelemetry module available. Follow the Ingress-NGINX installation guide.
Workloads exposed through an Ingress
The controller only emits spans for traffic that flows through it. Make sure the workloads you want traced are fronted by an
Ingress resource that routes to their Service. For background on routing, see the Ingress-NGINX user guide.Configuration
Point the controller at the Odigos OTLP endpoint
Configure the Ingress-NGINX Controller to export OpenTelemetry traces to the Odigos node collector’s OTLP/gRPC endpoint. For background on these keys, see the controller’s OpenTelemetry documentation.Choose one of the methods below based on how you manage the controller. If you installed it with Helm, use Helm values so a later
helm upgrade does not overwrite the settings; otherwise apply the ConfigMap directly.- Helm
- ConfigMap
Enable the OTel module and set the exporter through the
ingress-nginx chart values:Enable tracing per route
Enabling OTel on the controller does not trace every route by default. Activate tracing on a route with per-
Ingress annotations. For the full set of options, see the controller’s OpenTelemetry documentation.Confirm a destination on the default data stream
The Odigos collector only exports data when at least one destination is configured. Because the controller emits ingress spans on behalf of the edge rather than any specific Odigos-instrumented workload, the collector routes them through the default data stream — so make sure the destination you want the NGINX traces to reach is assigned to the default data stream.
Validation
After traffic flows through the ingress, look for the controller’s spans in your tracing backend. They appear under the service name you set inotel-service-name (for example, nginx-ingress), distinct from the application service names Odigos reports.
Confirm the path end to end. Neither the NGINX OTel module nor the Odigos collector logs anything per span, so no OTel errors in the logs is the healthy state — any OTel output is an error. To confirm spans are actually arriving, check your destination.
- Controller logs — confirm there are no export errors:
UNAVAILABLE error on every flush:
otlp-collector-host/otlp-collector-port, port 4318 instead of 4317, or a NetworkPolicy blocking egress to odigos-system.
- Collector logs — the collector is also quiet on success. Watch for export errors toward your destination:
Exporting failed. Dropping data. or Exporting failed. Rejecting data.:
- Your destination — open your backend and look for a service named after
otel-service-name(for example,nginx-ingress).
Example
Real traces interleave the NGINX ingress span with the Odigos application spans — the ingress span wraps the upstream’s application work, which itself can fan out into more application spans. A request throughingress → frontend → checkout lays out like this:
Horizontal position is time; indentation shows parent/child nesting.
NGINX ingress spans are additive — they do not replace the application spans Odigos generates. Each traced request yields an ingress span plus the application span(s), all sharing the same trace, as long as
opentelemetry-trust-incoming-span is enabled so context propagates to your workloads.Tuning
| Key | Effect |
|---|---|
otel-service-name | The service name spans show up under. Set per environment. |
opentelemetry-operation-name | Template for the span name. HTTP $request_method $uri produces names like HTTP GET /checkout; supports NGINX variables. |
otel-sampler | Leave at the default (AlwaysOn), which captures 100%, and configure sampling with Odigos tail sampling instead. |
opentelemetry-trust-incoming-span | Whether to continue trace context from inbound requests. Keep true so ingress spans link to upstream callers and downstream workloads. |
nginx.ingress.kubernetes.io/enable-opentelemetry (annotation) | Per-Ingress enablement. Remove to stop tracing a specific route. |
Troubleshooting
- No spans at all — the most common cause is a wrong
otlp-collector-host. Theodigos-data-collection-local-trafficservice must exist inodigos-systemand accept OTLP/gRPC. Verify withkubectl get svc -n odigos-system. - Set 4318 and nothing arrives — the module is gRPC-only; use 4317.
- OTel keys added to an application nginx ConfigMap did nothing — expected; that is the stock-nginx ConfigMap, not the controller’s. OTel config belongs in the controller ConfigMap.
- Config changes ignored — roll the controller:
kubectl -n ingress-nginx rollout restart deployment ingress-nginx-controller.