はじめに
最近Dynatraceを少し触る機会があり、アプリケーションのトレース(分散トレース)を取得する仕組みを調べていました。Dynatraceではエージェント(OneAgent)をKubernetes環境に導入して取得する場合は以下の二種類の方法があります。
| 方式 | 概要 |
|---|---|
| CloudNativeFullStack (MutatingWebhook +init-container + CSI Driver) |
MutatingWebhookがPod作成時にinit-containerを注入し、CSI Driver経由でOneAgentコードモジュールをボリュームマウント。Pod単位でLD_PRELOAD環境変数を設定して注入する方式 |
| ClassicFullStack (DaemonSet) |
DaemonSetとして各ノードにデプロイし、ホストOSの ld.so.preload経由で全プロセスに自動注入する方式 |

*CloudNativeFullStackの方がClassicFullStackと比較して新しい仕組みであり、Dynatraceのドキュメントでは前者の方式での導入を推奨されています。Dynatraceに関して詳細な仕様を確認したい場合、Dynatrace Operatorのgithubを参照するのが良いです。
AWSにおいては分散トレーシングの領域で長らく提供されてきたX-Rayの他に、AWS Distro for OpenTelemetryというサービスも提供されています。そこで気になったのが、AWSのネイティブサービスではどのようにトレースを取得するのか、ということです。それぞれどういった仕組みで動いているのでしょうか。
AWSネイティブサービスでのEKSのトレース取得
利用可能な選択肢
2026年5月現在、AWS Distro for OpenTelemetry(ADOT), X-Ray SDKの2つのサービスが存在します。ただし、X-Ray SDKはメンテナンスモードに移行しているため、今から利用する場合は特別な理由がない限りADOTの方が良いでしょう。
| サービス | 方式 | 備考 |
|---|---|---|
| AWS Distro for OpenTelemetry | Webhook + init-container | |
| X-Ray SDK + Daemon | 手動コード埋め込み + Daemon | 現在メンテナンスモード |
AWS Distro for OpenTelemetry
概要
AWS Distro for OpenTelemetry(ADOT)はAWSがサービスとして提供するOpenTelemetryのディストリビューションです。
仕組み
前述のDynatraceのCloudNativeFullStackと同様に、MutatingWebhookによりinit-containerをPodに追加することでトレースを取得します。
*MutatingWebhookはKubernetesの機能で、Podが作成される際にその定義を自動的に書き換えることができる仕組みです。この場合、App Podを作成する際に元々作成予定だったコンテナに加えてinit-containerを自動的に作成するようにします。

導入方法
EKSにADOTの導入はマネジメントコンソールからアドオンをインストールすることにより可能ですが、アドオンが実は2種類(AWS Distro for OpenTelemetry, Amazon CloudWatch Observability)あります。
後者の方が簡単に設定出来るため、今回は後者のAmazon CloudWatch Observabilityを導入してみます。
| Add-on | 名前 | 用途 |
|---|---|---|
| AWS Distro for OpenTelemetry | adot |
Collectorを完全に自分で構成したい場合 |
| Amazon CloudWatch Observability | amazon-cloudwatch-observability |
Application Signals + Container Insightsを使いたい場合 |
以下のように2つ並んでいますが、右側のAmazon CloudWatch Observabilityを選びます。
スクリーンショットの通り、EKS on Fargateを利用している場合は左を選ぶ必要があります。推測ですが、おそらくCloudWatch AgentをDaemonsetの形で展開するが、FargateはDaemonsetをサポートしていないからだと思われます。
(DaemonSetとはKubernetesのクラスタを構成するNode(サーバ)に特定のコンテナを1個ずつ展開するKubernetesのリソースです。)

