Enable Application Signals Auto-Instrumentation on EKS Using ADOT: Implementation Guide

You enable Application Signals auto-instrumentation on Amazon EKS by installing the amazon-cloudwatch-observability add-on, which deploys the AWS Distro for OpenTelemetry (ADOT) collector as a DaemonSet and automatically injects language-specific SDKs into pods via a mutating webhook, requiring zero application code changes.

AWS Application Signals (formerly CloudWatch Observability) provides automatic collection of metrics, traces, and logs from containerized workloads. According to the aws/agent-toolkit-for-aws repository, this auto-instrumentation architecture relies on the Amazon CloudWatch Observability EKS add-on to manage the complete lifecycle of ADOT components, from initial SDK injection to telemetry export, as documented in skills/core-skills/aws-observability/SKILL.md.

How the ADOT Auto-Instrumentation Architecture Works

The toolkit implements a non-intrusive instrumentation pattern that intercepts pod specifications at deployment time and injects the necessary OpenTelemetry components.

The CloudWatch Observability EKS Add-on

The amazon-cloudwatch-observability add-on runs as a DaemonSet on every node in your EKS cluster. It deploys two critical components: the ADOT collector and the CloudWatch Agent. The add-on also registers a mutating webhook that monitors for specific annotations on Deployment and StatefulSet resources. When it detects the adot.autoinstrumentation=true annotation, the webhook automatically modifies the pod specification to include an init container and environment variables. This architecture is detailed in the onboarding guide at skills/core-skills/aws-observability/references/application-signals-onboarding.md.

Init-Container Injection Mechanism

When the webhook detects an annotated workload, it injects an ADOT init container into the pod spec before the application containers start. This init container mounts a shared volume and installs the language-specific ADOT auto-instrumentation SDK into the application container's filesystem. For example, the Python init container uses the image public.ecr.aws/aws-observability/adot-autoinstrumentation-python:v0.18.0 to install the aws-opentelemetry-distro package. The init container approach ensures the SDK is present without requiring modifications to the application Docker image.

Collector Configuration and Exporters

The ADOT collector runs either as a sidecar or as part of the node-level DaemonSet, depending on the configuration. It is pre-configured with several key components:

  • OTLP exporter: Points to the Application Signals endpoint via the OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT environment variable
  • X-Ray exporter: Optional component for backward compatibility with existing X-Ray implementations
  • awsproxy extension: Allows the collector to forward X-Ray traces through the CloudWatch Agent when needed

The collector configuration for EKS DaemonSet deployments is documented in skills/core-skills/aws-observability/references/tracing.md.

Prerequisites and IAM Configuration

Before enabling auto-instrumentation, you must configure the appropriate IAM permissions for telemetry export.

Required IAM Policies

The node group IAM role or the pod's service account (via IRSA) must attach the CloudWatchAgentServerPolicy managed policy. This grants the ADOT collector permissions to publish metrics and traces to CloudWatch Application Signals. The add-on automatically attaches these policies to the node role when installed; for custom pod roles using IRSA, you must manually attach the policy.

Supported Language Runtimes

The toolkit provides specific init container images and SDK versions for each supported language:

Step-by-Step Implementation

Install the Amazon CloudWatch Observability Add-on

Using AWS CDK (TypeScript), enable the add-on to deploy the DaemonSet and mutating webhook:

import * as eks from 'aws-cdk-lib/aws-eks';

const cluster = eks.Cluster.fromClusterAttributes(this, 'MyCluster', {
  clusterName: 'my-eks-cluster',
  vpc: myVpc,
  securityGroup: mySg,
  // additional attributes
});

cluster.addAwsCdkAddon('cloudwatch-observability', {
  addonName: 'amazon-cloudwatch-observability',
  version: 'v6.3.0',
  resolveConflicts: eks.ResolveConflicts.OVERWRITE,
});

For Terraform, attach the required policy to your node group role:

resource "aws_iam_role_policy_attachment" "cw_observability" {
  role       = aws_eks_node_group.my_node_group.role
  policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
}

