ことの始まり
OpenTelemetryの自動計装を使って、アプリケーションコードを修正せずにトレースを取得したいな。
AWSだと ADOT(AWS Distro for OpenTelemetry) があるのか。
ECSならサイドカー構成にすればいい、と。ふむふむ。
ドキュメントを見ると、ちゃんとEC2へのADOT Collectorのインストール方法があるじゃん。
なるほど、これを入れて自動計装したアプリからOTLPで送ればいいのね。
…あれ?
ADOTにhostmetrics receiverがない。
メモリ使用率とかCloudWatch Agentで取っていたメトリクスもまとめてOpenTelemetryに寄せたいんだけど…。
え、ADOT Collectorだけじゃ取れないじゃん!
CloudWatch Agentと二重管理になっちゃう!
という茶番はさておき、ECSサイドカーコンテナとしてADOT Collectorを使う話はよく聞きます。
ADOTにはawscontainerinsightreceiverとawsecscontainermetricsreceiverがいるので困ることは少ないと思います。
が、EC2においてはv0.49.0の Collectorだけでメトリクス取得が完結しなさそうでした。
レシーバー一覧などはGitHubで記載があります。
結論
EC2においてはADOT Collectorを別途インストールする必要はありませんでした。
対応方法は2通りあるかと思います。
- CloudWatch AgentをOpenTelemetry Collectorとして使う
- OpenTelemetryでメトリクス・ログ・トレース一元管理する
AWSドキュメントを参照すると新規で監視を構築するならOpenTelemetryを使うことを推奨しているので、2の対処法で解決するかと思います。
一方で既存のCloudWatch Agentをやめずに自動計装でトレースを取得したい時が1のパターンかと思います。
Pythonで検証
以下の2通りで試します。
- CloudWatch AgentをOpenTelemetry Collectorとして使う
- OpenTelemetryでメトリクス・ログ・トレース一元管理する ※ログは取り忘れてます
1.CloudWatch AgentをOpenTelemetry Collectorとして使う
CloudWatch Agentの設定ファイルは例として以下とします。
{
"metrics": {
"metrics_collected": {
"mem": {
"measurement": [
"mem_used_percent"
]
}
}
},
"traces": {
"traces_collected": {
"otlp": {}
}
}
}
コードはとても簡単で、boto3を自動計装することを考えます。
S3バケット内のオブジェクト一覧を取得する処理を実行します。
import boto3
s3 = boto3.client("s3")
response = s3.list_objects_v2(
Bucket="gengen"
)
for obj in response.get("Contents", []):
print(obj["Key"])
ライブラリのインストールは以下となります。
それぞれのライブラリの役割が分かるよう、あえて分けて記載しています。
# 自動計装コマンド「opentelemetry-instrument」を使うため
pip install opentelemetry-distro
# OTLPでトレースを送信するためのExporter(CloudWatch Agentので作成するOTLPエンドポイントへ送信する)
pip install opentelemetry-exporter-otlp
# boto3 / botocoreを自動計装するためのInstrumentation
pip install opentelemetry-instrumentation-botocore
systemdでアプリケーションを管理している場合は以下を足しておけばApplication Signalsでサービス名が登録できます。
今回は事前にコマンドで設定しておきます。
export OTEL_SERVICE_NAME=s3-test
自動計装しながらpythonを実行します。
opentelemetry-instrument python s3-test.py
2.OpenTelemetryでメトリクス・ログ・トレース一元管理する ※ログは取り忘れてます
以下を参考にEC2にインストールします。
sudo yum update
sudo yum -y install wget systemctl
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.157.0/otelcol-contrib_0.157.0_linux_amd64.rpm
sudo rpm -ivh otelcol-contrib_0.157.0_linux_amd64.rpm
次に/etc/otelcol-contrib/config.yamlを修正します。
extensions:
sigv4auth:
region: ap-northeast-1
service: monitoring
receivers:
hostmetrics:
collection_interval: 60s
scrapers:
memory:
otlp:
protocols:
grpc:
endpoint: 127.0.0.1:4317
http:
endpoint: 127.0.0.1:4318
processors:
batch:
exporters:
otlphttp/cloudwatch:
endpoint: https://monitoring.ap-northeast-1.amazonaws.com
auth:
authenticator: sigv4auth
awsxray:
region: ap-northeast-1
service:
extensions:
- sigv4auth
pipelines:
metrics:
receivers:
- hostmetrics
processors:
- batch
exporters:
- otlphttp/cloudwatch
traces:
receivers:
- otlp
processors:
- batch
exporters:
- awsxray
上記設定ファイルは以下を参考に作成しています。
python周りは先ほどと同様で自動計装しながらpythonを実行します。
opentelemetry-instrument python s3-test.py
CloudWatch Query Studioを確認したところ、メモリに関するメトリクスが取得できています。

おまけ
OpenTelemetryで一元管理している方で追加対応してみました。
Flaskで8080ポートを受け付け、DynamoDBへGetItemする処理を追加してトレースを確認しました。
リクエストURLや処理時間、どのDynamoDBのテーブルへGetItemしているかが確認できます。

まとめ
EC2上で稼働するアプリケーションをOpenTelemetryの自動計装を使いたい場合は以下の2通りになります。
- CloudWatch AgentをOpen Telemetry Collectorとして使う
- OpenTelemetryでメトリクス・ログ・トレース一元管理する
2が一番キレイに見えますが、すでに本番稼働している場合はCloudWatch Query Studioでアラームを定義し直す作業が発生するため
まずは自動計装したいのであれば1で試していく方針がいいかなと思います。



