Kustomizeを運用に組み込んでみた

この記事は ウェブクルー Advent Calendar 2019 23日目の記事です。
昨日は@wcsakuraiさんの「Cloud RunとSlackBotで作るおすすめランチスポットボット」ってお話でした。

## はじめに
GKEの開発、テスト、本番の環境毎に異なる設定や環境変数を用いることがあり、Kustomizeを導入したので紹介します。

## Kustomizeとは
Kubernetesのyamlを効率よく運用するのに特化したパッケージングツールです。
`kubectl`に組み込まれることを前提に開発が進められてきており、`kubectl 1.14`で組み込まれました。

基本的な使い方はテンプレートのyamlに対して、各環境毎に変更する設定を記述したパッチを当てることで、一つのyamlを出力します。
パッチはKubernetesのyamlと同じ形式で作成し、テンプレートの内容を変更する要素のみ記述します。
また、環境毎に新規のリソースを加えることもできます。
例えば、本番環境にのみ Horizontal Pod Autoscaler 適用して、開発、テスト環境には適用しないといったことができます。

- 公式
  - https://kustomize.io/
- Github
  - https://github.com/kubernetes-sigs/kustomize

## Helm と Kustomize
Kustomizeの調査をしていく中で`Helm`も候補に上がりましたが、主に以下の理由で`Kustomize`を選択しました。

- 課題がyamlの管理に関することだったためGKEにあるリソースは範囲外だった
- 社内のリソース的にHelmを運用していくのが難しかった
- 導入を検討していた時期にkubectlコマンドに組み込まれて1.14のkubectlで使用できるようになった

## 導入前
- 各環境のdeploymentでreplicasの設定が同じ（開発環境とかはコストを抑えたい）
- 環境毎のconfigmapは同じフォルダに格納されていて分かりづらい
  - 環境毎で分ける必要がある時は、`dev`, `stg`, `prod`とかをファイル名に含めていた
  - hpaは本番にのみ適用してる
- yamlを変更する時は使用する時は各環境のGCPプロジェクト内にある作業サーバーに入ってkubectlコマンドを叩く必要があった
- 内製ツールの存在
  - 一つのフォルダに全てのyamlが格納されており事故防止のため環境毎に使用するyamlをまとめていた
  - 環境毎にDocker imageをbuildしているため、使用するimageのtagをデプロイ先に合わせて置換していた
  - 環境毎に変更したい場合は内製ツールのコードを修正する必要があった
- 手作業デプロイ中にこういった課題を解決しているツールがないか考えていた

例：導入前のyaml構成

```
k8s_yml
├── nginx-deployment.yml
├── nginx-service.yml
├── nginx-hpa.yml
├── app-deployment.yml
├── app-service.yml
├── app-hpa.yml
├── dev-nginx-configmap.yml
├── dev-app-secret.yml
├── dev-app-configmap.yml
├── prod-nginx-configmap.yml
├── prod-app-secret.yml
├── prod-app-configmap.yml
├── stg-nginx-configmap.yml
├── stg-app-secret.yml
└── stg-app-configmap.yml.cmd
```

実際はこれ以上にymlがあり、手作業デプロイ時のミスが起きやすい状態だった（幸いにもまだミスは起きていませんが。。。）

## 導入後
- develop（場合によってはstagingも）はreplicasを1でproduciotnを2に設定
- テンプレート用と各環境用に別れてyamlを管理
  - 環境毎に分かれていて、productionにのみhpaが適用されているのが分かりやすい
- 内製ツールを除却し、手作業でのデプロイをCI/CDを用いたデプロイに変更
  - デプロイ作業の時間を短縮  
  - 手作業による事故を防止  

例：導入後のyaml構成

```
k8s_yaml
├── base
│   ├── app
│   │   ├── deployment.yaml
│   │   ├── kustomization.yaml
│   │   └── service.yaml
│   └── nginx
│       ├── deployment.yaml
│       ├── kustomization.yaml
│       └── service.yaml
└── overlays
    ├── develop
    │   ├── app
    │   │   ├── configmap.yaml
    │   │   ├── deployment.yaml
    │   │   ├── kustomization.yaml
    │   │   └── secret.yaml
    │   └── nginx
    │       ├── configmap.yaml
    │       ├── deployment.yaml
    │       └── kustomization.yaml
    ├── production
    │   ├── app
    │   │   ├── configmap.yaml
    │   │   ├── deployment.yaml
    │   │   ├── hpa.yaml
    │   │   ├── kustomization.yaml
    │   │   └── secret.yaml
    │   └── nginx
    │       ├── configmap.yaml
    │       ├── deployment.yaml
    │       ├── hpa.yaml
    │       └── kustomization.yaml
    └── staging
        ├── app
        │   ├── configmap.yaml
        │   ├── deployment.yaml
        │   ├── kustomization.yaml
        │   └── secret.yaml
        └── nginx
            ├── configmap.yaml
            ├── deployment.yaml
            └── kustomization.yaml
```

## 運用してみて
検証を始めた時からこれなら運用に組み込めると思っていましたが、導入して良かったと思っています。
また、Kustomizeは使い方がシンプルなので既にあるyamlファイルに対しても導入がしやすかったのが良いなと思いました。
まだ導入できていないサービスもありますので、今後は範囲を広げていく予定です。
Kustomizeの導入を検討・検証している方の参考になればと思います。

明日は@tatsuyanamikiさんになります。よろしくお願いします！