Kustomizeに入門する
Kubernetes のツールである Kustomize を試してみます。
Kustomize とは
Kustomize はマニフェストファイルのテンプレートから、一部を変更したマニフェストファイルを生成できるツールです。開発・本番など、環境ごとに同様のリソースをデプロイしたい場合などに、環境ごとに同じファイルを何個も用意することなく、共通で使用できる部分を切り出して、環境間で差分がある設定値のみを管理することができます。
ユースケース
Git で Kubernetes のマニフェストファイルを管理し、GitHub Actions や Argo CD といった仕組みを用いて Kubernetes クラスタにマニフェストを適用する、所謂 CIOps や GitOps といったデプロイ戦略を採用している場合、Kubernetes リソースを管理するリポジトリのブランチ戦略およびディレクトリ構成としては、以下の2パターンが考えられます。
- 環境ごとのブランチを用意する
- 環境ごとのディレクトリを用意する
環境ごとのブランチを用意するパターンの場合、たとえば develop ブランチにマージされたマニフェストファイルを開発クラスタに適用し、正しい動作を確認できたあとに main ブランチにマージして本番クラスタに適用、という流れになります。この方法では、環境ごとにマニフェストファイルの差分が意図せず作られにくい/意図して作りにくいという点がメリット/デメリットであると言えます。
環境ごとのブランチを用意する
環境ごとのディレクトリを用意するパターンでは、環境ごとに細かい設定値を変えつつマニフェストの適用を行うことができます。しかし、環境ごとにほぼ同じ内容のマニフェストファイルを用意しなければならず、意図していない設定項目で差分が生まれてしまう可能性があります。
環境ごとにディレクトリを用意する
Kustomize では、環境間で共通の設定値をテンプレート化し、差分の情報のみを環境ごとのディレクトリに持たせることができるため、後者の構成において特に活用することができるでしょう。
Kustomizeで共通設定と環境ごとの差分を管理する構成
事前準備
当記事の使用環境
Kubernetes クラスタは Google Cloud の GKE を使用します。Kubernetes および Kustomize のバージョンは以下を使用しています。
$ kubectl version
Client Version: v1.29.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.30.6-gke.1125000
クラスタの作成
GKE の限定公開クラスタを使用します。Autopilot モードのクラスタ(もしくは Standard モードのゾーンクラスタ)は請求先アカウントにつき $74.40/月 の無料枠があるので、個人の学習用途であればかなり安価に利用できます。
以下の記事のように Terraform でクラスタを作成できるようにしておくと、検証用途のクラスタを手軽に作成・削除することができて便利です。
現在は DNS エンドポイントという仕組みでコントロールプレーンに接続することができるため、上記記事で作成しているような踏み台 VM は必要ありません。
DNS エンドポイントについては以下の記事をご一読ください。
Kustomize のインストール
公式ドキュメントの方法に従ってインストールします。
Namespace の作成
当記事では開発環境と本番環境の2つの環境へのデプロイを想定して Kustomize を使用しますが、それぞれの環境用にクラスタを2つ用意することはせず、Namespace を使用して仮想的に環境を分離します。
# Namespace を2つ作成する
$ kubectl create namespace development
$ kubectl create namespace production
使用するファイル
ディレクトリ構成
.
├── base # Kustomize のテンプレートとなるファイルを格納
│ ├── deployment.yaml
│ └── kustomization.yaml
└── overlays # Kustomize で書き換える内容を記述するファイルを格納
├── development
│ ├── kustomization.yaml
│ └── patch-deployment.yaml
└── production
├── kustomization.yaml
└── patch-deployment.yaml
base ディレクトリ(共通テンプレート)
base ディレクトリには、テンプレートとして環境ごとに共通の設定値を記述したマニフェストファイルを作成します。
当記事では、Nginx コンテナを含む Pod を管理する Deployment を作成します。このファイルではリソースを作成する Namespace と、Pod 数を指定する ReplicaSet が設定されていません。この2項目について Kustomize を使用して環境ごとの値を設定していきます。
# ./base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests:
cpu: "250m"
base ディレクトリにはテンプレートのほかに、kustomization.yaml という Kustomize の設定ファイルを配置します。このファイルには、変更対象のテンプレートファイルの名前を記載します。
# ./base/kustomization.yaml
resources:
- deployment.yaml
overlays/development ディレクトリ(開発環境の差分)
overlays ディレクトリには、環境ごとに変更する設定値を記載したファイルを格納します。まずは Namespace「development」に作成する Deployment 用のファイルを作成します。
patch-deployment.yaml
通常の Deployment と同じ形式でマニフェストファイルを記述しますが、対象となるテンプレートを特定するための metadata.name
項目と、テンプレートから変更する設定値のみを記述します。
# ./overlays/development/patch-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1 # base に replicas を追加
kustomization.yaml
環境ごとのディレクトリにも kustomization.yaml を作成します。ここでは resources
として書き換え対象のテンプレートがあるディレクトリを、patches
として書き換え内容を記載したファイルを記述します。
リソースを作成する Namespace についてはこのファイルで指定することで、環境用のディレクトリ配下にあるすべてのファイルでこの Namespace による書き換えを適用することができます。
# ./overlays/development/kustomization.yaml
resources:
- ../../base/ # 変更対象のテンプレートがあるディレクトリを指定
namespace: development # Namespace を設定
patches:
- path: patch-deployment.yaml # Deployment の内容を変更するファイルを指定
overlays/production ディレクトリ(本番環境の差分)
patch-deployment.yaml
Namespace「production」用の設定値を記載します。本番環境を想定するので、こちらではレプリカ数を3に設定し、またCPU の設定値を少しだけ増やしてみます。
# ./overlays/production/patch-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3 # base に replicas を追加
template:
spec:
containers:
- name: nginx
resources:
requests:
cpu: "500m" # base の requests.cpu を変更
kustomization.yaml
development 環境同様に、kustomization.yaml を記述します。namespace
の設定値のみ変えています。
# ./overlays/production/kustomization.yaml
resources:
- ../../base/ # 変更対象のテンプレートがあるディレクトリを指定
namespace: production # Namespace を設定
patches:
- path: patch-deployment.yaml # Deployment の内容を変更するファイルを指定
デプロイ
development 環境
kustomize build
コマンドでテンプレートを書き換えた内容を出力することができます。
$ kustomize build overlays/development/
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: development # 書き換えた部分
spec:
replicas: 1 # 書き換えた部分
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- image: nginx:1.27
name: nginx
ports:
- containerPort: 80
resources:
requests:
cpu: 250m
kubectl apply
コマンドの -k
オプションで、Kustomize で書き換えたマニフェストファイルを適用します。
$ kubectl apply -k overlays/development/
deployment.apps/myapp created
Kustomize で書き換えた通り、Namespace「development」にレプリカ数1の Deployment が作成されています。
$ kubectl get deployments -n development
NAME READY UP-TO-DATE AVAILABLE AGE
myapp 1/1 1 1 2m19s
Deployment の詳細を確認すると、development 環境では CPU リクエストを変更していないため、テンプレートで指定した 250m
が設定されています。
$ kubectl describe deployments -n development myapp
# 出力抜粋
Pod Template:
Labels: app=myapp
Containers:
nginx:
Image: nginx:1.27
Port: 80/TCP
Host Port: 0/TCP
Limits:
ephemeral-storage: 1Gi
Requests:
cpu: 250m
ephemeral-storage: 1Gi
memory: 256Mi
production 環境
production 環境では、Kustomize によって3つの項目が書き換えられています。
$ kustomize build overlays/production/
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: production # 書き換えた部分
spec:
replicas: 3 # 書き換えた部分
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- image: nginx:1.27
name: nginx
ports:
- containerPort: 80
resources:
requests:
cpu: 500m # 書き換えた部分
以下のコマンドで production 環境のデプロイを実施します。
$ kubectl apply -k overlays/production/
deployment.apps/myapp created
Kustomize で書き換えた通り、Namespace「production」にレプリカ数3の Deployment が作成されています。
$ kubectl get deployments -n production
NAME READY UP-TO-DATE AVAILABLE AGE
myapp 3/3 3 3 3m7s
Deployment の詳細を確認すると、CPU リクエストの設定値が Kustomize で書き換えた 500m
になっています。
$ kubectl describe deployments -n production myapp
# 出力抜粋
Pod Template:
Labels: app=myapp
Containers:
nginx:
Image: nginx:1.27
Port: 80/TCP
Host Port: 0/TCP
Limits:
ephemeral-storage: 1Gi
Requests:
cpu: 500m # Kustomize で設定された値
ephemeral-storage: 1Gi
memory: 512Mi
リソースの削除
kubectl apply
コマンドの -k
オプションで環境ごとのリソースを削除します。
$ kubectl delete -k overlays/development/
deployment.apps "myapp" deleted
$ kubectl delete -k overlays/production/
deployment.apps "myapp" deleted
Discussion