KubernetesをオープンソースのGraphiteで監視

#はじめに
この記事では、オープンソースの監視ツールGraphiteを使用してKubernetesを監視する方法について説明し、それをGrfanaで視覚化していく方法を説明していきます。 焦点は、Kubernetesクラスタを監視するための重要な指標の監視とプロットにあります。[Grafanaダッシュボードリソース](https://grafana.com/grafana/dashboards?search=kubernetes)からダウンロードできるKubernetesのカスタムダッシュボードをダウンロード、実装、監視します。 これらの監視ダッシュボードには、きめ細かいレベルでデータにドリルダウンできる[変数](https://grafana.com/docs/grafana/latest/reference/templating/)があります。

またこのようなセットアップを自ら行わずとも、[MetricFire](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Monitoring%20Kubernetes%20with%20Graphite)はGraphiteとGrafanaの統合を完了してプラスαのモノを提供しております。是非、MetricFireの[無料トライアルにサインアップ](https://www.hostedgraphite.com/accounts/signup-metricfire/?signup=japan&utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Monitoring%20Kubernetes%20with%20Graphite)してください。MetricFireとGrafanaをプラットフォームで直接使用できます。 MetricFireはホスト型のGraphite、Grafana、Prometheusサービスであり、これらのオープンソースツールのセットアップと管理を行っているため、お客様が行う必要は一切ありません。

#Kubernetesの概要
Kubernetesによると、Kubernetesは、コンテナ化されたワークロードとサービスを管理するための「移植可能で拡張可能なオープンソースプラットフォーム」であり、宣言的な構成と自動化の両方を容易にします。大規模で急速に成長しているエコシステムが存在し、Kubernetesのサービス、サポート、ツールは広く利用できます。

今日の業界では、Kubernetesデプロイメントの監視は困難ですが必要な活動です。 この記事では、ダッシュボードの使用方法を詳しく説明するため、Kubernetesの基本については説明しません。 Kubernetesモニタリングの詳細については、MetricFireブログの[Kubernetesモニタリングの概要](https://www.metricfire.com/blog/introduction-to-monitoring-kubernetes)をご覧ください。


#Graphiteの概要
Graphiteは非常に人気のあるエンタープライズモニタリングツールです。MetricFireには、2012年から開発および改善されているHosted Graphite製品があります。グラファイトは、StatsDなどのコレクターによってプッシュされたメトリックデータを受信する時系列モニタリングツールです。 collectdし、ユーザーが指定した時系列メトリックを監視します。 Graphiteの基本について知りたい場合は、この記事を読む前に、[アーキテクチャとコンセプト](https://www.metricfire.com/blog/monitoring-with-graphite-architecture-and-concepts)、Graphiteの[インストールとセットアップ](https://www.metricfire.com/blog/monitoring-with-graphite-installation-and-setup)に関する記事をご覧ください。

#Graphite、Grafana、Kubernetesのセットアップ

この記事では、AWSにデプロイされたKubernetesクラスターを使用します。 [Amazon AWS EKSユーザーガイド](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html)の指示に従ってAWS CLIをインストールし、kubectlコマンドラインツールもインストールしてください。

kubectlがインストールされたら、コマンド「kubectl cluster-info」を実行すると、次の出力が表示されます。

```
~ ./kubectl cluster-info
Kubernetes master is running at https://92797800687320683968AF0937C2B5D3.yl4.ap-south-1.eks.amazonaws.com
CoreDNS is running at https://92797800687320683968AF0937C2B5D3.yl4.ap-south-1.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
```

次に、kubernetesクラスターにGrafanaをセットアップします。 以下は、GrafanaポッドとKubernetesで実行されるサービスを作成する単純な設定ファイルです

```
| apiVersion: apps/v1 |
|:--|
| kind: Deployment |
| metadata: |
|  labels: |
|    app: grafana |
|  name: grafana |
| spec: |
|  replicas: 1 |
|  selector: |
|    matchLabels: |
|      app: grafana |
|  template: |
|    metadata: |
|      labels: |
|        app: grafana |
|    spec: |
|      containers: |
|      - image: grafana/grafana:5.4.3 |
|        name: grafana |
|        ports: |
|        - containerPort: 3000 |
|          name: http |
|  |
|        volumeMounts: |
|          - name: grafana-storage |
|            mountPath: /var/lib/grafana |
|      volumes: |
|        - name: grafana-storage |
|          persistentVolumeClaim: |
|            claimName: grafana-storage |
|      securityContext: |
|        runAsNonRoot: true |
|        runAsUser: 65534 |
|        fsGroup: 472 |
| --- |
| kind: PersistentVolumeClaim |
| apiVersion: v1 |
| metadata: |
|  name: grafana-storage |
| spec: |
|  accessModes: |
|    - ReadWriteOnce |
|  resources: |
|    requests: |
|      storage: 1Gi |
| --- |
| apiVersion: v1 |
| kind: Service |
| metadata: |
|  name: grafana |
|  labels: |
|    app: grafana |
| spec: |
|  type: LoadBalancer |
|  ports: |
|  - port: 3000 |
|    protocol: TCP |
|    targetPort: 3000 |
|  selector: |
|    app: grafana |
```

「kubectl create -f grafana-deployment.yml」を実行して、Grafanaポッドとサービスを作成します。
コマンド「kubectl get service」を実行すると、次のような出力が表示されます。

```
➜  ~/github/k8-graphite-monitoring (master) kubectl get service
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP                                                                PORT(S)                       AGE
grafana      LoadBalancer   10.100.252.229   a942a31a4780f11eaa9010a814a720da-1449083553.ap-south-1.elb.amazonaws.com   3000:31159/TCP                3d21h
kubernetes   ClusterIP      10.100.0.1       <none>                                                                     443/TCP                       3d22h
```

a942a31a4780f11eaa9010a814a720da-1449083553.ap-south-1.elb.amazonaws.comは新しく作成されたサービスのホスト名で、3000はアクセスするポートです。 [http://a942a31a4780f11eaa9010a814a720da-1449083553.ap-south-1.elb.amazonaws.com:3000](http://a942a31a4780f11eaa9010a814a720da-1449083553.ap-south-1.elb.amazonaws.com:3000/)にアクセスし、admin / adminを使用してログインし、次のようにGrafanaが稼働していることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/3eec35d1-dfe8-4b8c-40d5-5ad91e93fb5f.png)

同様に、Graphiteのポッドとサービスを作成してみましょう。 以下の設定ファイルを使用して、Graphiteサービスを作成します。

```
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
   app: graphite
 name: graphite
spec:
 replicas: 1
 selector:
   matchLabels:
     app: graphite
 template:
   metadata:
     labels:
       app: graphite
   spec:
     containers:
     - image: graphiteapp/docker-graphite-statsd
       name: graphite
       ports:
       - containerPort: 2003
         name: carbon-plain     
       - containerPort: 2004
         name: carbon-pkl   
       - containerPort: 2023
         name: carbon-ag-plain
       - containerPort: 2024
         name: carbon-ag-pkl   
       - containerPort: 8125
         name: statsd   
       - containerPort: 8126
         name: statsd-admin  
       - containerPort: 80
         name: http       
---
apiVersion: v1
kind: Service
metadata:
 name: graphite
 labels:
   app: graphite
spec:
 type: LoadBalancer
 ports:
 - port: 80
   protocol: TCP
   targetPort: 80
   name: http
 - port: 2003
   protocol: TCP
   targetPort: 2003
   name: carbon
 selector:
   app: graphite
```

「kubectl create -f Graphite-deployment.yml」を実行して、このポッドとサービスを作成します。
この時点で、GrafanaとGraphiteの両方が稼働しているはずです。
「kubectl get service」を実行して、両方のサービスが稼働していることを確認します。

```
➜  ~/github/k8-graphite-monitoring (master) kubectl get service
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP                                                                PORT(S)                       AGE
grafana      LoadBalancer   10.100.252.229   a942a31a4780f11eaa9010a814a720da-1449083553.ap-south-1.elb.amazonaws.com   3000:31159/TCP                3d21h
graphite     LoadBalancer   10.100.216.91    ac0f466207b2211eaa9010a814a720da-687823427.ap-south-1.elb.amazonaws.com    80:32198/TCP,2003:32041/TCP   104s
kubernetes   ClusterIP      10.100.0.1       <none>                                                                     443/TCP                       3d22h
```

Grafanaと同様に、ブラウザーにhttp://ac0f466207b2211eaa9010a814a720da-687823427.ap-south-1.elb.amazonaws.comと入力して、以下に示すように、GraphiteWebアプリケーションを開くことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/f6a228cb-dac4-d41f-5eab-d862182d29ea.png)

次に、GrafanaのデータソースとしてGraphiteを追加します。 以下に示すように、Grafanaのデータソースセクションを参照し、データソースとしてGraphiteを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/680ae28e-1a5b-3a74-f461-f970753e75c0.png)


次に、KubernetesクラスターでSnap Daemonを実行します。 Snap Daemonは、さまざまなkubernetesモニタリングメトリックをプルし、それらをGraphiteにプッシュするモニタリングデーモンです。

Snap Daemonを実行する前に、snap_ds.yml内に1つの小さな変更を加える必要があります。 次に示すように、configセクションでGraphiteサービスのホスト名とポートを更新します。

```
apiVersion: apps/v1
kind: DaemonSet
metadata:
 name: snap
spec:
 selector:
   matchLabels:
     name: snap
 template:
   metadata:
     name: snap
     labels:
       name: snap
   spec:
     hostPID: true
     hostNetwork: true
     containers:
     - name: snap
       image: raintank/snap_k8s:v4
       volumeMounts:
         - mountPath: /sys/fs/cgroup
           name: cgroup
         - mountPath: /var/run/docker.sock
           name: docker-sock
         - mountPath: /var/lib/docker
           name: fs-stats
         - mountPath: /usr/local/bin/docker
           name: docker
         - mountPath: /proc_host
           name: proc
         - mountPath: /opt/snap/tasks
           name: snap-tasks
       ports:
       - containerPort: 8181
         hostPort: 8181
         name: snap-api
       imagePullPolicy: IfNotPresent
       securityContext:
         privileged: true
       env:
         - name: PROCFS_MOUNT
           value: /proc_host
     volumes:
       - name: dev
         hostPath:
           path: /dev
       - name: cgroup
         hostPath:
           path: /sys/fs/cgroup
       - name: docker-sock
         hostPath:
           path: /var/run/docker.sock
       - name: fs-stats
         hostPath:
           path: /var/lib/docker
       - name: docker
         hostPath:
           path: /usr/bin/docker
       - name: proc
         hostPath:
           path: /proc
       - name: snap-tasks
         configMap:
           name: snap-tasks
---
apiVersion: v1
kind: ConfigMap
metadata:
 name: snap-tasks
data:
 core.json: |-
   {
       "version": 1,
       "schedule": {
           "type": "simple",
           "interval": "10s"
       },
       "workflow": {
           "collect": {
               "metrics": {
                   "/intel/docker/*":{},
                   "/intel/procfs/cpu/*": {},
                   "/intel/procfs/meminfo/*": {},
                   "/intel/procfs/iface/*": {},
                   "/intel/linux/iostat/*": {},
                   "/intel/procfs/load/*": {}
               },
               "config": {
                   "/intel/procfs": {
                       "proc_path": "/proc_host"
                   }
               },
               "process": null,
               "publish": [
                   {
                       "plugin_name": "graphite",                   
                       "config": {
                           "prefix": "snap.dev.<%NODE%>",
                           "server": "ac0f466207b2211eaa9010a814a720da-687823427.ap-south-1.elb.amazonaws.com",
                           "port": 2003
                       }
                   }
               ]
           }
       }
   }
```

「kubectl create -f snap_ds.yml」を実行して、スナップデーモンを作成し、開始します。 「kubectl get pod」を実行すると、次のような出力が表示されます。

```
NAME                       READY   STATUS    RESTARTS   AGE
grafana-6f64b8c7f6-tc7qn   1/1     Running   0          3d23h
graphite-775d8b989-zwp9x   1/1     Running   0          65m
snap-dblx2                 1/1     Running   0          56m
snap-g5pzm                 1/1     Running   0          56m
snap-jdqrg                 1/1     Running   0          56m
```

Grafana用に1つのポッド、Graphite用に1つ、Snap用に3つが表示されます。 これは、Kubernetesクラスターに3つのノードがあり、Snapが各ノードでデーモンとして実行され、メトリックをプルしてGraphiteにプッシュするためです。

#Grafanaでモニタリングの視覚化をプロットする
Grafanaには、[Grafanaダッシュボードのリソースサイト](https://grafana.com/grafana/dashboards?search=kubernetes&orderBy=name&direction=asc)で見つけることができる多くの事前構築されたダッシュボードが付属しています。 これらのダッシュボードの1つをKubernetesモニタリングに利用します:[KubernetesContainer Stats](https://grafana.com/grafana/dashboards/482)

[Kubernetes Container Stats](https://grafana.com/grafana/dashboards/482)ページで、[Download JSON](https://grafana.com/api/dashboards/482/revisions/1/download)リンクをクリックして、Grafanaポータルにインポートします。 グラファイトデータソースを適切に選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/8435f12e-6b81-1d2f-66ae-d7aee101ec80.png)

ダッシュボードがインポートされるとすぐに、以下のように、ダッシュボードにメトリックが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/d33c267d-4b5f-e97b-792a-2d83fc03a761.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/114e5253-962d-0a16-4d4c-9b1f38766f6e.png)

同様に、別のダッシュボードKubernetes Nodeホストメトリックがあります。 これがインポートされると、ダッシュボードで選択されたホストごとのメトリックが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/fb25dc73-d01a-d746-d1dd-c67160be0dea.png)


これらのダッシュボードの値が重要なしきい値を超えた場合は、これらのダッシュボードにアラートを設定することができます。 Grafanaアラートの設定方法とカスタムダッシュボードの作成方法については、記事[「基本から詳細までのGrafanaダッシュボード」](https://qiita.com/MetricFire/items/f7ac1c9edf33eac48772)をご覧ください。

Kubernetesによって公開された指標に基づいて、他のタイプの視覚化を作成することもできます。 [「お気に入りのGrafanaダッシュボード」](https://www.metricfire.com/blog/our-favorite-grafana-dashboards)の記事を見て、より高度なダッシュボードをいくつか作成してください。

#MetricFireによるモニタリングのセットアップ
上記で行った設定は、ほんの数個のノードを含む非常に基本的なKubernetesインフラストラクチャで機能します。 数百ノード以上の数Mbpsのネットワークトラフィックである本番レベルの負荷を処理するには、増加する負荷を処理するために、GraphiteとGrafanaの両方をスケールアウトする必要があります。

[Hosted Graphite](https://www.metricfire.com/graphite-as-a-service)と[Hosted Grafana](https://www.metricfire.com/hosted-grafana)が登場します。 これにより、長期間のストレージに合わせてスケーリングし、データの冗長ストレージを自動的に提供できます。

MetricFireを介したホストされたGraphiteとホストされたGrafanaは、MetricFireのすべての製品が成長し続けるオープンソースプロジェクトに基盤を持っているため、[新機能の継続的なアクティブな展開](https://www.metricfire.com/blog/hosted-prometheus-vs-datadog)を可能にします。 ここでMetricFireの無料トライアルにサインアップし、数分以内に[Kubernetesダッシュボードの構築](https://www.hostedgraphite.com/accounts/signup-metricfire?utm_source=Blog&utm_medium=MetricFire&utm_campaign=Free%20Trial&utm_term=Monitoring%20Kubernetes%20with%20Graphite&_ga=2.159747581.1162615510.1589767768-2038175526.1567400116)を開始してください。

#まとめ
この記事では、Graphiteを使用してKubernetesモニタリングを設定する方法について説明しました。 GraphiteとGrafanaを使用してKubernetesを監視するための高度な視覚化を見てきました。

Hosted GraphiteとGrafanaの[無料トライアルにサインアップ](https://www.hostedgraphite.com/accounts/signup-metricfire/?signup=japan&utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Monitoring%20Kubernetes%20with%20Graphite)にご登録ください。 また、[MetricFire](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Monitoring%20Kubernetes%20with%20Graphite)の製品について、またはMetricFireがあなたの会社をどのように支援できるかについて質問がある場合は、是非[デモを予約](https://calendly.com/metricfire-chatwithus/chat?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Monitoring%20Kubernetes%20with%20Graphite)して直接当社にご連絡ください。