Datadog で CoreOS をモニタリングする


## はじめに

<img src="https://qiita-image-store.s3.amazonaws.com/0/20833/faf7e10f-3fc6-edd3-5eb8-9e98b1647ee7.png" width="200px">

CoreOS 上で dd-agent を動かそうとした場合、 yum や apt といった通常のパッケージ管理ツールを使って CoreOS マシンにインストールすることはできない。アプリケーションや各種サービスを全てコンテナで扱う、いわゆる "docker way" で行う必要がある（そうした方が良いとも思う）。なので、dd-agent もそれ専用のコンテナを起動し、 `--privileged` オプションを付けホスト情報へアクセス可能にしてあげることで CoreOS をモニタリングする。

<img src="https://www.datadoghq.com/wp-content/uploads/2014/06/DockerizeImage2.png" width=350px>

## CoreOS 上に Datadog をインストールする
### コマンドラインからインストールする
CoreOS クラスタ全体で Datadog の API キーを共有するため、etcd にセットしておく

```bash
$ etcdctl set /ddapikey c0re0s070120131499294110c0re0sdd
c0re0s070120131499294110c0re0sdd
```

dd-agent コンテナを run

```bash
$ docker run \
  -d \
  --privileged \
  --name dd-agent \
  -h `hostname` \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /proc/mounts:/host/proc/mounts:ro \
  -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro \
  -e API_KEY=`etcdctl get /ddapikey` \
  datadog/docker-dd-agent
```

しばらくすると、Datadog の方で CoreOS マシンが認識され、

