Prometheus を GKE で導入

# Prometheus

Go言語製の代表的なPull型でメトリクスベースのホワイトボックスモニタリングシステム
GoogleエンジニアがGoogle Borgmonに影響を受けて作成

- Borgmon rule -> PromQL
- Borgmon AlertManager -> AlertManager
 
本番環境でコンピュータシステム(アクセスが多いウェブサイトを支えているアプリケーション、ツール、データベース、ネットワークなど)を運用を助けるために作られたシステムである。
サーバとして起動し、監視対象を自動的に検出し、監視対象に対してHTTPリクエストを行いメトリクスを取得する。

メトリクスベースなのでイベント数よりもメトリクス数を考慮する。

## アーキテクチャ
![スクリーンショット 2019-10-16 16.17.17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238769/2930856c-3f2a-2a3e-f358-6bfc4547a1b6.jpeg)

## インストルメンテーション

## メトリクス

### Prometheusにおける命名規則

`<ライブラリ>_<名前>_<単位>_<サフィックス>`

## クライアントライブラリ
コードでメトリクスを生成する

### HELP
メトリクスの説明

### TYPE
- counter
- gauge
- summary
- histogram
- untyped

## サービスディスカバリ

## スクレイピング
定期的にメトリクスを取得

## ストレージ
データベース

## ダッシュボード
Grafana...

## Exporter

Prometheus ServerからHTTPリクエストを受け取り、アプリケーション(Node、Server)から必要な監視項目のデータを収集し正しい形式に変換してPrometheus Serverにレスポンスとしてメトリクスを返すプロキシ(GKEではDaemonSet)

### Node exporter

各GCEインスタンスに置いてLinuxの標準的なカーネル、マシンレベルのメトリクスを開示するexporter
CPU、メモリ、ディスクスペース、ディスクI/O、ネットワーク帯域幅...

<img width="512" alt="スクリーンショット 2019-09-23 18.27.11.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238769/faba8763-9567-6cc3-530a-b8e3933e2dae.jpeg">

### cAdvisor
コンテナのメトリクスを取得するためのExporter

### apiserver

kube-apiserverについてのメトリクスを提供するexporter

### kubelet

kubeletについてのメトリクスを提供するexporter 

#### metrics path

`http://kubelet:10255/metrics`

### cAdvisor

cgroupsについてのメトリクスを提供するexporter

#### コンテナの CPU のメトリクス
- container_cpu_usage_seconds_total
- container_cpu_system_ seconds_total
- container_cpu_user_seconds_total 

#### metrics path

`http://kubelet:10255/metrics/cadvisor`


## Exporter format

```
text/plain
# HELP
# TYPE
~
~
```

### Role

#### endpoints

#### service

#### Pod
kubernetes pods を探し出す

# Alertmanager
アラート発報システム
Prometheusで集計したメトリクスをもとにアラート通知を行う
Slack, PagerDutyへの通知や類似通知の重複削除が可能

## Silences
問題があることをすでに知っている場合や、メンテナンスのためにサービスを落としている場合には、それについてオンコール担当者を呼び出しても無意味である場合はSilenceを使って特定のアラートをしばらくの間無視できる

## Routing
アラートの送り先をルーティングする。

## Grouping
アラートをラックごとにグルーピングする

## 通知
receiverを介して外部にアラートを送る。通知はテンプレート化されており、内容をカスタマイズしたり、重要な細部を強調したりできる。

## 設定ファイル
命名には基本的には `alertmanager.yml`


# PromQL

クエリを用いてメトリクスの集計を行う

```
rate(http_status_5xx_total[5m]) / rate(http_status_2xx_total[5m])
sum(node_memory_MemFree)
avg(node_memory_MemFree)
```
## Container Network Input Output 
### Input
`sort_desc(sum by (pod_name) (rate(container_network_receive_bytes_total{image!="",namespace="default"}[1m])))`
### Output
`sort_desc(sum by (pod_name) (rate(container_network_transmit_bytes_total{image!="",namespace="default"}[1m])))`
## コンテナ数
`count(rate(container_last_seen{name=~".+"}[5m]))`
## default name space http request
### 200
`increase(istio_requests_total{destination_service_namespace="default", request_protocol="http", response_code="200"}[1m])`
### 404
`increase(istio_requests_total{destination_service_namespace="default",request_protocol="http",response_code="404"}[1m])`

## Memory Usage 
`sum(container_memory_usage_bytes{namespace="default", image!=""}) by (namespace, pod_name)`

## Pods CPU Usage [1m]
`sum(rate(container_cpu_usage_seconds_total{namespace="default", image!=""}[1m])) by (pod_name) * 100`

## GKEに導入 （アプリケーション）

Namespace: default
Service: prometheus-grafana

1. GCPダッシュボード /Kubernetes Engine/Applications/Marketplaceからデプロイ
2. prometheus & grafana を選択
3. 必要な設定項目を記載してデプロイ
4. prometheus-grafanaを外部公開

```
$ kubectl patch svc prometheus-grafana -n default -p '{"spec": {"type": "LoadBalancer"}}'
```

5. ログインユーザーを登録


```
$ kubectl get secret prometheus-grafana --namespace default --output=jsonpath='{.data.admin-user}' | base64 --decode
```

6. ログインパスワードを登録

```
$ kubectl get secret prometheus-grafana --namespace default --output=jsonpath='{.data.admin-password}' | base64 --decode
```

7. `4.`で外部公開したIPからGrafanaに`5.` `6.`で登録したユーザー、パスワードでログイン

## GKEに導入

### ログインの設定
```
$ PASSWORD=$(head -c 12 /dev/urandom | shasum| cut -d' ' -f1)
$ kubectl -n istio-system create secret generic grafana --from-literal=username=admin --from-literal=passphrase="$PASSWORD"
```