Datadog Agent が読み取り専用でも起動できるようになったので、ECS Fargate で試してみた

Datadog Agent が読み取り専用でも起動できるようになったので、ECS Fargate で試してみた

Datadog Agent が読み取り専用ルートファイルシステムに対応したので、ECS Fargate で実際に試してみました。
2026.01.26

こんにちは。オペレーション部のしいなです。

はじめに

コンテナセキュリティの観点から、読み取り専用ルートファイルシステムの有効化は今や定番の対策となっています。
AWS Security Hub の ECS.5 [1]でも推奨されているベストプラクティスです。
しかし、監視に利用する Datadog Agent をサイドカーコンテナとして構成する場合、読み取り専用では起動できないという悩ましい課題がありました。
セキュリティと監視、どちらも妥協したくない方に朗報です。
Datadog で読み取り専用ルートファイルシステムに対応したコンテナ構成がサポートされたとの情報を見つけました。[2]
公式ドキュメントでも確認ができます。
https://docs.datadoghq.com/containers/guide/readonly-root-filesystem/

そこで、今回は ECS Fargate で読み取り専用のコンテナ構成を試して、サイドカーコンテナの起動と監視が行えるか検証してみました。

結論

次のコンテナ構成を行うことで、読み取り専用ルートファイルシステムでもサイドカーコンテナ(Datadog Agent)は起動可能です。
・必要なディレクトリに書き込み可能なボリュームを提供
・init コンテナを使用してデフォルトの設定ファイルを事前にコピー
・ボリュームを init コンテナと Datadog Agent コンテナの両方にマウント

ECS Fargate 統合によるecs.fargateで始まる各種メトリクスも収集できます。

読み取り専用では本当に起動できないのか?

単純にルートファイルシステムを読み取り専用としたサイドカーコンテナ(Datadog Agent)を起動してみます。

試してみる

ECS Fargete でルートファイルシステムへの読み取り専用アクセスを定義するパラメータreadonlyRootFilesystemを有効化し、サイドカーコンテナ(Datadog Agent)を起動してみます。

タスクのステータスを見ると、すぐに停止済みとなりました。
タスク停止

ログドライバーに指定している CloudWatch Logs ロググループで Datadog Agent ログを見てみます。

