AWS上にObservability検証環境を構築してみた(Grafana + Tempo + Loki + AMP)
こんにちは、ゲームソリューション部のsoraです。
今回は、AWS上にObservability検証環境を構築してみたことについて書いていきます。
構成
今回構築したのは以下の構成です。
Fargateで動くサンプルアプリでADOT Collector + FluentBitを使って、トレース・ログ・メトリクスを収集し、EC2上のGrafanaで可視化する構成です。
サンプルアプリがあるECSへはHTTPで接続します。
プライベートサブネットのEC2へはSSMポートフォワーディングで接続します。

| 主なコンポーネント | 役割 |
|---|---|
| ECS(Fargate) | サンプルアプリ + ADOT Collector + FluentBit |
| EC2 | Grafana / Tempo / Loki(docker-compose) |
| ALB | サンプルアプリへのHTTPアクセス |
| Amazon Managed Service for Prometheus (AMP) | メトリクスの保存 |
データのフローについては以下です。
- トレース:アプリ → ADOT Collector → Tempo(EC2)
- ログ:アプリ → FluentBit(FireLens)→ Loki(EC2)
- メトリクス:アプリ → ADOT Collector → AMP
構築
今回はTerraformで構築しました。
基本的なリソースが多いのでコードは割愛しますが、ポイントだけ解説します。
Amazon Managed Service for Prometheus(AMP)
AMPはフルマネージドなPrometheus互換のモニタリングサービスです。
AWSコンソールからワークスペースを作成すると、以下のような画面が表示されます。

ワークスペースには以下の情報が含まれています。
- エンドポイント - リモート書き込みURL:メトリクスを送信する際に使用
- エンドポイント - クエリURL:Grafanaなどからクエリを実行する際に使用
ちなみに、AMP自体にはメトリクスを閲覧するUIがありません。
そのため、Grafanaなどの外部ツールからクエリして可視化する必要があります。
また、ルール管理やアラートマネージャーの設定はコンソールから行うことができます。
OpenTelemetry(OTel)の設定
サンプルアプリにOpenTelemetry SDKを組み込み、トレースとメトリクスを出力します。
from opentelemetry import trace, metrics
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
# トレース設定
provider = TracerProvider(resource=resource)
otlp_exporter = OTLPSpanExporter(
endpoint=os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317"),
insecure=True
)
provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
trace.set_tracer_provider(provider)
# メトリクス設定
metric_exporter = OTLPMetricExporter(
endpoint=os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT", "http://localhost:4317"),
insecure=True
)
metric_reader = PeriodicExportingMetricReader(metric_exporter)
meter_provider = MeterProvider(resource=resource, metric_readers=[metric_reader])
metrics.set_meter_provider(meter_provider)
FlaskとRequestsの自動計装も有効にしています。
FlaskInstrumentor().instrument_app(app)
RequestsInstrumentor().instrument()
これにより、HTTPリクエストのトレースとメトリクスが自動的に収集されます。
ADOT Collectorの設定
ECSタスク内でサイドカーとして動作するADOT Collectorが、アプリからのテレメトリを受信して各ツールやサービスへ転送します。
AMPへの書き込みにはSigV4認証が必要なため、sigv4authを設定しています。
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
exporters:
otlphttp/tempo:
endpoint: http://${TEMPO_ENDPOINT}:4318
prometheusremotewrite:
endpoint: ${AMP_REMOTE_WRITE_URL}
auth:
authenticator: sigv4auth
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlphttp/tempo]
metrics:
receivers: [otlp]
exporters: [prometheusremotewrite]
Tempoの設定
Tempoはトレースデータを保存・検索するためのツールです。
server:
http_listen_port: 3200
distributor:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
ingester:
max_block_duration: 5m
lifecycler:
ring:
kvstore:
store: inmemory
replication_factor: 1
storage:
trace:
backend: local
local:
path: /var/tempo/traces
wal:
path: /var/tempo/wal
Lokiの設定
Lokiはログデータを保存・検索するためのツールです。
ECSタスクからはFluentBit(FireLens)経由でログを受信します。
auth_enabled: false
server:
http_listen_port: 3100
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
Grafanaの設定
Grafanaでは、Tempo・Loki・AMPの3つをデータソースとして設定します。
AMPへの接続にはSigV4認証を使用するため、EC2のIAMロールに適切な権限を付与しています。
datasources:
- name: Tempo
type: tempo
url: http://localhost:3200
- name: Loki
type: loki
url: http://localhost:3100
- name: Prometheus (AMP)
type: prometheus
url: https://aps-workspaces.ap-northeast-1.amazonaws.com/workspaces/xxx/
jsonData:
sigV4Auth: true
sigV4Region: ap-northeast-1
動作確認
サンプルアプリ
ALBのDNS名にブラウザでアクセスして、サンプルのアプリにアクセスします。

各ボタンで異なる特性のAPIを呼び出せます。
| ボタン | 動作 |
|---|---|
| Hello API | 即時レスポンス |
| Slow API | 2〜5秒遅延 |
| Error API | 500エラー |
| Chain API | 複数API呼び出し |




Grafana
SSMポートフォワーディングでEC2に接続し、ブラウザで http://localhost:3000 にアクセスします。
aws ssm start-session \
--target <EC2_INSTANCE_ID> \
--document-name AWS-StartPortForwardingSession \
--parameters '{"portNumber":["3000"],"localPortNumber":["3000"]}'
Starting session with SessionId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Port 3000 opened for sessionId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
Waiting for connections...
Connection accepted for session [xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx]
ログイン後、Exploreからデータソースを確認できます。


Tempoでトレース確認
Tempoを選択し、Service Nameにsample-appを入力してみると、トレースが確認できました。

Lokiでログ確認
Lokiを選択し、job = ecs-sample-appでフィルタしてみると、ログが確認できました。

AMPでメトリクス確認
Prometheus (AMP)を選択し、PromQLクエリを実行してみると、メトリクスが確認できました。

最後に
今回は、AWS上にObservability検証環境を構築してみたことを記事にしました。
この記事がどなたかの参考になれば幸いです。







