Kubernetes 上に Kong をデプロイし、Prometheus によりトラフィックをモニタリングしてみる

これは、[Kong + HashiCorp Meetup Tokyo #1](https://kong-meetup.connpass.com/event/135495/) で実演したデモの紹介です。  


## はじめに

「Kong + HashiCorp Meetup Tokyo #1」というイベントを開催しました。
イベント題名にもある Kong という製品のデモンストレーションをご紹介します。
準備が整っていれば、10 分程度で Kong の世界が体験出来るかと思います。

「Kubernetes」と「Kubernetes Ingress Contoller for Kong」を利用します。


## Kong について

オープンソースのAPIゲートウェイソフトウェアで、Web APIを使ったクラウドやマイクロ サービスのインテグレーションを可能にします。
Linux、Docker、Kubernetes、AWS、 GCP、Azureなど幅広い環境で利用できることが特徴で、通算7500万ダウンロードの人気の高さを誇ります。


## 準備した環境について

- MAC 
    - macOS Mojave バージョン 10.14.6
    - プロセッサ : 3.1 Ghz 
    - メモリ : 16 GB 
- VirtualBox
    - minikube を動作させるために必要
    - バージョン 6.0.6 r130520
- Docker 
    - Desktop Community Version 2.0.0.3
    - Kuvernetes: v1.10.11


## 前準備

インストールされていない場合、

- VirtualBox [インストール](https://www.virtualbox.org/wiki/Downloads)

- Docker [インストール (Docker Destop for Mac)](https://hub.docker.com/editions/community/docker-ce-desktop-mac)  

ターミナルから利用するコマンドについて

- helm  (Kubernetes 用のパッケージマネージャー) 

```
$ brew install kubernetes-helm
```

- minibule (Kubernetes ローカル環境で実行するためのツール)

```
$ brew cask install minikube
```

- kubectl (Kubernetes コマンドラインツール)

``` 
$ brew install kubectl
```

- watch (コマンド)  
watch コマンドは、インストール状況確認に便利です。(しなくても進められます。)

``` 
$ brew install watch
```


- munikube のメモリ設定について  
4 GB ほど割り当てたほうが安定した動作確認がしやすいです。  

設定例
    
``` 
$ minikube config set memory 4096
$ minikube delete (一旦 delete する必要あります)
$ minibuke start
```

## Kong デモンストレーション

ここからが Kong デモンストレーションのご紹介です。

０. 初期化（リセット用途）

やり直しを行うとき等に利用します。

``` 
$ minikube delete
$ minubuke start
$ helm init
```


１. Kong をインストール  

Kubernetes 用パッケージマネージャー helm を利用します。
--namespace kong で、ネームスペースを指定し展開しています。

```
$ helm install stable/kong --name kong --namespace kong --values https://bit.ly/2RgSRio --version 0.9.0
```  


２. Kong インストール状況確認  

ここでは、watch コマンドを利用しています。
watch コマンドをインストールしていない場合は、kubectl 以下を何度か実行してください。

```
$ watch -n 1 kubectl get pod -n kong
```
実行後、

```
NAME                                  READY   STATUS      RESTARTS   AGE
kong-kong-58d994d4d8-z7cwv            1/1     Running     0          3m55s
kong-kong-controller-cb4c7977-cmd8h   2/2     Running     0          3m55s
kong-kong-init-migrations-fxt6r       0/1     Completed   0          3m55s
kong-postgresql-0                     1/1     Running     0          3m55s
```

migrations 項目以外が Running になれば、インストール成功！

NAME 表示上から、

- プロキシリクエスト処理用、DataPlane  
- KongAPI を処理する、ControlPlane  
- データストアにテーブルを作成する、マイグレーション  
- データストア（postgresql）

と４つの POD が設定されました。  


３. Exporse Kong (公開)

ポートフォワードを設定します。  

```
$ kubectl --namespace kong port-forward $(kubectl get pods --namespace kong -l "app=kong" -o jsonpath="{.items[0].metadata.name}") 8000 &
```

ポート 8000 にて外部からアクセス出来るようになりましたので確認します。


４. Exporse 確認
  
cURL コマンドを利用します。
  
```
$ curl 127.0.0.1:8000
Handling connection for 8000
{“message”:“no Route matched with those values”}
```
このようなレスポンスがあれば、成功！


５. サービスをインストール

このデモにて利用するサービスをインストールします。
kubernetes にリソースを追加するので、YAML ファイルの適用になります。

```
$ kubectl apply -f https://gist.githubusercontent.com/hbagdi/2d8ef66fe22cb99e1514f410f992268d/raw/a03d789b70c46ccd0b99d9f1ed838dc21419fc33/multiple-services.yaml
```

実行結果、

```
deployment.extensions/http-svc created
service/billing created
service/invoice created
service/comments created
```


６. サービスに対する Ingress をインストール

Ingress (ロードバランス用APIオブジェクト) をインストールし、
kubernetes クラスター内のサービズに外部アクセス出来るようにします。

```
$ echo "apiVersion: configuration.konghq.com/v1
kind: KongIngress
metadata:
name: strip-path
route:
strip_path: true
" | kubectl apply -f -
```

and

```
$ echo "apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
    configuration.konghq.com: strip-path
name: sample-ingresses
spec:
rules:
- http:
    paths:
    - path: /billing
    backend:
        serviceName: billing
        servicePort: 80
    - path: /comments
    backend:
        serviceName: comments
        servicePort: 80
    - path: /invoice
    backend:
        serviceName: invoice
        servicePort: 80" | kubectl apply -f -
```


７. サービス確認

サービスの呼び出しができるか確認します。

```
$ curl -i http://localhost:8000/billing/status/200
```

実行後、

```
Handling connection for 8000
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Kong-Upstream-Latency: 2
X-Kong-Proxy-Latency: 13
Via: kong/1.0.0
```
200 OK とレスポンスされていれば、成功です。

このデモ紹介では、トラフィックのモニタリングを行いたいので、ループ処理にて FakeTraffic を与えます。
PC によっては、高負荷になるかもしれませんので sleep 0.01 の値を調整しても良いです。

```
$ while true;
do
  curl http://localhost:8000/billing/status/200
  curl http://localhost:8000/billing/status/501
  curl http://localhost:8000/billing/status/501
  curl http://localhost:8000/invoice/status/201
  curl http://localhost:8000/invoice/status/404
  curl http://localhost:8000/comments/status/200
  sleep 0.01
done
```


８. トラフィックのモニタリング

[Prometheus](https://www.webapi.tokyo/prometheus%E3%81%AE%E5%87%84%E3%81%84%E6%89%80/) とは、リソース監視のソフトで、インフラ状況を可視化できます。

Prometheus をインストールします。

```
$ helm install --name prometheus stable/prometheus --namespace monitoring --values https://bit.ly/2RgzDtg --version 8.4.1
```

あわせて Prometheus で得た情報をグラフ化する Grafana をインストールします。
ここでは、--namespace nonitoring のネームスペースを指定し展開しています。

```
 $ helm install stable/grafana --name grafana --namespace monitoring --values http://bit.ly/2FuFVfV --version 1.22.1
```



９. Prometheus と Grafana のイントール確認

８.で指定した、namespace monitoring の pod の状況を確認します。

```
$ watch -n 1 kubectl get pod -n monitoring
```

実行結果、
    
```
Every 1.0s: kubectl get pod -n monitoring

NAME                                             READY   STATUS    RESTARTS   AGE
grafana-95898fd7-htk7n                           1/1     Running   0          11m
prometheus-alertmanager-845d9678b9-7h8k7         2/2     Running   0          14m
prometheus-kube-state-metrics-857f8ffb9d-jpxdz   1/1     Running   0          14m
prometheus-node-exporter-pltc7                   1/1     Running   0          14m
prometheus-pushgateway-75f7fdb48b-cth7q          1/1     Running   0          14m
prometheus-server-6d6c5d6dd8-nwj52               2/2     Running   0          14m
```

このように、全ての STATUS が Running となれば、インストールは完了です。


１０. Prometheus と Grafana の Expose

外部からアクセスできるように Expose します。

Prometheus

```
$ kubectl --namespace monitoring port-forward $(kubectl get pods --namespace monitoring -l "app=prometheus,component=server" -o jsonpath="{.items[0].metadata.name}") 9090 &
```
    
Grafana 

```
$ kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
```

Prometheusは、ポート9000、Grafanaは、ポート3000で Expose されました。


１１. Grafana の確認

    
ブラウザを開き、ポート3000 にアクセスします。
    
``` 
// ブラウザ
127.0.0.1:3000
```

Grafana へアクセスでき、LogIn 画面が確認できるかと思います。
ログイン用のパスワードを生成します。


１２. パスワード生成

パスワードを生成します。パスワードは、ターミナル内に表示されます。

```
$ kubectl get secret --namespace monitoring grafana -o jsonpath=“{.data.admin-password}” | base64 --decode ; echo
```


１３. Grahaa Dashboard

ユーザー名「**admin**」、生成したパスワードで再度 Grafana へログインします。
画面左上方にある「Home」メニューを押し、「Kong」を選択します。
グラフが表示される画面に切り替わりますが、未だモニタリングされていない状態です。


１４. Kong プラグインの追加

Kong に用意されているプラグインを追加して、Prometeus を有効化します。
Kong には、このようなプラグインが様々用意されており、機能拡張が容易に行えます。

```
$ echo "apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
labels:
    global: \"true\"
name: prometheus
plugin: prometheus
" | kubectl apply -f -
```


１５. モニタリング確認

再び、ブラウザに戻り、Grahaa 画面を確認してみます。
Kong プラグイン追加により Prometheus が利用可能になりモニタリングが開始されます。
モニタリング（グラフ）開始までは少し時間かかります。


## モニタリング内容

- サービスに関するレイテンシ情報  
![0_RequestLatenciesofVariousServices.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473881/96e38ce1-fbba-61cc-3262-61309075f71a.png)
サービスがリクエストに応答するのにかかる時間のレイテンシデータを収集できます。
このデータを使用して、待ち時間が特定のしきい値を超えた場合、警告することができます。

- Kong 自体のレイテンシ情報
![1_KongProxyLatency.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473881/ccbd6ec7-ac0c-e0a5-8cee-3cb8079ca632.png)
Kong パフォーマンスのメトリックも収集できます。 
Kong によって追加されたレイテンシに関してモニタリングできます。

- リクエストレート、バンド幅
![2_RequestRateandBandwidth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473881/dda4658d-baf3-3a3c-c276-d8db2ff3cad5.png)
![3_RequestRateandBandwidth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473881/e356fce8-3d50-a86b-4027-8fcb050c0e26.png)
kong_http_status 時系列にて、各サービスまたはKubernetesクラスター全体の合計リクエストレートモニタリングできます。
ネットワーク帯域幅（kong_bandwidth）の量もモニタリングでき、要求/応答のサイズがインフラの他の動作とどのように相関するかを推定できるようになります。

他にも、「Error Rate」のモニタリングも可能です。


## まとめ

このように「Kubernetes Ingress Controller for Kong 」を利用すると、管理者が Kong Admin APIをコールすることなく、Kubernetes 上でプロキシ設定が可能となります。
つまり、Kong の API サービス管理とKubernetes のコンテナ管理が統合できるようになります。

今回は、Kubernetes 上に Kong をデプロイ、Prometheus 用プラグインを追加し、Prometheus と Grafana を利用してトラフィックをモニタリングするデモを紹介しました。
1つのプラグイン紹介となりましたが、 Kong は様々なプラットフォームにインストール出来るうえ、様々なプラグインが用意されており機能拡張が容易に行える製品となっております。

※ 注意 : 今回の設定等はあくまでもデモ用途であり本利用の際には検討が必要です。