[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-check-apikey.sh: executing... 
[cont-init.d] 01-check-apikey.sh: exited 0.
[cont-init.d] 50-ci.sh: executing... 
[cont-init.d] 50-ci.sh: exited 0.
[cont-init.d] 50-ecs-managed.sh: executing... 
[cont-init.d] 50-ecs-managed.sh: exited 0.
[cont-init.d] 50-ecs.sh: executing... 
ln: failed to create symbolic link '/etc/datadog-agent/datadog.yaml': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/file_handle.d/conf.yaml.default': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/cpu.d/conf.yaml.default': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/io.d/conf.yaml.default': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/memory.d/conf.yaml.default': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/network.d/conf.yaml.default': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/uptime.d/conf.yaml.default': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/disk.d/conf.yaml.default': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/load.d/conf.yaml.default': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/ntp.d/conf.yaml.default': Read-only file system
rm: cannot remove '/etc/datadog-agent/conf.d/telemetry.d/conf.yaml.default': Read-only file system
[cont-init.d] 50-ecs.sh: exited 123.
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.
[s6-finish] sending all processes the KILL signal and exiting.

50-ecs.sh[3]の処理で Datadog Agent の設定ファイルの書き込みに失敗していることがわかります。
スクリプトが異常終了し、タスクが停止されてしまうため、読み取り専用のファイルシステムでは起動できません。

書き込みが必要な理由

エージェントが書き込みが必要な理由は主に3つあります。

  • 状態管理
    エージェントは収集済みデータの位置やチェックポイントを記録して状態を管理しています。
  • プロセス間通信
    APM トレースや DogStatsD メトリクスを受信するためにソケットファイルを作成する必要があり、これがプロセス間通信に使われます。
  • 設定ファイル
    コンテナの設定を動的に生成するため、設定ファイルへの書き込みが発生します。

書き込みが必要なディレクトリ

対象のディレクトリは次のとおりです。

ディレクトリ 用途 書き込み必須
/etc/datadog-agent/ 設定ファイル はい
/opt/datadog-agent/run/ ランタイム状態の保持 はい
/var/run/datadog/ APM・DogStatsDのソケット はい
/var/log/datadog/ ログ出力 いいえ
/tmp/ 診断用の一時ファイル いいえ

読み取り専用ルートファイルシステムに対応したコンテナ構成

構成の概要

Datadog Agent をサイドカーパターンで構成します。

  • ボリューム準備
    Datadog Agent コンテナに必要な5つのボリュームを定義します。
  • 初期化処理
    init コンテナ(datadog-init)で設定ファイルをボリューム(datadog-config)にコピーします。
  • 依存関係
    init コンテナの正常終了(dependsOn: SUCCESS)後にサイドカーコンテナ(datadog-agent)を読み取り専用で起動します。
  • マウント
    各ボリュームを対応するマウントポイントにマウントします。

コンテナ構成

コンテナ名 役割 readonlyRootFilesystem
datadog-init 設定ファイルのコピー(初期化) false
datadog-agent Datadog Agent 本体(サイドカー) true

マウントポイント一覧

sourceVolume containerPath 用途
datadog-config /etc/datadog-agent Datadog Agent の設定ファイルを格納するディレクトリ
datadog-run /opt/datadog-agent/run Agentのランタイムデータ(チェックポイントなど)を保存
datadog-sockets /var/run/datadog DogStatsDやAPMトレース用のUNIXソケット通信に使用
datadog-tmp /tmp 一時ファイルの保存領域
datadog-logs /var/log/datadog Datadog Agent 自体のログファイルを出力

タスク定義

{
    "family": "datadog-agent-readonly",
    "containerDefinitions": [
        {
            "name": "datadog-init",
            "image": "public.ecr.aws/datadog/agent:latest",
            "cpu": 0,
            "portMappings": [],
            "essential": false,
            "command": [
                "sh",
                "-c",
                "cp -r /etc/datadog-agent/* /opt/datadog-agent-config/"
            ],
            "environment": [],
            "mountPoints": [
                {
                    "sourceVolume": "datadog-config",
                    "containerPath": "/opt/datadog-agent-config"
                }
            ],
            "volumesFrom": [],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/ecs/datadog-agent-readonly",
                    "awslogs-region": "ap-northeast-1",
                    "awslogs-stream-prefix": "init"
                },
                "secretOptions": []
            },
            "systemControls": []
        },
        {
            "name": "datadog-agent",
            "image": "public.ecr.aws/datadog/agent:latest",
            "cpu": 0,
            "portMappings": [
                {
                    "containerPort": 8125,
                    "hostPort": 8125,
                    "protocol": "udp"
                }
            ],
            "essential": true,
            "environment": [
                {
                    "name": "DD_SITE",
                    "value": "datadoghq.com"
                },
                {
                    "name": "ECS_FARGATE",
                    "value": "true"
                }
            ],
            "mountPoints": [
                {
                    "sourceVolume": "datadog-config",
                    "containerPath": "/etc/datadog-agent"
                },
                {
                    "sourceVolume": "datadog-run",
                    "containerPath": "/opt/datadog-agent/run"
                },
                {
                    "sourceVolume": "datadog-sockets",
                    "containerPath": "/var/run/datadog"
                },
                {
                    "sourceVolume": "datadog-tmp",
                    "containerPath": "/tmp"
                },
                {
                    "sourceVolume": "datadog-logs",
                    "containerPath": "/var/log/datadog"
                }
            ],
            "volumesFrom": [],
            "secrets": [
                {
                    "name": "DD_API_KEY",
                    "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:XXXXXXXXXXXX:secret:DdApiKeySecret-XXXXXXXX-XXXXX"
                }
            ],
            "dependsOn": [
                {
                    "containerName": "datadog-init",
                    "condition": "SUCCESS"
                }
            ],
            "readonlyRootFilesystem": true,
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "/ecs/datadog-agent-readonly",
                    "mode": "non-blocking",
                    "awslogs-create-group": "true",
                    "max-buffer-size": "25m",
                    "awslogs-region": "ap-northeast-1",
                    "awslogs-stream-prefix": "ecs"
                },
                "secretOptions": []
            },
            "systemControls": []
        }
    ],
    "taskRoleArn": "arn:aws:iam::XXXXXXXXXXXX:role/ecs-service-taskrole",
    "executionRoleArn": "arn:aws:iam::XXXXXXXXXXXX:role/ecsTaskExecutionRole",
    "networkMode": "awsvpc",
    "volumes": [
        {
            "name": "datadog-config",
            "host": {}
        },
        {
            "name": "datadog-run",
            "host": {}
        },
        {
            "name": "datadog-sockets",
            "host": {}
        },
        {
            "name": "datadog-tmp",
            "host": {}
        },
        {
            "name": "datadog-logs",
            "host": {}
        }
    ],
    "placementConstraints": [],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "1024",
    "memory": "3072"
}

やってみた

実際にボリュームを準備し、init コンテナとreadonlyRootFilesystemtrueと指定したサイドカーコンテナ(datadog-agent)を起動してみます。
タスクのステータスは実行中となりました。
起動1

コンテナのステータスを見ると、init コンテナ(datadog-init)は正常終了(exit code 0)となっています。
本体である、サイドカーコンテナ(datadog-agent)は起動中となりました。
起動2

ログドライバーに指定している CloudWatch Logs ロググループで Datadog Agent ログを見てみます。

