なになれ

IT系のことを記録していきます

KubernetesマニフェストでDRYを守るためのkustomizeの使い方

Kubernetesマニフェストyamlファイルなので、ファイルの数が多くなるにしたがって記述の重複も多くなって困ります。
kustomizeを利用すると、重複をなくすDRYな状態を保てます。
その他にもKubernetesマニフェストを記述する際に便利な機能があります。
本投稿では、kustomizeの使い方について紹介します。
github.com

目次

インストール方法

macの場合はbrewでインストールできます。

$ brew install kustomize

kubectlでもkubectl kustomizeというサブコマンドでkustomizeを利用できます。
ただkustomizeのバージョンが古いので個別にkustomizeをインストールすることをオススメします。

重複をなくす

kustomizeには、overlayという仕組みがあります。
開発環境や本番環境毎に差分のkubernetesマニフェストを用意して、差分の箇所だけ変更できます。

例を以下に示します。

baseについて

まずはフォルダ構成を以下のようにします。
staging環境とproduction環境で一部の差異があることを想定したディレクトリ構成です。

~/app
├── base
│   ├── kustomization.yaml
│   └── pod.yaml
└── overlays
    ├── production
    │   ├── kustomization.yaml
    │   └── pod.yaml
    └── staging
        ├── kustomization.yaml
        └── pod.yaml

baseのディレクトリに元になるyamlを配置します。

base/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  app: example
resources:
- pod.yaml

kustomization.yamlはkustomizeの設定用のリソースファイルです。kustomizeを利用するにはこのファイルが必要です。
resourcesでは、kustomizeの処理に含まれるyamlファイルを指定します。
commonLabelsでkustomizeで処理するファイル全体に共通のlabel指定を行うことができます。

base/pods.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: example
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:1
        ports:
        - containerPort: 80

kubernetesyamlを書きます。
commonLabelsで指定しているので、labelの記述は不要です。

stagingについて

staging環境における構成です。

overlays/staging/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- path: pod.yaml
images:
- name: nginx
  newTag: "1.18"

resoucesでbaseのディレクトリを指定します。
patchesで差分のyamlファイルを指定します。
imagesではイメージタグの差分を個別に指定することができます。

下記のようにコマンドでkustomization.yamlimagesを変更することが可能です。

$ kustomize edit set image nginx:1.19

overlays/staging/pod.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 2

replicasを差分として追加します。
apiVersionなどの記述は変更箇所を特定するために必要です。

kubectl applyをするには以下のようにします。

$ kustomize build overlays/staging | kubectl apply -f -

kustomize buildでkustomizeの処理を適用したKubernetesマニフェストが出力されます。

productionについて

production環境における構成です。

overlays/production/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
- path: pod.yaml
images:
- name: nginx
  newTag: "1.19"
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 4

ConfigMapの変更を反映する

kustomizeのconfigMapGeneratorを使用すると、ConfigMapを変更してもそれを参照しているPodにConfigMapの変更が反映されないという事象に対応できます。
これはconfigMapGeneratorを使うことでconfigMapの変更をトリガーにして、kubernetesリソースのローリングアップデートを機能させることができるためです。

例を以下に示します。
baseの構成は先ほどと変わらず、overlaysを修正します。

overlays/production/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
configMapGenerator:
- envs:
  - config.env
  name: config
secretGenerator:
- envs:
  - secret.env
  name: secret
  type: Opaque
patches:
- path: pod.yaml
images:
- name: nginx
  newTag: "1.19"

configMapGenerator環境変数ファイルを指定します。
secretGeneratorもありますが、configMapGeneratorと使い方はほぼ変わりません。

overlays/production/pod.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 4
  template:
    spec:
      containers:
      - name: nginx
        envFrom:
        - configMapRef:
            name: config
        - secretRef:
            name: secret

envFromでは、各Generatorのnameを指定します。

overlays/production/config.env

ENV=production

overlays/production/secret.env

USER=production
PASSWORD=production

secretの暗号化はsecretGeneratorで実施してくれます。
Secretリソースを作る時のように暗号化した値の指定は不要です。

kustomize buildすると以下の出力になります.

apiVersion: v1
data:
  ENV: production
kind: ConfigMap
metadata:
  name: config-fctgtgtt22
---
apiVersion: v1
data:
  PASSWORD: cHJvZHVjdGlvbg==
  USER: cHJvZHVjdGlvbg==
kind: Secret
metadata:
  name: secret-52d6mkchk6
type: Opaque
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: example
  name: nginx
spec:
  replicas: 4
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - envFrom:
        - configMapRef:
            name: config-fctgtgtt22
        - secretRef:
            name: secret-52d6mkchk6
        image: nginx:1.19
        name: nginx
        ports:
        - containerPort: 80

configMapのnameのsuffixに識別子が付与されています。
configの内容が変更される毎にこの識別子が変更されるので、kubectl applyをするとローリングアップデートが行われます。
また、secretの値が暗号化されています。

まとめ

kustomizeを使えばKubernetesマニフェストの記述が楽になります。
kustomizeには今回紹介したこと以外にも機能があるので公式のドキュメントを見てみると良いと思います。