DatadogでECSを監視する

AWSのECSで動かしているコンテナを、Datadogで監視する方法です。

こちらは、公式のマニュアル。

Amazon Elastic Container Service (ECS)

こちらは、公式の紹介ブログ。

Monitoring ECS with Datadog | Datadog

前提

  • ECS Container Instanceが存在
  • Datadogには、AWSのIntegrationをインストール済

作業

監視する方法ですが、DockerHubにて公開しているdatadog-agentのコンテナイメージを、ECS上で動かせということらしいです。

タスク定義作成

タスク定義作成用のjsonがDatadogマニュアルで公開されており参考になります。

https://docs.datadoghq.com/json/datadog-agent-ecs.json

下記のjsonのタスク定義にて、以下のデータを収集できるようになります。

  • Data Collection
    • ECSで用意されているメトリクスを収集してきてくれる
  • Process Collection
    • コンテナ上で動作しているプロセス一覧を収集してきてくれる

環境変数 DD_API_KEY に、利用するDatadogのAPI KEYを登録しておきます。

{
  "containerDefinitions": [
    {
      "name": "datadog-agent",
      "image": "datadog/agent:latest",
      "cpu": 10,
      "memory": 256,
      "essential": true,
      "mountPoints": [
        {
          "containerPath": "/var/run/docker.sock",
          "sourceVolume": "docker_sock",
          "readOnly": true
        },
        {
          "containerPath": "/host/sys/fs/cgroup",
          "sourceVolume": "cgroup",
          "readOnly": true
        },
        {
          "containerPath": "/host/proc",
          "sourceVolume": "proc",
          "readOnly": true
        },
        {
          "containerPath": "/etc/passwd",
          "sourceVolume": "passwd",
          "readOnly": true
        }
      ],
      "environment": [
        {
          "name": "DD_API_KEY",
          "value": "<APIKEY>"
        },
        {
          "name": "DD_SITE",
          "value": "datadoghq.com"
        },
        {
          "name": "DD_PROCESS_AGENT_ENABLED",
          "value": "true"
        }
      ]
    }
  ],
  "volumes": [
    {
      "host": {
        "sourcePath": "/var/run/docker.sock"
      },
      "name": "docker_sock"
    },
    {
      "host": {
        "sourcePath": "/proc/"
      },
      "name": "proc"
    },
    {
      "host": {
        "sourcePath": "/sys/fs/cgroup/"
      },
      "name": "cgroup"
    },
    {
      "host": {
        "sourcePath": "/etc/passwd"
      },
      "name": "passwd"
    }
  ],
  "family": "datadog-agent-task"
}

上記のjsonでは Log Collection の設定は実施していません。ECSでもログをCloudwatch Logsに連携できるようになったので、CloudwarhcLogsのログをDatadogで連携することで、監視を実現します。

IAMユーザの用意

ECS Task Roleで、以下のIAMポリシーを許可する必要があります。

  • ecs:ListClusters
  • ecs:ListContainerInstances
  • ecs:DescribeContainerInstances
サービス定義作成

作成したタスク定義を、各Container Instance上で起動させます。サービスタイプを DAEMON とすることで、各Container Instance上で1台ずつ動いてくれるようになります。

以上の作業を実施することで、Datadog上に各種メトリクスとコンテナ上のプロセス情報を収集できるようになります。

CloudFormation

上記をまとめて実行してくれるCloudFormationを置いておきます。

cloudformation/ecs-datadog-agent at master · goodbyegangster/cloudformation · GitHub

参考

そもそも、Datadog Agentはどうやって他のContainerの情報を収集しているのか分からなかったので、調べてみました。

Datadog Agentのタスク定義では、以下のECS Container Instance(Docker Host)上のパスをマウントしているので、それぞれがどういった役割を持っているのか調べてみます。

  • DataCollection
    • /var/run/docker.sock
    • /sys/fs/cgroup/
    • /proc/
  • ProcessCollection
    • /etc/passwd

/var/run/docker.sock