![Infrastructure_Overview___Datadog.png](https://qiita-image-store.s3.amazonaws.com/0/20833/8a4caf25-a0fe-9a2f-d926-b72e1a7bcba6.png "Infrastructure_Overview___Datadog.png")


しばらくすると、各種メトリクスを見る事ができるようになる

![core-01___Datadog.png](https://qiita-image-store.s3.amazonaws.com/0/20833/b586274d-6245-e05a-ffca-aa39a40e5384.png "core-01___Datadog.png")


### systemd からインストールする
CoreOS クラスタ全体で Datadog の API キーを共有するため、etcd にセットしておく（

```bash
$ etcdctl set /ddapikey c0re0s070120131499294110c0re0sdd
c0re0s070120131499294110c0re0sdd
```

`/etc/systemd/system/dd-agent.service` として dd-agent Unit を作成。

```bash
$ sudo vi /etc/systemd/system/dd-agent.service
```

```yml
[Unit]
Description=Datadog Agent
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill dd-agent
ExecStartPre=-/usr/bin/docker rm dd-agent
ExecStartPre=/usr/bin/docker pull datadog/docker-dd-agent
ExecStartPre=/bin/sh -c "export DATADOG_API_KEY=$(/usr/bin/etcdctl get /ddapikey)"
ExecStart=/usr/bin/docker run --privileged --name dd-agent -h %H -v /var/run/docker.sock:/var/run/docker.sock -v /proc/mounts:/host/proc/mounts:ro -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro -e API_KEY=$DATADOG_API_KEY datadog/docker-dd-agent

[Install]
WantedBy=multi-user.target
```

ポイントとしては `ExecStart` は `-e API_KEY=$(/usr/bin/etcdctl get /ddapikey)` のようにコマンドを埋め込めないので、一度 etcd から値を環境変数に入れ、それを使って `docker run` している。さらに環境変数に入れる `ExecStart` でも同じく `DATADOG_API_KEY=$(/usr/bin/etcdctl get /ddapikey)` のようには書けないので、

```
ExecStartPre=/bin/sh -c "export DATADOG_API_KEY=$(/usr/bin/etcdctl get /ddapikey)"
```

としている（ただ、`ExecStart` が `$(command)` のできないようにしてるのには意図があるだろうからこの方法は良くないのかもしれない）

Unit を enable にして

```bash
$  sudo systemctl enable /etc/systemd/system/dd-agent.service
Created symlink from /etc/systemd/system/multi-user.target.wants/dd-agent.service to /etc/systemd/system/dd-agent.service.
```

dd-agent 起動

```bash
$ sudo systemctl start dd-agent.service
```

起動を確認

```bash
$ docker ps | grep dd-agent
5289f15b79ae        datadog/docker-dd-agent:latest   /usr/local/bin/run-d   10 minutes ago      Up 10 minutes       8125/udp            dd-agent
```

```bash
$ systemctl status dd-agent.service
● dd-agent.service - Datadog Agent
   Loaded: loaded (/etc/systemd/system/dd-agent.service; enabled)
   Active: inactive (dead) since Thu 2014-09-04 18:06:30 JST; 11min ago
  Process: 2315 ExecStart=/usr/bin/docker run -d --privileged --name dd-agent -h %H -v /var/run/docker.sock:/var/run/docker.sock -v /proc/mounts:/host/proc/mounts:ro -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro -e API_KEY=$DATADOG_API_KEY datadog/docker-dd-agent (code=exited, status=0/SUCCESS)
  Process: 2305 ExecStartPre=/bin/sh -c export DATADOG_API_KEY=$(/usr/bin/etcdctl get /ddapikey) (code=exited, status=0/SUCCESS)
  Process: 2294 ExecStartPre=/usr/bin/docker pull datadog/docker-dd-agent (code=exited, status=0/SUCCESS)
  Process: 2283 ExecStartPre=/usr/bin/docker rm dd-agent (code=exited, status=1/FAILURE)
  Process: 2275 ExecStartPre=/usr/bin/docker kill dd-agent (code=exited, status=1/FAILURE)
 Main PID: 2315 (code=exited, status=0/SUCCESS)

Sep 04 18:06:26 core-01 docker[2275]: Error response from daemon: No such container: dd-agent
Sep 04 18:06:26 core-01 docker[2275]: 2014/09/04 18:06:26 Error: failed to kill one or more containers
Sep 04 18:06:26 core-01 docker[2283]: Error response from daemon: No such container: dd-agent
Sep 04 18:06:26 core-01 docker[2283]: 2014/09/04 18:06:26 Error: failed to remove one or more containers
Sep 04 18:06:26 core-01 docker[2294]: Pulling repository datadog/docker-dd-agent
Sep 04 18:06:30 core-01 systemd[1]: Started Datadog Agent.
Sep 04 18:06:30 core-01 docker[2315]: 5289f15b79aebe76d1a623c5464b19811606cb72c714949d4357c99535fbb1d1
```

### Cloud-Config からインストールする
cloud-config の dd-agent に関連する部分だけ記載

```yaml
#cloud-config

coreos:
  units:
    - name: docker-tcp.socket
      command: start
      enable: true
      content: |
        [Unit]
        Description=Docker Socket for the API

        [Socket]
        ListenStream=2375
        Service=docker.service
        BindIPv6Only=both

        [Install]
        WantedBy=sockets.target
    - name: dd-agent.service
      command: start
      enable: true
      content: |
        [Unit]
        Description=Datadog Agent
        After=docker.service
        Requires=docker.service

        [Service]
        TimeoutStartSec=0
        ExecStartPre=-/usr/bin/docker kill dd-agent
        ExecStartPre=-/usr/bin/docker rm dd-agent
        ExecStartPre=/usr/bin/docker pull datadog/docker-dd-agent
        ExecStart=/usr/bin/docker run --privileged --name dd-agent -h %H -v /var/run/docker.sock:/var/run/docker.sock -v /proc/mounts:/host/proc/mounts:ro -v /sys/fs/cgroup/:/host/sys/fs/cgroup:ro -e API_KEY=c0re0s070120131499294110c0re0sdd datadog/docker-dd-agent

        [Install]
        WantedBy=multi-user.target
```

dd-agent は docker が利用可能になってから起動させるように書いてある。
この cloud-init を用いて provisioning すると自動で dd-agent コンテナが起動する。
しかし、マシン起動直後に `$ docker ps` しても dd-agent は確認出来ない、これは systemd が全 unit の dependency を解決して順番に service を実行しているためで少しまてば dd-agent コンテナが起動してくる。`systemctl` を使えば pull 中とか経過も確認できる。

```bash
$ systemctl status dd-agent.service
● dd-agent.service - Datadog Agent
   Loaded: loaded (/etc/systemd/system/dd-agent.service; enabled)
   Active: activating (start-pre) since Fri 2014-09-05 14:06:11 UTC; 44s ago
  Process: 914 ExecStartPre=/usr/bin/docker rm dd-agent (code=exited, status=1/FAILURE)
  Process: 857 ExecStartPre=/usr/bin/docker kill dd-agent (code=exited, status=1/FAILURE)
  Control: 923 (docker)
   CGroup: /system.slice/dd-agent.service
           └─control
             └─923 /usr/bin/docker pull datadog/docker-dd-agent

Sep 05 14:06:11 core-02 systemd[1]: Starting Datadog Agent...
Sep 05 14:06:12 core-02 docker[857]: Error response from daemon: No such container: dd-agent
Sep 05 14:06:12 core-02 docker[857]: 2014/09/05 14:06:12 Error: failed to kill one or more containers
Sep 05 14:06:12 core-02 docker[914]: Error response from daemon: No such container: dd-agent
Sep 05 14:06:12 core-02 docker[914]: 2014/09/05 14:06:12 Error: failed to remove one or more containers
Sep 05 14:06:12 core-02 docker[923]: Pulling repository datadog/docker-dd-agent
```

## スクリーンショット
![](https://www.datadoghq.com/wp-content/uploads/2014/08/CoreOSDashboard.png)

このダッシュボードは予め用意されたものではなくてカスタムダッシュボードでこういうのが作れる。特に [Top Lists](https://www.datadoghq.com/2014/08/easy-ranking-new-top-lists/) ウィジェットが便利

## メモと感想
### 有料の Datadog を使う事に関して

パッケージを直接インストールできない、CoreOS 上の Docker コンテナの監視をどうするかという事に関して Datadog は非常に良い選択肢だと思っている。お金はかかるけれど、OSS のモニタリングツールと可視化ツールを組み合わせてもここまでのものは用意できない...と思ったのが正直なところ。Docker コンテナについても datadog で非常に気持ちよくモニタリングできているので、合わせて別の記事を投稿しようと思う。

### unifile 内での etcd の値の取得方法はどうしたらいいか

この記事の本筋とは反れるかもだけど、etcd に set しておいた value を systemd の unitfile で受け取る正しい（またはスマートな）やり方ないのかな。`EnvironmentFile` を使うって手もある、etcd から環境変数ファイルを作成するための unit を作って、それを依存関係で指定しておくとか。

### systemd を使って dd-agent を自動起動する場合予め pull した CoreOS イメージを使うかどうか

CoreOS クラスタの増強時に dd-agent コンテナの pull の時間を省こうと思うと、既に pull 済みの CoreOS イメージ (AMI とか）を用いる方法がある。しかし、CoreOS マシンをステートレス（という言い方がこの場合にふさわしいかわからないが）な状態にしておこうと思うとカスタマイズしたイメージは作らない方がいい。12Factor App のようにインフラ側もステートレスに出来るならしていおいた方が後でとにかく色々と使い回しやすいんじゃないかと思っている。実際に本番環境には dd-agent を入れるけどお金節約のためステージング環境には入れない、みたいな場合に CoreOS AMI に dd-agent を入れてしまうとステージング環境で使えなくなる、ということがあった。初期起動を犠牲に使い回しやすさを取る場合、S3 に置いたイメージを EC2 上の CoreOS から pull すると 1GB のイメージで 40 秒程度で終わるが、複数のイメージを自動起動する場合に 40s * 3 = 120s 。`X-ConditionMachineMetadata` を使って環境によって dd-agent 起動しないっていう方法もありそう。

### コンテナ名は dd-agent でいいのか、クラスタ全体で一意にしなくていいか

わかりやすさでいうと dd-agent がシンプルでいいよなー。同じコンテナ名だけど特定のコンテナにだけ負荷がかかったりで異常が出たりとかの場合に一意にしておくとよい。どちらがいいのか。

## REF

* [Monitor CoreOS at scale with Datadog - Datadog Blog](https://www.datadoghq.com/2014/08/monitor-coreos-scale-datadog/)