🚢

Kustomizeに入門する

2025/01/01に公開

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