ファイル名からして、Docker用に用意されているソケットであることは分かりますね。恐らくこのソケットで用意されたAPI経由で、色々な情報をDatadog Agentが拾ってきているのだろうと予想できます。

Docker-machineにsshログインして、実際にdocker.sockのAPIを叩いてみると、情報を取得できます。docker.sockのソケットの裏側では、HTTPサーバが待っているそうなので、こんな感じでアクセスできます。

docker@default:~$ curl --unix-socket /var/run/docker.sock http://docker/containers/json
[
    {
        "Id": "f6975b30286b3af66f4f8f97dc90a37d3dc6be22aae6a04c87c0936b247ebe65",
        "Names": [
            "/test"
        ],
        "Image": "redis:latest",
    (略)
    }
]

/sys/fs/cgroup/

そもそもこいつは、

cgroupは2006年9月にGoogleのエンジニアによって最初のパッチが投稿され,2.6.24カーネルで最初のマージがなされた機能です。

cgroupは"Control Group"の略です。プロセスをグループ化して,そのグループ内に存在するプロセスに対して共通の管理を行うために使います。たとえば,ホストOSが持つCPUやメモリなどのリソースに対して,グループごとに制限をかけることができます。

コンテナはプロセスを隔離空間に入れることによって作成しますので,コンテナ内に入っているプロセスの集合に対してまとめてリソース制限をかける必要のある場面は多く,このような場面にcgroupが使えます。cgroupを使って,あるコンテナがホストOSの持つ有限なリソースを使いつくして,ホストOS上のプロセスや他のコンテナに影響を与えないようにできます。

第3回 Linuxカーネルのコンテナ機能[2] ─cgroupとは?(その1):LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術|gihyo.jp … 技術評論社

実際にdocker-machine上のcgroup配下を調べてみると、コンテナ単位でcpuやmemoryのスタッツ情報を拾ってこれます。

docker@default:~$ cat /sys/fs/cgroup/memory/docker/f6975b30286b3af66f4f8f97dc90a37d3dc6be22aae6a04c87c0936b247ebe65/memory.stat
cache 7368704
rss 1146880
rss_huge 0
shmem 0
mapped_file 3223552
dirty 0
writeback 0
swap 0
pgpgin 4692
pgpgout 2613
pgfault 1726
pgmajfault 61
inactive_anon 0
active_anon 1146880
inactive_file 4612096
active_file 2756608
unevictable 0
hierarchical_memory_limit 9223372036854771712
hierarchical_memsw_limit 9223372036854771712
total_cache 7368704
total_rss 1146880
total_rss_huge 0
total_shmem 0
total_mapped_file 3223552
total_dirty 0
total_writeback 0
total_swap 0
total_pgpgin 4692
total_pgpgout 2613
total_pgfault 1726
total_pgmajfault 61
total_inactive_anon 0
total_active_anon 1146880
total_inactive_file 4612096
total_active_file 2756608
total_unevictable 0

/proc/

DockerとはコンテナにてLinuxカーネルを共有する技術である、という事なので、Docker-machine上の /proc を見に行けば、そこにはコンテナ上のリソース情報があり、そこから何でも拾ってこれるよね、という話だと思っています。

コンテナのPIDは、以下のコマンドにて確認できます。

docker@default:~$ docker ps -q | xargs -n1 docker top
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
999                 3093                3072                0                   22:25               ?                   00:00:04            redis-server *:6379

このPIDディレクトリ配下のstatを見に行くと、該当コンテナでのプロセス情報を取得できます。

docker@default:~$ cat /proc/3093/stat
3093 (redis-server) S 3072 3093 3093 0 -1 4210944 1197 313 44 17 203 220 0 0 20 0 4 0 531327 51494912 1039 18446744073709551615 1 1 0 0 0 0 0 4097 17610 0 0 0 17 0 0 0 5 0 0 0 0 0 0 0 0 0 0

/etc/passwd

OSのパスワードファイル。DatadogのProcessCollectionにて、どうしてパスワードファイルを参照する必要あるのか、Datadog Agentのソースコード見てみないと予想もできず、僕には分からなかったです。