kustomize で ConfigMap を作成する方法

# 概要
前回、[kustomize で secrets を作成する方法](https://qiita.com/syogun/items/cd7ebc55f68d53042db5)という記事を書きましたが、今回はその続編としてkustomizeの`configMapGenerator`を使用して、ConfigMap作成する方法を書いてみたいと思います。

# ConfigMapの値が自動反映されない問題
そもそもなぜ、`configMapGenerator`を使う必要があるのでしょうか。
以前書いた[Helm環境でConfigMapの更新を検知してPodを自動デプロイする方法](https://qiita.com/syogun/items/20285fad40986590996b#%E3%83%8F%E3%83%9E%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8)では、
>ちなみにConfigMapを参照する方法として、VolumeでMountする方法と環境変数として渡す方法の2通り方法があります。
VolumeでMountする方法は、一定期間ごとに変更を確認し、ConfigMapに変更がある場合は動的に反映させます。

とご紹介しました。
ここ言っている動的に反映とは、ConfigMap自体を指しますが、これだけでは不十分です。
実際にPodで動いているコンテナに最新の設定値(ConfigMap)を反映させるには、Podの再起動やデプロイが必要になるかと思います。
（私にとって）ここが通常のConfigMapの課題でした。

# configMapGeneratorとは
そこでkustomizeには、`configMapGenerator`の登場です。
通常のConfigMapを作成とは違い、`configMapGenerator`でConfigMapリソースを作成した場合、
新たにハッシュ値つきのConfigMapリソース名が作成されます。

例)

```shell

$ kubectl get configmap
envoy-conf-82fkh22552     1      2d16h
envoy-conf-g5mdb27tkh     1      2d15h
```

新たにConfigMapリソースが作成された後、Deploymentなどで指定しているConfigMapリソース名も自動で変更してくれるようです。
そうすることによって、ConfigMapを変更時にPodsが再作成されます。
結果、ConfigMap変更が自動変更されない問題が解決できます。

参考：https://blog.mosuke.tech/entry/2019/06/21/kustomize/

# 環境
* GKE 1.14.10-gke.27
* Kustomize 3.4.0
* Cloud Build

# 詳細
## ディレクト構成
以下のようなディレクトリ構成を前提にしています。

```shell

k8s
└── ops
    ├── base
        ├── envoy
        │   ├── envoy.yaml
        │   ├── deployment.yaml
        │   └── service.yaml
        ├── grpc-gateway
        │   ├── ingress.yaml
        │   └── service.yaml
        ├── grpc-server
        │   └── service.yaml
        └── kustomization.yaml # configMapGeneratorの設定を入れる
```


## 設定
各種設定は、以下のようにしました。
### base/envoy/envoy.yaml
envoyの設定値を入れます。通常のConfigMapのようなリソースの指定は不要です。以下サンプルです。

```
admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9901
```

### base/kustomization.yaml
configMapGeneratorを使用し、上記のenvoy.yamlを指定します。

```yaml

resources:
- envoy/deployment.yaml
- envoy/service.yaml
- grpc-gateway/ingress.yaml
- grpc-gateway/service.yaml
- grpc-server/service.yaml

configMapGenerator:
- name: envoy-conf
  files:
    - envoy/envoy.yaml
```

### base/envoy/deployment.yaml
ConfigMapをVolume Mountします。必要そうなところだけ抜粋します。

```yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: envoy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: envoy
  template:
    metadata:
      labels:
        app: envoy
    spec:
      containers:
      - name: envoy
        image: envoyproxy/envoy-alpine:v1.9.1
        ports:
        - name: https
          containerPort: 8080
        volumeMounts:
        - name: envoy-conf
          mountPath: /etc/envoy # volumeMountsの指定。/etc/envoy/にenvoy.yamlがmountされる。
      volumes:
      - name: envoy-conf
        configMap:
          name: envoy-conf # configMapGeneratorで指定したNameを指定
          items:
          - key: envoy.yaml
            path: envoy.yaml
```

# まとめ
* 人のオペレーションはなるべく減らしたいので、ConfigMapを自動反映できるのは良い。
* ただし、この方式だとConfigMapが無限にたまっていきそうですが、世代管理とかやった方が良さげ。いい方法があれば教えてください。
* Rollbackは、kubectl editでConfigMapのリソース名を編集すればいけそうですが、事故りそうなので再デプロイするのが無難かもです。

# 参考
以下の文献を参考にさせていただきました。
[Kustomizeで環境ごとに異なるマニフェストを作る](https://blog.mosuke.tech/entry/2019/06/21/kustomize/)