アドオン導入後、関連するPodが作成されていることが確認できます。
$ kubectl get pods -n amazon-cloudwatch -o wide
NAME READY STATUS RESTARTS AGE IP NODE
amazon-cloudwatch-observability-controller-manager-5698f467hhqh 1/1 Running 0 26m 10.0.133.132 ip-10-0-137-41.ap-northeast-1.compute.internal
cloudwatch-agent-9dsj4 1/1 Running 0 26m 10.0.153.235 ip-10-0-153-235.ap-northeast-1.compute.internal
cloudwatch-agent-sbkh5 1/1 Running 0 26m 10.0.137.41 ip-10-0-137-41.ap-northeast-1.compute.internal
fluent-bit-pv8sr 1/1 Running 0 26m 10.0.153.235 ip-10-0-153-235.ap-northeast-1.compute.internal
fluent-bit-xr468 1/1 Running 0 26m 10.0.137.41 ip-10-0-137-41.ap-northeast-1.compute.internal
サンプルコンテナを作成すると、init-containerの設定がpodのyamlに含まれていること・OpenTelemetryの環境変数が設定されていることが分かります。
apiVersion: v1
kind: Pod
metadata:
name: flask-sample-7d6b799697-dnlhf
namespace: tracing-demo
labels:
app: flask-sample
pod-template-hash: 7d6b799697
spec:
initContainers:
- name: opentelemetry-auto-instrumentation-python
image: 602401143452.dkr.ecr.ap-northeast-1.amazonaws.com/eks/observability/adot-autoinstrumentation-python:v0.17.0
command:
...略...
volumeMounts:
- mountPath: /otel-auto-instrumentation-python
name: opentelemetry-auto-instrumentation-python
containers:
- name: app
image: python:3.12-slim
...略...
env:
- name: OTEL_AWS_APP_SIGNALS_ENABLED
value: "true"
- name: OTEL_AWS_APPLICATION_SIGNALS_ENABLED
value: "true"
- name: OTEL_TRACES_SAMPLER_ARG
value: endpoint=http://cloudwatch-agent.amazon-cloudwatch:2000
...略...
可視化方法
ADOTではトレースデータを複数の方法で可視化することが出来ます。
CloudWatch Application Signals
CloudWatchの一機能として、しれっと左タブに存在するのがこのApplication Signalsです。
amazon-cloudwatch-observabilityを利用する場合は自動で設定されます。
先ほど作成したサンプルアプリに何件かリクエストを発生させて、Application Signalsで確認してみます。

以下のようにレイテンシーやトレース情報が取得できています。
マルチバックエンド
上記のApplication Signalsに加えて、CloudWatch AgentにカスタムのOTel パイプラインを追加することで、別のバックエンド(組織で利用しているAPM製品やPrometheus・Jaeger等)にもデータを送信・可視化できます。
詳細は以下のドキュメントのAppending OpenTelemetry collector configuration filesを確認してください。
X-Ray SDK + Daemon
概要
この方法はADOTのサービスリリース前から存在する方法で、アプリケーションのコードにX-Ray SDKを組み込み、X-Ray Daemon経由でトレース情報を送信することでトレースを取得します。
2026年2月にメンテナンスモードへ移行したため、今から利用する場合はADOTをオススメします。
仕組み
ADOTと異なり、トレースを取得するにはアプリケーションコードへのSDK組み込みが求められます。加えて、トレースデータの送信を担うX-Ray DaemonをDaemonSet等でクラスタに展開しておく構成になります。

導入方法
アプリケーションのコードに明示的にSDKを組み込む必要があります。
from flask import Flask, jsonify
from aws_xray_sdk.core import xray_recorder ←←←
from aws_xray_sdk.ext.flask.middleware import XRayMiddleware ←←←
app = Flask(__name__)
xray_recorder.configure(service='my-service')
XRayMiddleware(app, xray_recorder)
@app.route('/hello')
def hello():
subsegment = xray_recorder.begin_subsegment('custom-logic')
try:
subsegment.put_annotation('key', 'value')
result = {"message": "hello"}
except Exception as e:
subsegment.add_exception(e)
raise
finally:
xray_recorder.end_subsegment()
return jsonify(result)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
可視化方法
X-Ray SDKでトレースを取得する場合も、ADOTの場合と同様にAWS CloudWatch Application Signalsで確認が可能です。

ただし、以下のドキュメントを見るとApplication SignalsとしてもADOTとX-Ray SDKで一部機能的な差があるようです。
まとめ
この記事ではEKSのトレースを取得する方法について、AWS Distro for OpenTelemetry(ADOT)とX-Ray SDKの仕様に焦点を当てて確認を行いました。
普段あまり意識することはないかもしれませんが、MutatingWebhookやDaemonSetなどKubernetesの仕様がどのように活用されているかを理解しておくと何かのタイミングで役に立つかもしれません(実は私がこの仕様を調べたのは、Dynatraceを導入する際にMutatingWebhookがクラスタ設定で上手く動かなかったからです)。
この記事がなにかの役に立てば幸いです。

