mackerel-agent on kubernetesでホスト名をいい感じに設定する

kubernetesでのモニタリングはprometheusが定番と思いますが、grafana等を自前で用意する必要がある為、運用負荷となると思います。このあたりを楽したいので私はmackerelを利用しています。

k8s環境で各ノードのメトリクスをmackerelに集約するためには、mackerel-agentをDaemonSetで起動しました。DaemonSetで起動するまでは良かったのですが、ホスト名の自由がなく、使いづらかったので共有したいと思います。

## ホスト名がDaemonSetのnameに連動する
DaemonSetでmackerel-agentをdeployするk8s manifestを単純に作成すると、以下のようになります。

```mackerel.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: mackerel-agent
  namespace: kube-system
  labels:
    app: mackerel-agent
spec:
  tolerations: # masterにもmackerel-agentをdeployする設定
  - operator: Exists
    effect: NoSchedule
  - operator: Exists
    effect: NoExecute
  - operator: Exists
  selector:
    matchLabels:
      name: mackerel-agent
  template:
    metadata:
      labels:
        name: mackerel-agent
    spec:
      containers:
      - name: mackerel-agent
        image: mackerel/mackerel-agent:latest
...
```

このmanifestでDaemonSetを起動して、podを確認します。

```
$ kubectl get pods -n kube-system
NAME                                                                       READY     STATUS    RESTARTS   AGE
mackerel-agent-jqp9n                                                       1/1       Running   0          5s
mackerel-agent-kqf7d                                                       1/1       Running   0          5s
mackerel-agent-xcqdc                                                       1/1       Running   0          5s
...
```

上記の通り、pod名は、DaemonSetのnameをprefixとした `mackerel-agent-*` という名前になっていると思います。
そしてこのとき、mackerelでHostsを確認すると、HOST NAMEにpod名が付与されていることが確認できます。

![Screen Shot 2018-06-04 at 11.24.55.png](https://qiita-image-store.s3.amazonaws.com/0/42709/a5dbc5d7-1bb9-cd4e-7b20-f9e02c17a525.png)

これでは、どのホストのことなのかサッパリで、運用する上で不便だと思います。
ただ、ホスト名を設定するために、DaemonSetのメタデータであるnameを変えるのはちょっと。。

## hostnameをつける
manifestでhostnameをつけることができます。

```mackerel.yaml
...
spec:
  tolerations: # masterにもmackerel-agentをdeployする設定
  - operator: Exists
    effect: NoSchedule
  - operator: Exists
    effect: NoExecute
  - operator: Exists
  selector:
    matchLabels:
      name: mackerel-agent
  template:
    metadata:
      labels:
        name: mackerel-agent
    spec:
      hostname: hogehoge # **ホスト名をつける**
      containers:
      - name: mackerel-agent
        image: mackerel/mackerel-agent:latest
...
```

このときpod名の命名規則は変更ありません。

```
$ kubectl -n kube-system get pods
NAME                                                                       READY     STATUS    RESTARTS   AGE
mackerel-agent-5pmv5                                                       1/1       Running   0          8s
mackerel-agent-hwgn6                                                       1/1       Running   0          8s
mackerel-agent-shcnv                                                       1/1       Running   0          8s
```

hostnameを与えた場合でmackerelをみると、ホスト名が設定されています。

![Screen Shot 2018-06-04 at 11.39.27.png](https://qiita-image-store.s3.amazonaws.com/0/42709/e66afc39-477b-c6e6-e5a2-15eb33df01cb.png)

hostnameを使えば任意のホスト名を付与できました。

## テンプレート化する
hostnameを使えば、任意のホスト名を付与できることが分かったのですが、stagingやproductionといった異なる環境で、mackerelのservice/roleを使いまわす場合に `hogehoge-production`, `hogehoge-staging` みたいなホスト名にしたいです。

このため、helmを使ってテンプレート化し、パラメータとして与えるようにします。
(このためだけにhelmを使うのがなんとなく嫌ですが、manifestでは変数をかけないので。。）


```mackerel-agent/templates/mackerel-agent.yaml
...
      hostname: hogehoge-{{ .Values.env }}
...
```

`helm template` でmanifestを作成

```
$ helm template --set env=staging mackerel-agent > mackerel-agent.yaml
```

出力されたmanifestでは `hostname: hogehoge-staging` となっています。


## 更にやりたいこと
ホスト名をもっと色々表示してほしいので整理します。

1. service名をprefixとしてつけたい（できた）
    - hogehoge-*
2. 環境名(production/staging)をホスト名に含めたい (できた） 
    - 環境間はservice/roleを共有したい
3. masterかnodeかをホスト名に含めたい (できてない）
    - kubernetesのロールをホスト名で見分けたい
4. pod毎のsuffixをつけてほしい (できてない)
    - どのnodeなのかをホスト名に付与したい

1~4を総合すると、 `hogehoge-production-master-<node名>` みたいなホスト名にしたいです。

今回できてない3・4は、deploy時に確定する情報なので、manifestやhelmで頑張るのは厳しそうです。
こうなってくると、deploy後にホスト名を設定するように変更して、mkrするscriptを書くしかないかもしれません。

## mackerelへの期待
mackerelとkubectlで得られる情報を付き合わせるの運用はやめたいです。mackerel-agentからkube-apiserver叩いて勝手にノードの情報とってきてくれないかな？(あとslack通知にもその情報出したい）