Kubernetesのconfigmapやsecret更新時にワークロードをアップグレードしてくれるReloaderを触ってみた

## はじめに
皆さんこんにちはasmgです。今回は、Kubernetesのconfigmapやsecret更新時にワークロードをアップグレードしてくれる[Reloader](https://github.com/stakater/Reloader)というものを触ってみたのでまとめていきたいと思います。


## Reloaderを検証してみようと思った背景
通常configmapやsecretリソースは更新時に、Deploymentのenvやvolumeの変更は行われません。なので、即時書き換えを行いたい場合にはsecretやconfigmapのリソースnameを変更するなどの作業が必要でした。これは意外と手間だったりするのでReloaderというカスタムオペレーターを使って上記のような課題を解決してみようとなりました。

:::note info
* <b>subPathボリュームマウントとしてConfigMapを使用するコンテナはConfigMapの更新を受信しません。</b>
ref:https://kubernetes.io/ja/docs/concepts/storage/volumes/#configmap

* <b>従って、configmapを更新させる場合には、configmapのリソースnameを変更する必要があります。</b>
:::

## 本記事の実行環境
検証機
Mac Book pro 14inch M1 Pro
検証環境
kind（Kubernetes in Docker）

## Reloaderの導入方法
```terminal:terminal
➜ $kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml
```
ref: https://github.com/stakater/Reloader#deploying-to-kubernetes

## secret、configmapリソースの更新時に自動でワークロードのアップグレードがされるかを確認
本記事では、configmapが更新時に自動でワークロードのアップグレードされるか確認します。

### 導入前の設定
```terminal:ディレクトリ構造
├── test-reloader
│   ├── configmap.yaml
│   ├── deployment.yaml
│   └── kustomization.yaml
```

```yaml:configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
  labels: {}
data:
  conf-yaml: |
    test
```
```yaml:deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
          - {name: conf-yaml, mountPath: /conf.yaml ,subPath: conf.yaml}
      volumes:
        - {name: conf-yaml, configMap: {name: test-config, items: [{key: conf-yaml, path: conf.yaml}]}}
```
```yaml:kustomization.yaml
resources:
  - deployment.yaml
  - configmap.yaml
```
### 導入前のconfigmapの動作
configmapを以下のように変更して実行してみました。
```yaml:configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
  labels: {}
data:
  conf-yaml: |
    test1
```
#### 動作結果
```terminal:terminal
# configmapをapply
➜ $kubectl apply -k test-reloader

# deployment リソースの取得
➜ $kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
sample-app-567598db56-pgslm          1/1     Running   0          13m

# podの中に入る
➜ kubectl exec -it  sample-app-567598db56-pgslm /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
 
cat conf.yaml
test
```
新しくapplyしたconfigmapは反映されてないことが分かります。

### Reloader導入後のconfigmapの動作
```diff_yaml:configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
  labels: {}
+ annotations:
+    reloader.stakater.com/match: "true"
data:
  conf-yaml: |
    test
```
```diff_yaml:deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-app
+  annotations:
+    configmap.reloader.stakater.com/reload: "*"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
          - {name: conf-yaml, mountPath: /conf.yaml ,subPath: conf.yaml}
      volumes:
        - {name: conf-yaml, configMap: {name: test-config, items: [{key: conf-yaml, path: conf.yaml}]}}
```
:::note info
<b>tips</b>
今回は、annotationに以下のような設定を入れて全てのconfigmap、secretの変更を取得するように設定しています。

```yaml:全てのconfigmap、secretの変更を取得する場合
  annotations:
    configmap.reloader.stakater.com/reload: "*"
```

特定のconfigmap、secretを取得するようにする場合には以下のような設定を入れてください。

```yaml:特定のconfigmap、secretの変更を取得する場合（今回はconfigmapのみ）
  annotations:
    configmap.reloader.stakater.com/reload: "test-config"
```

:::

deploymentリソースとconfigmapリソースをReloaderに対応させてapplyし、以下のようにconfigmapリソースが変更された際にワークロードがアップグレードされるかを確認します。

```yaml:configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
  labels: {}
  annotations:
    reloader.stakater.com/match: "true"
data:
  conf-yaml: |
    test1
```
#### 動作結果
```terminal:terminal
# configmapをapply
➜ $kubectl apply -k test-reloader

# deployment リソースの取得
➜ $kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
reloader-reloader-8544c57567-tb4fg   1/1     Running   0          25m
sample-app-567598db56-pgslm          1/1     Running   0          1m

# podの中に入る
➜ kubectl exec -it  sample-app-567598db56-pgslm /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.

cat conf.yaml
test1
```
Pod`sample-app-567598db56-pgslm`の起動時間(AGE)を見てもらうと秒数が短くなっていることがわかります。
configmapが更新されると自動でPodsの再起動がかかりconfigmapが更新されていることがわかります。

## まとめ
Kubernetes configmap secret更新時にワークロードをアップグレードしてくれるReloaderを触ってみました。
今回は、configmapのみ検証してみましたがconfigmap更新時にPodsを再起動してくれるので検証中などにReloaderは有効に感じました。
configmapの更新のタスクがよくある場合検証用Kubernetesクラスターへの導入してみると作業効率が上がると思います。