custom metrics による HPAに学ぶ Operator と Adapter

## 概要

custom metrics による HPAについて調べる過程で Operator や Adapter に関する知見を得ましたので共有します。
[CloudNative Days Kansai 2019 Meetup](https://cloudnativedays.connpass.com/event/152321/)でLTした際の[スライド](https://speakerdeck.com/loftkun/hpa-with-custom-metrics)もご参照ください。

[![スライド1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/61d45f01-0fcb-98f5-6e3f-46ad62182a0b.png)](https://speakerdeck.com/loftkun/hpa-with-custom-metrics)


以下について記載しています。

- Pod Autoscaler
  - VPAとHPA
- CPU使用率によるHPA
- custom metricsによるHPA
  - Operatorとは
  - Adapterとは

## Pod Autoscaler 

VPAとHPAがあります。

### VPA( Vertical Pod Autoscaler )

resources requestsを増減してくれます。

![スライド56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/73c36dc1-994d-f532-e71e-7827b4884abf.png)

### HPA( Horizontal Pod Autoscaler )

pod数を増減してくれます。

![スライド58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/6b49ee33-a9a8-4dce-da67-52fa49125b49.png)

本記事はHPAに関するお話です。

## CPU使用率によるHPA

公式ドキュメント( [Horizontal Pod Autoscaler Walkthrough](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) ) に手順がありますのでやってみました。

サンプルアプリケーション(`php-apache`)に負荷をかけると以下スライドのようにpod数が増えたので、確かにCPU使用率を基にしたHPAが動作していることが確認できました。

![スライド12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/09cad244-6e23-a951-bc8a-f4e85ce52a71.png)

## カスタムメトリクスによるHPA

[luxas/kubeadm-workshop](https://github.com/luxas/kubeadm-workshop)にサンプルがあるのでやってみました。

マニフェストファイルは[demos/monitoring](https://github.com/luxas/kubeadm-workshop/tree/master/demos/monitoring)にあり、
サンプルアプリ(`sample-metrics-app`)が公開している`http_requests`というメトリクスに基づいてpod数が増減するサンプルとなっているようでした。

![スライド16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/251f88a5-8715-1f6d-b8b3-2d815b558616.png)

サンプルアプリ(`sample-metrics-app`)にアクセスすると以下スライドのようにpod数が増えたので、確かに`http_requests`というメトリクスに基づいてHPAが動作していることが確認できました。

![スライド19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/4444aad9-b67d-791e-6bd1-c9ef2e3e292c.png)

無事、カスタムメトリクスに基づいたHPAの動きを確認できました。
めでたし、めでたしといきたいところですが、
マニフェストファイル([demos/monitoring](https://github.com/luxas/kubeadm-workshop/tree/master/demos/monitoring)) を読んでみるといくつかの疑問が湧いてきました。

## 疑問点

### Operatorとは🤔

`prometheus-operator`を使ったDeploymentが定義されていました。
何なのでしょうか？
![スライド21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/c6853399-5142-4fdd-4918-638eaef9ffd7.png)

### 謎のリソース🤔

`ServiceMonitor`や`Prometheus`という謎のリソースが`kind`に指定されている箇所がありました。
これらはいつどこで定義されいつから使用可能になったのでしょう？

![スライド22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/e2d1daf2-b87f-aa51-3129-2791061d7d50.png)
![スライド23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/b9ccd996-3646-aec5-fc5a-1ee91ab2f567.png)

### Adapter🤔

メトリクスサーバと思われるDeploymentには`prometheus-adapter`なるimageが指定されていました。
`adapter`とは何なのでしょうか？

![スライド24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/9316734f-d230-322f-8416-bb1052f13fdb.png)

このメトリクスサーバは、アプリが公開しているメトリクスをどのようにして収集しているのでしょうか？(左の`How to?`)
また、HPA コントローラーはそのメトリクスをどのように取得しているのでしょうか？(右の`How to?`)

![スライド27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/672f87cc-71e2-e4cd-9077-214ee254cfc7.png)

## 調査方法

マニフェストファイル([demos/monitoring](https://github.com/luxas/kubeadm-workshop/tree/master/demos/monitoring)) に記載された各定義を整理することにしました。
そのためにマニフェストの各要素をExcelのテキストボックスとして出力するツール([loftkun/yaml2excel](https://github.com/loftkun/yaml2excel))を書きました。

Excelファイルを出力するようにしたのは、参照関係のある要素同士をドラッグして近づけたり、矢印でつないだりして整理できるのが便利なためです。
今のところ、整理作業は手作業が必要ですが、マニフェストの参照関係に基づいて自動化できるとよいなと思っています。
( このような整理のできる良いツールが有りましたら教えていただけると大変助かります。 )

![スライド28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/f6205834-dfe3-477a-795b-86e46b9740d8.png)

## 調査結果

以下のような構成になっていました。

![スライド43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/b05187a2-44e3-47a0-3b2c-7ebd04acf90a.png)

### Operator

上記スライドの左側を説明します。

1. `Prometheus Operator`をデプロイすると`ServiceMonitor`や`Prometheus`といったカスタムなリソース定義(CRD)を生成していました。
1. そのため、`Prometheus Operator`をデプロイした後は、`kind`に`ServiceMonitor`や`Prometheus`を指定したオブジェクトをデプロイできるようになっていました。
1. `ServiceMonitor`には監視対象メトリクスのエンドポイントを設定できます
1. `Prometheus Operator`は`ServiceMonitor`に設定されたエンドポイントを基に`Prometheus`のconfig(`prometheus.yml`)を生成してくれていました。

このことから、`Operator`とは自身が取り扱うことのできるCRDと、その取り扱いを実装したコントローラーであり、人間の手作業による運用(Operation)をコードで実装したものだと理解しました。

### Adapter

上記スライドの右下側を説明します。

1. `Custom metrics server`は、`Prometheus`と`HPA controller`の間に立っています。
1. `API Service`は`Custom metrics server`を`kube-api server`の拡張領域である`aggregation layer`に登録するためのものです。
1. これにより`HPA controller`は`kube-api server`経由で`Custom metrics server`を介して`Prometheus`のメトリクスを取得できるようになっているようでした。

`Prometheus`と`HPA controller`という本来通信が不可能な2者の間にあるのが`Custom metrics server`であり、両者をつなげる互換性を提供している位置付けにあると捉えることができそうです。
そんな`Custom metrics server`のimageが`prometheus-adapter`と名付けられていることから、これは互換性を提供するパターンである`Adapterパターン`の事例であると理解しました。

## まとめ

- `Prometheus Operator`によるメトリクスの収集を題材として`Operator`が何なのかを理解できたはず
- `Adapterパターン`の具体的な事例として`prometheus-adapter`を用いた`Custom metrics server`を知ることができた
- [luxas/kubeadm-workshop](https://github.com/luxas/kubeadm-workshop) は、custom metricsによるHPAを動かすサンプルとしてだけでなく、`Operator`や`Adapter`について理解する上でも非常に良いサンプルでした

本記事が参考になりましたら幸いです。