Skip to main content
This walkthrough demonstrates how to enable automatic OpenTelemetry instrumentation for a Python Flask application using the OpenTelemetry Operator and Collector in Kubernetes. The operator can inject language-specific auto-instrumentation into pods so you don’t need to modify application code. What you’ll do:
  • Deploy an Instrumentation custom resource (CR) to configure auto-instrumentation.
  • Annotate a Deployment to opt the pod into Python auto-instrumentation.
  • Generate traffic and verify traces in Jaeger.
Prerequisites:
  • A Kubernetes cluster (e.g., kind, GKE, EKS).
  • OpenTelemetry Operator and an OpenTelemetry Collector deployed in the cluster.
  • A tracing backend such as Jaeger.
For operator installation and examples, see the OpenTelemetry operator docs: https://opentelemetry.io/docs/operator/
This image shows a screenshot of the OpenTelemetry documentation webpage, focusing on the installation and configuration of an OpenTelemetry Operator for Kubernetes. It includes sections on installing the operator, creating a collector, and configuring automatic instrumentation.

Sample Flask application (no manual instrumentation)

Save this Flask app as app.py (this example contains no OpenTelemetry code):
Because the app is uninstrumented, the operator will inject auto-instrumentation at pod startup.

Verify cluster components

Confirm nodes and that the Collector pod and operator are running:

Create the Instrumentation CR

Create an Instrumentation resource to tell the operator:
  • which exporter endpoint to use (Collector HTTP OTLP/4318),
  • which context propagators to enable,
  • the sampling strategy.
Save as instrumentation.yaml:
Key fields explained:
FieldPurposeExample
exporter.endpointCollector HTTP endpoint where auto-instrumented telemetry is senthttp://my-collector-collector:4318
propagatorsContext propagation formats to supporttracecontext, baggage
samplerSampling strategy for generated tracestype: parentbased_traceidratio, argument: "1" (sample 100%)
Apply the Instrumentation CR:
Confirm pods (operator, Collector, Jaeger, app):

Opt your Deployment into auto-instrumentation

To enable Python auto-instrumentation for a Deployment, add the annotation instrumentation.opentelemetry.io/inject-python: "true" to the pod template. You can also reference a specific Instrumentation CR by name (e.g., "python-instrumentation") or use cross-namespace format ("other-namespace/my-instrumentation").
Add instrumentation.opentelemetry.io/inject-python: "true" to your Deployment pod template to enable Python auto-instrumentation. You may also set the annotation value to the Instrumentation CR name to bind to a specific configuration.
The operator documentation lists language-specific annotation options for other runtimes as well.
The image shows a webpage from the OpenTelemetry documentation, focusing on adding annotations for automatic instrumentation in different programming languages. There is a sidebar for navigation and various options for language-specific configurations.

Deployment and Service (example)

Save this Deployment + Service as flask_deployment.yaml. It includes the Python injection annotation and exposes the app via a NodePort.
Apply the Deployment and Service:
Confirm the new pods are running:
Verify nodes:

Generate traffic and verify traces

Send a request to the service using a node IP and the NodePort (replace with your node IP):
Because the operator injected the Python instrumentation and exported telemetry to the Collector, you should see traces for myapp-api in Jaeger. Open the Jaeger UI and refresh the traces list to locate recent traces for the service.
The image shows the Jaeger UI dashboard displaying search results for traces related to a service. It includes a timeline graph, trace details, and filtering options.
Click a trace to inspect attributes automatically added by the instrumentation—pod name, node name, replica set, service instance, HTTP attributes, and more.
The image shows a trace analysis interface displaying details of a GET request, including HTTP and process information in a structured format.

Summary

Steps recap:
  1. Deploy the OpenTelemetry Operator and a Collector.
  2. Create an Instrumentation CR that configures exporter, propagators, and sampler.
  3. Annotate your Deployment pod template to enable language-specific auto-instrumentation.
  4. Generate traffic and verify traces in your tracing backend (Jaeger/Zipkin).
If you need help adapting this to another runtime (Java, Node.js, .NET), the operator supports language-specific annotations — see the Operator docs for details.

Watch Video

Practice Lab