[Kubernetes] 自動でPVCを拡張する (pvc-autoresizer)

# 抱えていた問題

PVCのデータが増えていくので、 以下のようなコマンドでちょっとずつ拡張していた→手作業！

```
kubectl patch pvc <pvc-name> -p '{"spec":{"resources":{"requests":{"storage":"70Gi"}}}}}'
```

手作業をへらすために、大きく拡張すれば、コストの無駄が出るし、少しずつ拡張すれば工数の無駄が出る。

なんとかせねば。

# 考慮したもの

- [Kintone Engineering Blog](https://blog.kintone.io/)にあった記事
    - [https://blog.kintone.io/entry/pvc-autoresizer](Introducing pvc-autoresizer)
    - コード: https://github.com/topolvm/pvc-autoresizer
- [RedHatのブログ](https://cloud.redhat.com/blog)にあった記事
    - [Automating Volume Expansion Management - an Operator-based Approach](https://cloud.redhat.com/blog/automating-volume-expansion-management-an-operator-based-approach) 
    - コード: https://github.com/redhat-cop/volume-expander-operator

選択結果: RedHatのほうは、PodのRestartまでOperatorの中に実装されていたが、Kubernetes 1.15で `ExpandInUsePersistentVolumes`が[BetaになってDefaultでTrueになってる](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#resizing-an-in-use-persistentvolumeclaim)からRecreateいらないのではと思って1つ目の pvc-autoresizerにした
> 既存のPVCを使用しているPodまたはDeploymentを削除して再作成する必要はありません。使用中のPVCは、ファイルシステムが拡張されるとすぐにPodで自動的に使用可能になります。

# pvc-autoresizerとは

Prometheusでkubeletのディスクに関するメトリクスをあつめて、ディスク使用量が指定した閾値に達したら、ボリュームを拡張するというもの。 (betaではある)

[README](https://github.com/topolvm/pvc-autoresizer)がしっかりしていてわかりやすいが、個人的には、 [design.md](https://github.com/topolvm/pvc-autoresizer/blob/6d78b78aceb5091aa438a180cd76d33b71830535/docs/design.md)がもっとわかりやすいのでこちらを先に読むのがおすすめ。

## 1. Prometheusでストレージのサイズのメトリクスを収集
ubeletで収集するvolume stats
- `kubelet_volume_stats_available_bytes`
- `kubelet_volume_stats_capacity_bytes `
のメトリクスを`Prometheus`でScrapeする

## 2. pvc-autoresizerをデプロイ

```
helm repo add pvc-autoresizer https://topolvm.github.io/pvc-autoresizer
helm repo update
```

```
helm install --create-namespace --namespace pvc-autoresizer pvc-autoresizer pvc-autoresizer/pvc-autoresizer --set "controller.args.prometheusURL=http://prometheus-operated.monitoring.svc:9090"
```

以下のようなオプションがある:
- `controller.args.prometheusURL`
- `controller.replicas`
- `controller.args.additionalArgs`

詳細は[charts/pvc-autoresizer](https://github.com/topolvm/pvc-autoresizer/tree/main/charts/pvc-autoresizer)

## 2. `StorageClass`の変更

`resize.topolvm.io/enabled: "true"`をアノテーションにつけるだけ。

(or `pvc-autoresizer`を`--no-annotation-check=true`で起動する)

ただし条件:
- `allowVolumeExpansion: true`に設定が必要


## 3. `PVC`の変更

どんな条件で拡張するかをアノテーションで指定: 
- `resize.topolvm.io/storage_limit` (必須) 例. `200Gi`
- `resize.topolvm.io/threshold` (任意の `%`か `Gi`) defaultは `10%`
- `resize.topolvm.io/increase` (任意の `%` か `Gi`) defaultは `10%`

ストレージがどこまで行ったら (threshold)、マックスどこまで(storage_limit)、どれだけふやすのか(increase)というとてもわかり易い！


ただし条件:
- `volumeMode: Filesystem` でないといけない
- `spec.storageClassName`に上記のStorageClassが入ってないといけない

# ハマリポイント

- `PVC`の`spec.storageClassName` <- StatefulSetなどでPersistentVolumeClaimなどでAnnotationだけ書いてるとこのフィールドがなくてStorageClassにたいしてPVCを取得するところで対象にならないので注意!
- `kubelet_volume_stats_available_bytes`と`kubelet_volume_stats_capacity_bytes`のメトリクスをPrometheus OperatorのServiceMonitorで取得していると `exposed_namespace` にPVCのNamespaceが格納されるが、pvc-autoresizerでは`namespace`を見るので、間違ったものを見るために[`if _, ok := vsMap[namespacedName]; !ok`で](https://github.com/topolvm/pvc-autoresizer/blob/79451051cfc7fc0ff802ebb8544f1ac240d7fc07/runners/pvc_autoresizer.go#L125)弾かれるので注意
- これらを探すのにLogが少なくてDebugが大変！ -> 自分でForkして[ログ足して](https://github.com/nakamasato/pvc-autoresizer/pull/1/files)デプロイして始めて発見した。

# 感謝

いろいろあったがしっかり動いたので、こんな便利なものを作って公開してくれる人に感謝！

# 参考

- [https://blog.kintone.io/entry/pvc-autoresizer](Introducing pvc-autoresizer)
- https://github.com/topolvm/pvc-autoresizer
- [Automating Volume Expansion Management - an Operator-based Approach](https://cloud.redhat.com/blog/automating-volume-expansion-management-an-operator-based-approach) 
- https://github.com/redhat-cop/volume-expander-operator