[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-check-apikey.sh: executing... 
[cont-init.d] 01-check-apikey.sh: exited 0.
[cont-init.d] 50-ci.sh: executing... 
[cont-init.d] 50-ci.sh: exited 0.
[cont-init.d] 50-ecs-managed.sh: executing... 
[cont-init.d] 50-ecs-managed.sh: exited 0.
[cont-init.d] 50-ecs.sh: executing... 
[cont-init.d] 50-ecs.sh: exited 0.
[cont-init.d] 50-eks.sh: executing... 
[cont-init.d] 50-eks.sh: exited 0.
[cont-init.d] 50-kubernetes.sh: executing... 
[cont-init.d] 50-kubernetes.sh: exited 0.
[cont-init.d] 50-mesos.sh: executing... 
[cont-init.d] 50-mesos.sh: exited 0.
[cont-init.d] 51-docker.sh: executing... 
[cont-init.d] 51-docker.sh: exited 0.
[cont-init.d] 59-defaults.sh: executing... 
[cont-init.d] 59-defaults.sh: exited 0.
[cont-init.d] 60-network-check.sh: executing... 
[cont-init.d] 60-network-check.sh: exited 0.
[cont-init.d] 60-sysprobe-check.sh: executing... 
[cont-init.d] 60-sysprobe-check.sh: exited 0.
[cont-init.d] 89-copy-customfiles.sh: executing... 
[cont-init.d] 89-copy-customfiles.sh: exited 0.
[cont-init.d] done.
[services.d] starting services
starting security-agent
starting process-agent
starting agent
starting trace-agent
starting system-probe
[services.d] done.
2026-01-23 01:49:18 UTC | TRACE-LOADER | INFO | (pkg/util/log/setup/log.go:60 in SetupLogger) | TRACE-LOADER: using slog logger
2026-01-23 01:49:18 UTC | TRACE-LOADER | INFO | (pkg/util/log/log.go:738 in func1) | Starting to load the configuration
2026-01-23 01:49:18 UTC | TRACE-LOADER | INFO | (pkg/util/log/log.go:738 in func1) | Loading proxy settings
2026-01-23 01:49:18 UTC | TRACE-LOADER | INFO | (pkg/util/log/log.go:738 in func1) | Starting to resolve secrets
2026-01-23 01:49:18 UTC | TRACE-LOADER | INFO | (pkg/util/log/log.go:738 in func1) | Finished resolving secrets
2026-01-23 01:49:18 UTC | TRACE-LOADER | INFO | (pkg/util/log/log.go:743 in func1) | Agent did not find PodResources socket at /var/lib/kubelet/pod-resources/kubelet.sock
2026-01-23 01:49:18 UTC | TRACE-LOADER | INFO | (pkg/util/log/log.go:743 in func1) | 2 Features detected from environment: ecsfargate,ecs_orchestratorexplorer
2026-01-23 01:49:18 UTC | TRACE-LOADER | INFO | (cmd/loader/main_nix.go:85 in main) | Socket-activation for the trace-agent is disabled, running the trace-agent directly...
2026-01-23 01:49:18 UTC | TRACE-LOADER | INFO | (cmd/loader/main_nix.go:261 in execOrExit) | Starting the trace-agent...

読み取り専用のファイルシステムでも正しく起動できていることが確認できます。

メトリクス確認

読み取り専用ファイルシステムで起動したサイドカーコンテナによって ECS Fargete とコンテナ関連メトリクスが正しく取得できているか確認してみます。

ダッシュボード(Amazon Fargate Overview)
ダッシュボードでは AWS Fargate 上で稼働する Amazon ECS クラスターの主要なメトリクス(CPU使用率、メモリ使用量、I/O使用状況、ネットワーク、エフェメラルストレージなど)を確認できます。

該当タスクが表示されていることが確認できます。
Amazon-Fargate-Overview-Datadog-01-23-2026_12_01_PM

Amazon Elastic Container (ECS) エクスプローラー
エクスプローラーではすべての AWS アカウントにわたる Fargate のタスク、サービスなどの ECS コンポーネントのステータスを確認できます。

こちらでも該当タスクが表示されています。
ECS-Tasks-Datadog-01-23-2026_05_36_PM

メトリクスサマリー
Datadog に報告されたメトリクスのリストを確認できます。

ECS Fargate 統合によりecs.fargateで始まるメトリクス[4]が報告されていることがわかります。
Metrics-Summary-Datadog-01-23-2026_12_02_PM

まとめ

Datadog Agent を読み取り専用ルートファイルシステムで起動するコンテナ構成を ECS Fargate で試してみました。
init コンテナで設定ファイルを事前にコピーし、書き込みが必要な5つのディレクトリにボリュームをマウントすることで、読み取り専用でも問題なく起動することが確認できました。
ecs.fargateで始まるメトリクスも正常に収集されており、セキュリティ要件が厳しい環境でも Datadog による監視が実現できます。
コンテナセキュリティのベストプラクティスに準拠しつつ、可観測性を維持したい方はぜひ試してみてください。
本記事が参考になれば幸いです。

参考

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html

脚注
  1. https://docs.aws.amazon.com/securityhub/latest/userguide/ecs-controls.html#ecs-5 ↩︎

  2. https://github.com/DataDog/datadog-agent/issues/15127 ↩︎

  3. https://github.com/DataDog/datadog-agent/blob/main/Dockerfiles/agent/cont-init.d/50-ecs.sh ↩︎

  4. https://docs.datadoghq.com/integrations/aws-fargate/?tab=webui#metrics ↩︎

この記事をシェアする

FacebookHatena blogX

関連記事