Annotate Deployments for Auto-Instrumentation

Add the adot.autoinstrumentation annotation to your workload manifests to trigger the mutating webhook:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-python-app
  annotations:
    adot.autoinstrumentation: "true"
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-python-app
  template:
    metadata:
      labels:
        app: my-python-app
    spec:
      serviceAccountName: my-app-sa
      containers:
        - name: app
          image: myrepo/my-python-app:latest

The webhook automatically injects the appropriate init container based on the detected language runtime.

Configure ServiceEvents (Optional)

For supported languages (Python, Node.js, Java), the add-on can inject ServiceEvents environment variables to include CI/CD metadata in traces:

env:
  - name: OTEL_SERVICE_NAME
    value: "my-python-service"
  - name: OTEL_RESOURCE_ATTRIBUTES
    value: "deployment.environment=prod,git.repository=repo-name"

These variables are automatically added when ServiceEvents is enabled for the platform and language combination, as noted in skills/core-skills/aws-observability/references/application-signals-onboarding.md.

Understanding the End-to-End Flow

The complete telemetry flow follows this path:

  1. Application Pod starts with the init container copying the ADOT SDK into the container filesystem
  2. ADOT SDK automatically instruments the application runtime using the attached agent or wrapper
  3. ADOT Collector receives OTLP data from the SDK via local endpoints
  4. CloudWatch Application Signals ingests the metrics and traces for visualization and analysis

This architecture ensures that workloads send telemetry to the OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT without requiring manual SDK initialization or exporter configuration in the application code.

Summary

  • Install the add-on: Deploy amazon-cloudwatch-observability to create the DaemonSet and mutating webhook that manage ADOT components
  • Annotate workloads: Add adot.autoinstrumentation=true to Deployments or StatefulSets to trigger automatic SDK injection
  • Configure IAM: Ensure node roles or IRSA-attached roles include CloudWatchAgentServerPolicy for telemetry export permissions
  • Language support: Use built-in init containers for Python (0.18.x), Node.js (0.12.x), Java (2.28.2), and .NET without code changes
  • Reference architecture: Consult skills/core-skills/aws-observability/SKILL.md and the language-specific guides in appsignals-guides/ for implementation details

Frequently Asked Questions

What is the difference between ADOT and the CloudWatch Observability add-on?

ADOT (AWS Distro for OpenTelemetry) is the open-source distribution of OpenTelemetry that provides the SDKs and collectors for telemetry collection. The Amazon CloudWatch Observability add-on is the managed EKS component that automates the deployment and configuration of ADOT, including the mutating webhook, init containers, and IAM policy management. You use the add-on to consume ADOT without manually managing the collector configurations or SDK installations.

Do I need to modify my application code to use auto-instrumentation?

No. Auto-instrumentation requires zero code changes. The mutating webhook detects the adot.autoinstrumentation annotation and injects an init container that installs the language-specific SDK into the container filesystem. The SDK then automatically instruments supported libraries and frameworks at runtime using environment variables like OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES.

Which programming languages support Application Signals auto-instrumentation on EKS?

Python, Node.js, Java, and .NET are fully supported. The toolkit provides specific init container images and SDK versions for each: Python uses the aws-opentelemetry-distro pip package (0.18.x), Node.js uses the @aws/aws-distro-opentelemetry-node-autoinstrumentation npm package (0.12.x), Java uses the ADOT Java agent JAR (2.28.2), and .NET uses the AWSOpenTelemetryDistroDotNet script. Each language has a dedicated guide in the skills/core-skills/aws-observability/references/appsignals-guides/ directory.

How does the collector export data to Application Signals?

The ADOT collector deployed by the add-on is pre-configured with an OTLP exporter that targets the OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT. It also includes the awsproxy extension to forward X-Ray traces through the CloudWatch Agent when necessary. This configuration is applied automatically by the DaemonSet deployment described in skills/core-skills/aws-observability/references/tracing.md.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →