StackDriverでKubernetes(GKE)の細かいメトリクスが見たかった

GKEのモニタリング、アラートにStackDriverがどの程度使いやすいか検証する為に奮闘中のメモ

# 前提

- kuberntes: 1.10.2-gke.3
- GKEクラスタの設定で `Stackdriver Monitoring` は `有効` になっている状態

# StackDriverでGKEのメトリクスを見る

まずはデフォルトの状態でどのくらい見れるのか見てみます

- `Resources -> Metrics Exploer` を開く
- `ResoruceType: GKE Container` を選択
- 選択できるメトリクスを見てみる

https://cloud.google.com/monitoring/api/metrics_gcp#gcp-container
↑ここに書いてあるとおりです。

<img width="1126" alt="Metrics_Explorer-1.png" src="https://qiita-image-store.s3.amazonaws.com/0/9575/bb64a928-3966-5dc8-cbf5-a695072b8998.png">


- CPU usage
- CPU utilization
- Disk capacity
- Disk usage
- Log bytes
- Log entries
- Log-bases metric errors
- Memory limit
- Memory usage
- Page faults
- Reserved cores

こんな感じですね。

# デフォルトのDashboard(Overview？)を見てみる

Kubernetes Engineのnodeやpodの情報を見ることができます

- `Resources -> Kubernetes Engine` を選択
- `Inventory` から対象のクラスタを選択

<img width="1680" alt="SrackDriver-GKE-Overview.png" src="https://qiita-image-store.s3.amazonaws.com/0/9575/6c6c7568-9113-1c48-a333-19562581c2b8.png">

- ただ、これ、なぜか他のクラスタにデプロイされてるpodの情報も表示される...
- カスタマイズできない(Filterはできる)
- 微妙に使いづらい

うーん :thinking: 

# 普段モニタリングしたいメトリクス

HPAでオートスケールさせているdeploymentがあったりするので
とりあえずライトなところで

- 各pod毎のCPU使用率
- deploymentでグルーピングしたCPU使用率
- オートスケールで変化したpod数の推移
- availableなpodの数
    - 起動に失敗してpodが立ち上がらないなどの障害をアラートする為

などはモニタリングしたいところです。

# カスタムメトリクス

カスタムメトリクスを自分でStackDriverにreportすれば、モニタリングできそうです。

https://cloud.google.com/monitoring/custom-metrics/

> Before you begin
> Custom metrics are a paid feature of Monitoring and there could be costs for your custom metrics. For > more information, see Stackdriver Pricing. You can try out this and other Stackdriver premium features free for 30 days, when you create a new Stackdriver account.

---

> あなたが始める前に
> カスタムメトリックは監視の有償機能であり、カスタムメトリックにはコストがかかる可能性があります。 詳細については、スタックドライバの価格設定を参照してください。 このStackdriverプレミアム機能は、新しいStackdriverアカウントを作成するときに30日間無料でお試しいただけます。

とのことです。
とりあえず、試用期間があるようなので、UPGRADEしておきます。

# kube-state-metricsを使ってみる

自前でメトリクス収集を実装するのはさすがに面倒です...
そこで
https://github.com/kubernetes/kube-state-metrics
を使ってみることにしました。

# kube-state-metricsをdeployする

```kube-state-metrics.yml
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kube-state-metrics
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1 
# kubernetes versions before 1.8.0 should use rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: kube-state-metrics
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: kube-state-metrics
  namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: kube-system
  name: kube-state-metrics
  labels:
    app: kube-state-metrics
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kube-state-metrics
  template:
    metadata:
      labels:
        app: kube-state-metrics
    spec:
      serviceAccountName: kube-state-metrics
      hostNetwork: true
      containers:
      - name: kube-state-metrics
        image: gcr.io/google_containers/kube-state-metrics:v1.3.1
        ports:
          - name: http-metrics
            containerPort: 8080
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          timeoutSeconds: 5
        resources:
          requests:
            memory: 200Mi
            cpu: 100m
          limits:
            memory: 300Mi
            cpu: 200m
      - name: prometheus-to-sd
        image: gcr.io/google-containers/prometheus-to-sd:v0.2.6
        ports:
          - name: profiler
            containerPort: 6060
        command:
          - /monitor
          - --stackdriver-prefix=custom.googleapis.com
          - --source=kube-state-metrics:http://localhost:8080
          - --pod-id=$(POD_NAME)
          - --namespace-id=$(POD_NAMESPACE)
        env:
          - name: GOOGLE_APPLICATION_CREDENTIALS
            value: /secrets/credentials.json
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace

```

- `ServiceAccount`を作成
- `ClusterRoleBinding` で作成したServiceAccountをClusterRoleに紐付ける
    - 本当はもっと細かく権限設定したClusterRoleを用意すべきかと思いますが、検証環境なのでてっとりばやくcluster-adminを使いました
- `kube-state-metricsのDeployment`を作成
    - 先に作成したServiceAccountをつける
    - StackDriverにメトリクスを送信するcontainerとして、`prometeus-to-sd` をsidecar containerとして起動しておく
    - [kube-state-metrics](https://console.cloud.google.com/gcr/images/google-containers/GLOBAL/kube-state-metrics?gcrImageListsize=50)
    - [prometeus-to-sd](https://console.cloud.google.com/gcr/images/google-containers/GLOBAL/prometheus-to-sd?gcrImageListsize=50)
- メトリクス収集なので、 `kube-system` のnamespaceに入れることにしました

`kubectl apply -f kube-state-metrics.yml`
でデプロイします。

# StackDriverで見てみる

- `Resource -> Metrics Exploler` を選択
- `Resource type: GKE Container` を選択

<img width="1167" alt="Metrics_Explorer-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/9575/a44d6a56-9320-ba3f-b45a-876b11cc3c25.png">

```
Metric: custom.googleapis.com/kube-state-metrics/kube_deployment_status_replicas_available
Description: The number of available replicas per deployment.
Resource type: gke_container
Unit: number     Kind: Gauge     Value type: Int64
```
など、モニタリングできるメトリクスが増えました。

<img width="1392" alt="Metrics_Explorer-3.png" src="https://qiita-image-store.s3.amazonaws.com/0/9575/ab9d5c1c-6165-fac8-ffa3-9f5d2f1c55d5.png">

試用期間でしばらく運用してみて、使えそうなら本格運用を考えようかと思います。

# まとめ

- StackDriverのデフォルトのメトリクスだと運用には足りない
- カスタムメトリクスを使ってメトリクスを増やすことができる
    - カスタムメトリクスはAlertにも使える
    - Alert設定は新しいUIが出来て作りやすくなった
- StackDriverは $8 / host くらいなので、モニタリング系サービスの中では安い方だと思う