mackerel-agentをkubernetes上で動かす

# はじめに

この記事は、**Mackerel Advent Calendar 2016 16日目** の記事です。
kubernetesで mackerel-agent を動かしたときのことを書きます。
kubernetesのメトリクスなどもどうやって取得するかを書けるといいんですが、そこまでできてません。今回は単純にmackerel-agentをkubernetes上で動かす方法だけです。

# kubernetes

kubernetes はもともとgoogleが自社内でコンテナを運用していて、そこで得たコンテナ管理のノウハウなどをオープンソースにしたものが元になっています。今回の主題ではないので詳細には立ち入りません。たくさん参考になる記事がありますのでそちらを参照してください。

# kubernetes 上で mackerel-agentを動かす

## Podでの起動

kubernetesでのコンテナの管理は、Podといわれる幾つかのコンテナをグループ化したもの(Pod内に1コンテナでも良い)で管理します。このPodの単位で起動、停止などを行います。Podの特徴はいくつかあり、例えばPod内のコンテナは同一ホストにデプロイされる(Pod単位でホストにデプロイされる)などがあります。今回ホスト上でmackerel-agentを動かしたくはないので、Podとしてmackerel-agentを動かしたいと思います。

Podの設定ファイルは以下のようになります。

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: mackerel-agent
spec:
  containers:
    - name: mackerel-agent
      image: mackerel/mackerel-agent:latest
      imagePullPolicy: Always
      env:
      - name: apikey
        value: <your api key>
      - name: opts
        value: -role=<Service>:<Role>
      - name: enable_docker_plugin
        value: "1"
      lifecycle:
        preStop:
          exec:
            command: ["/usr/bin/mackerel-agent", "retire", "-force"]
      volumeMounts:
      - name: docker-sock
        mountPath: /var/run/docker.sock
      - name: mackerel-id
        mountPath: /var/lib/mackerel-agent/
  volumes:
    - name: docker-sock
      hostPath:
        path: /var/run/docker.sock
    - name: mackerel-id
      hostPath:
        path: /var/lib/mackerel-agent/
```

`apikey`, `Service`, `Role`は適切に設定してください。また、`auto_retirement`を設定する代わりにkubernetesの[lifecycle hooks](http://kubernetes.io/docs/user-guide/pods/#termination-of-pods)を利用しています。これは、Pod停止時には自動で退役してほしいのと`auto_retirement`だとうまく退役できないことがあったためです。ただ、これも問題があってPodが起動しているNode(インスタンス)が停止するような状況(kubeletがPodのlifecycle hookを処理する前にterm/killされてしまう)などではうまく機能しません。不要な方は当該行を削除してください。


上記のyamlファイルをローカルに保存し、kuberctlで実行することで mackerel-agentを起動できます。

```shell-session
$ kubectl create -f <yamlファイル名> 
```
mackerel-agentを止める時は以下のようにします。

```shell-session
$ kubectl delete pod mackerel-agent
```

ホストとmackerel-agent内のdocker API versionがズレているとホスト情報は取れてもコンテナ情報が取れないことがあります。また、同一ホスト上で多数のコンテナが動いているとコンテナ情報が取れないことがあるので要注意です。これらは今後の改善に期待したいと思います。

問題がなければ、mackerelの画面上にyamlで指定したService,Roleでホストが増えているはずです。

## DaemonSetでの起動

監視ツールのようなコンテナをクラスタ上全台で動かすためには、kubernetesの[DaemonSet](http://kubernetes.io/docs/admin/daemons/)の仕組みを使うのが簡単です。

mackerel-agentをDaemonSetで動かす設定ファイルは以下のようになります。

```yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  labels:
    name: mackerel-agent
  name: mackerel-agent
spec:
  template:
    metadata:
      labels:
        app: mackerel-agent
    spec:
      containers:
        - name: mackerel-agent
          image: mackerel/mackerel-agent:latest
          imagePullPolicy: Always
          env:
          - name: apikey
            value: <your api key>
          - name: opts
            value: -role=<Service>:<Role>
          - name: enable_docker_plugin
            value: "1"
          lifecycle:
            preStop:
              exec:
                command: ["/usr/bin/mackerel-agent", "retire", "-force"]
          volumeMounts:
          - name: docker-sock
            mountPath: /var/run/docker.sock
          - name: mackerel-id
            mountPath: /var/lib/mackerel-agent/
      volumes:
        - name: docker-sock
          hostPath:
            path: /var/run/docker.sock
        - name: mackerel-id
          hostPath:
            path: /var/lib/mackerel-agent/
```

Podのときと同じように、`apikey`, `Service`, `Role`は適切に設定してください。
上記のyamlファイルをローカルに保存し、kubectlで実行することで mackerel-agentを起動できます。

```shell-session
$ kubectl create -f <yamlファイル名> 
```
DaemonSetでのmackerel-agentを止める時は以下のようにします。

```shell-session
$ kubectl delete ds mackerel-agent
```

## 追加でmackerel-agent-pluginを有効にしたい時

追加でmackerel-agent-pluginを有効にしたい時はどうすればいいでしょうか。できればコンテナ内で完結させて、ホスト上に設定ファイルを展開したくありません。これをしようとすると、設定ファイルを予めコピーしたコンテナイメージを作成することになると思います。

例えば、以下のようなDockerfileを書いてカスタマイズしたコンテナイメージを作成します。

```text:Dockerfile
FROM mackerel/mackerel-agent:latest

COPY conf.d/* /etc/mackerel-agent/conf.d/
```

次に、追加した設定ファイルを読み込むように前述の設定を一部変更します。

```yaml
(snip)
          image: <カスタマイズしたイメージ>
          env:
          - name: apikey
            value: <your api key>
          - name: opts
            value: -role=<Service>:<Role>
          - name: enable_docker_plugin
            value: "1"
          - name: include
            value: /etc/mackerel-agent/conf.d/*.conf
(snip)
```

このようにすることで、ホスト上に設定ファイルを展開しなくても追加の設定ファイルを読み込ませることができます。異なる設定のmackerel-agentを展開したい時は、異なる設定をコピーしたイメージそれぞれをkubernetesのPod Selector機能を利用して展開することで可能です。

# おわりに

Kubernetes上でmackerel-agentを動かす方法を紹介しました。
dockerやkubernetesを使っているけど、ホスト上でmackerel-agent動かしているみたいな方に参考になれば幸いです。