Kustomizeを使用したKubernetesオブジェクトの宣言的管理

Kustomizeは、kustomizationファイルを用いてKubernetesオブジェクトをカスタマイズするためのスタンドアロンツールです。

1.14以降、kubectlもkustomizationファイルを使用したKubernetesオブジェクトの管理をサポートしています。 kustomizationファイルを含むディレクトリ内のリソースを表示するには、次のコマンドを実行します:

kubectl kustomize <kustomization_directory>

これらのリソースを適用するには、--kustomizeまたは-kフラグを指定してkubectl applyを実行します:

kubectl apply -k <kustomization_directory>

始める前に

kubectlをインストールしてください。

Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:

バージョンを確認するには次のコマンドを実行してください: kubectl version.

Kustomizeの概要

Kustomizeは、Kubernetesの設定をカスタマイズするためのツールです。 アプリケーションの設定ファイルを管理するために、次の機能があります:

  • 他のソースからリソースを生成する
  • リソースに対して横断的なフィールドを設定する
  • リソースのコレクションを構成およびカスタマイズする

リソースの生成

ConfigMapとSecretは、Podなど他のKubernetesオブジェクトによって使用される設定や機密データを保持します。 ConfigMapやSecretの信頼できる情報源は、通常、.propertiesファイルやSSH鍵ファイルなど、クラスター外部にあります。 Kustomizeには、secretGeneratorconfigMapGeneratorがあり、ファイルやリテラルからSecretやConfigMapを生成することができます。

configMapGenerator

ファイルからConfigMapを生成するには、configMapGeneratorfilesリストにエントリを追加します。 以下は、.propertiesファイルからデータ項目を含むConfigMapを生成する例です:

# application.propertiesファイルを作成
cat <<EOF >application.properties
FOO=Bar
EOF

cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
  files:
  - application.properties
EOF

生成されたConfigMapは、次のコマンドで確認できます:

kubectl kustomize ./

生成されたConfigMapは次のとおりです:

apiVersion: v1
data:
  application.properties: |
    FOO=Bar    
kind: ConfigMap
metadata:
  name: example-configmap-1-8mbdf7882g

envファイルからConfigMapを生成するには、configMapGeneratorenvsリストにエントリを追加します。 以下は、.envファイルからデータ項目を含むConfigMapを生成する例です:

# .envファイルを作成
cat <<EOF >.env
FOO=Bar
EOF

cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-1
  envs:
  - .env
EOF

生成されたConfigMapは、次のコマンドで確認できます:

kubectl kustomize ./

生成されたConfigMapは次のとおりです:

apiVersion: v1
data:
  FOO: Bar
kind: ConfigMap
metadata:
  name: example-configmap-1-42cfbf598f

備考:

.envファイル内の各変数は、生成するConfigMap内で個別のキーになります。 これは、application.propertiesという名前のファイル(とそのすべてのエントリ)を単一のキーの値として埋め込む前の例とは異なります。

ConfigMapは、リテラルのキーと値のペアからも生成できます。 リテラルのキーと値のペアからConfigMapを生成するには、configMapGeneratorのliteralsリストにエントリを追加します。 以下は、キーと値のペアからデータ項目を含むConfigMapを生成する例です。

cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-2
  literals:
  - FOO=Bar
EOF

生成されたConfigMapは、次のコマンドで確認できます:

kubectl kustomize ./

生成されたConfigMapは次のとおりです:

apiVersion: v1
data:
  FOO: Bar
kind: ConfigMap
metadata:
  name: example-configmap-2-g2hdhfc6tk

生成されたConfigMapをDeploymentで使用するには、configMapGeneratorの名前で参照します。 Kustomizeは、この名前を自動的に生成された名前に置き換えます。

これは、生成されたConfigMapを使用するDeploymentの例です:

# application.propertiesファイルを作成
cat <<EOF >application.properties
FOO=Bar
EOF

cat <<EOF >deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: my-app
        volumeMounts:
        - name: config
          mountPath: /config
      volumes:
      - name: config
        configMap:
          name: example-configmap-1
EOF

cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
configMapGenerator:
- name: example-configmap-1
  files:
  - application.properties
EOF

ConfigMapとDeploymentを生成します:

kubectl kustomize ./

生成されたDeploymentは、生成されたConfigMapを名前で参照します:

apiVersion: v1
data:
  application.properties: |
    FOO=Bar    
kind: ConfigMap
metadata:
  name: example-configmap-1-g4hk9g2ff8
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: my-app
  name: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - image: my-app
        name: app
        volumeMounts:
        - mountPath: /config
          name: config
      volumes:
      - configMap:
          name: example-configmap-1-g4hk9g2ff8
        name: config

secretGenerator

Secretは、ファイルまたはリテラルのキーと値のペアから生成できます。 ファイルからSecretを生成するには、secretGeneratorfilesリストにエントリを追加します。 以下は、ファイルからデータ項目を含むSecretを生成する例です:

# password.txtファイルを作成
cat <<EOF >./password.txt
username=admin
password=secret
EOF

cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-1
  files:
  - password.txt
EOF

生成されたSecretは次のとおりです:

apiVersion: v1
data:
  password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg==
kind: Secret
metadata:
  name: example-secret-1-t2kt65hgtb
type: Opaque

リテラルのキーと値のペアからSecretを生成するには、secretGeneratorliteralsリストにエントリを追加します。 以下は、キーと値のペアからデータ項目を含むSecretを生成する例です:

cat <<EOF >./kustomization.yaml
secretGenerator:
- name: example-secret-2
  literals:
  - username=admin
  - password=secret
EOF

生成されたSecretは次のとおりです:

apiVersion: v1
data:
  password: c2VjcmV0
  username: YWRtaW4=
kind: Secret
metadata:
  name: example-secret-2-t52t6g96d8
type: Opaque

ConfigMapと同様に、生成されたSecretは、secretGeneratorの名前を参照することでDeploymentで使用できます:

# password.txtファイルを作成
cat <<EOF >./password.txt
username=admin
password=secret
EOF

cat <<EOF >deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    app: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: app
        image: my-app
        volumeMounts:
        - name: password
          mountPath: /secrets
      volumes:
      - name: password
        secret:
          secretName: example-secret-1
EOF

cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
secretGenerator:
- name: example-secret-1
  files:
  - password.txt
EOF

generatorOptions

生成されたConfigMapとSecretには、コンテンツハッシュのサフィックスが付加されます。 これにより、コンテンツが変更されたときに新しいConfigMapまたはSecretが生成されることが保証されます。 サフィックスを付加する挙動を無効にするには、generatorOptionsを使用できます。 さらに、生成されたConfigMapとSecretに対して横断的なオプションを指定することも可能です。

cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: example-configmap-3
  literals:
  - FOO=Bar
generatorOptions:
  disableNameSuffixHash: true
  labels:
    type: generated
  annotations:
    note: generated
EOF

kubectl kustomize ./を実行して、生成されたConfigMapを確認します:

apiVersion: v1
data:
  FOO: Bar
kind: ConfigMap
metadata:
  annotations:
    note: generated
  labels:
    type: generated
  name: example-configmap-3

横断的なフィールドの設定

プロジェクト内のすべてのKubernetesリソースに対して横断的なフィールドを設定することは非常に一般的です。 横断的なフィールドを設定するいくつかのユースケースは次のとおりです:

  • すべてのリソースに同じNamespaceを設定する
  • 同じ名前のプレフィックスまたはサフィックスを追加する
  • 同じラベルのセットを追加する
  • 同じアノテーションのセットを追加する

以下は例です:

# deployment.yamlを作成
cat <<EOF >./deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
EOF

cat <<EOF >./kustomization.yaml
namespace: my-namespace
namePrefix: dev-
nameSuffix: "-001"
labels:
  - pairs:
      app: bingo
    includeSelectors: true 
commonAnnotations:
  oncallPager: 800-555-1212
resources:
- deployment.yaml
EOF

kubectl kustomize ./を実行して、これらのフィールドがすべてDeploymentリソースに設定されていることを確認します:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    oncallPager: 800-555-1212
  labels:
    app: bingo
  name: dev-nginx-deployment-001
  namespace: my-namespace
spec:
  selector:
    matchLabels:
      app: bingo
  template:
    metadata:
      annotations:
        oncallPager: 800-555-1212
      labels:
        app: bingo
    spec:
      containers:
      - image: nginx
        name: nginx

リソースの集約とカスタマイズ

プロジェクト内で一連のリソースを集約し、同じファイルやディレクトリ内で管理することは一般的です。 Kustomizeは、異なるファイルからリソースを集約し、それらにパッチやその他のカスタマイズを適用することをサポートしています。

集約

Kustomizeは、異なるリソースの集約をサポートしています。 kustomization.yamlファイルのresourcesフィールドは、構成に含めるリソースのリストを定義します。 resourcesリストにリソースの構成ファイルへのパスを設定します。 以下は、DeploymentとServiceで構成されるNGINXアプリケーションの例です:

# deployment.yamlファイルを作成
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
EOF

# service.yamlファイルを作成
cat <<EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx
EOF

# それらを集約するkustomization.yamlを作成
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF

kubectl kustomize ./の出力のリソースには、DeploymentとServiceの両方のオブジェクトが含まれます。

カスタマイズ

パッチを使用して、リソースにさまざまなカスタマイズを適用できます。 Kustomizeは、patchesフィールドを使用したStrategicMergeJson6902による異なるパッチメカニズムをサポートしています。 patchesは、ファイルまたはインライン文字列で、単一または複数のリソースを対象にできます。

patchesフィールドには、指定された順序で適用されるパッチのリストが含まれます。 パッチの対象となるリソースは、groupversionkindnamenamespacelabelSelectorannotationSelectorによって選択されます。

1つのことを行う小さなパッチが推奨されます。 たとえば、デプロイメントのレプリカ数を増やすパッチと、メモリ制限を設定する別のパッチを個別に作成します。 パッチ対象のリソースは、パッチファイルのgroupversionkindnameフィールドを使用してマッチングされます。

# deployment.yamlファイルを作成
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
EOF

# パッチ用のincrease_replicas.yamlを作成
cat <<EOF > increase_replicas.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 3
EOF

# 別のパッチ用のset_memory.yamlを作成
cat <<EOF > set_memory.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  template:
    spec:
      containers:
      - name: my-nginx
        resources:
          limits:
            memory: 512Mi
EOF

cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
patches:
  - path: increase_replicas.yaml
  - path: set_memory.yaml
EOF

kubectl kustomize ./を実行して、Deploymentを確認します:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - image: nginx
        name: my-nginx
        ports:
        - containerPort: 80
        resources:
          limits:
            memory: 512Mi

すべてのリソースやフィールドがstrategicMergeパッチをサポートしているわけではありません。 任意のリソース内の任意のフィールドの変更をサポートするために、KustomizeはJson6902によるJSONパッチの適用を提供しています。 Json6902パッチ対象の正しいリソースを見つけるには、kustomization.yamltargetフィールドを指定することが必須です。

たとえば、Deploymentオブジェクトのレプリカ数を増やすことは、Json6902パッチでも実行できます。 対象のリソースは、targetフィールドのgroupversionkindnameを使用してマッチングされます。

# deployment.yamlファイルを作成
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
EOF

# JSONパッチを作成
cat <<EOF > patch.yaml
- op: replace
  path: /spec/replicas
  value: 3
EOF

# kustomization.yamlを作成
cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml

patches:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: my-nginx
  path: patch.yaml
EOF

kubectl kustomize ./を実行して、replicasフィールドが更新されていることを確認します:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - image: nginx
        name: my-nginx
        ports:
        - containerPort: 80

パッチに加えて、Kustomizeは、パッチを作成せずに、コンテナイメージのカスタマイズや、他のオブジェクトからコンテナへのフィールド値の注入も提供します。 たとえば、kustomization.yamlimagesフィールドで新しいイメージを指定することで、コンテナ内で使用されるイメージを変更できます。

cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
EOF

cat <<EOF >./kustomization.yaml
resources:
- deployment.yaml
images:
- name: nginx
  newName: my.image.registry/nginx
  newTag: "1.4.0"
EOF

kubectl kustomize ./を実行して、使用されるイメージが更新されていることを確認します:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - image: my.image.registry/nginx:1.4.0
        name: my-nginx
        ports:
        - containerPort: 80

場合によっては、Pod内で実行されているアプリケーションが、他のオブジェクトからの設定値を使用する必要があるかもしれません。 たとえば、DeploymentオブジェクトのPodは、対応するService名をEnvから読み取るか、コマンド引数として読み取る必要があります。 kustomization.yamlファイルでnamePrefixまたはnameSuffixが追加されるとService名が変更される可能性があるため、コマンド引数にService名をハードコードすることは推奨されません。 このような用途のために、Kustomizeはreplacementsを通じてService名をコンテナに注入できます。

# deployment.yamlファイルを作成(ヒアドキュメントのデリミタを引用符で囲む)
cat <<'EOF' > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        command: ["start", "--host", "MY_SERVICE_NAME_PLACEHOLDER"]
EOF

# service.yamlファイルを作成
cat <<EOF > service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx
EOF

cat <<EOF >./kustomization.yaml
namePrefix: dev-
nameSuffix: "-001"

resources:
- deployment.yaml
- service.yaml

replacements:
- source:
    kind: Service
    name: my-nginx
    fieldPath: metadata.name
  targets:
  - select:
      kind: Deployment
      name: my-nginx
    fieldPaths:
    - spec.template.spec.containers.0.command.2
EOF

kubectl kustomize ./を実行して、コンテナに注入されたService名がdev-my-nginx-001であることを確認します:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dev-my-nginx-001
spec:
  replicas: 2
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - command:
        - start
        - --host
        - dev-my-nginx-001
        image: nginx
        name: my-nginx

ベースとオーバーレイ

Kustomizeには、ベースオーバーレイの概念があります。 ベースは、kustomization.yamlを含むディレクトリで、一連のリソースと関連するカスタマイズが含まれます。 ベースは、kustomization.yamlが内部に存在する限り、ローカルディレクトリまたはリモートリポジトリのディレクトリのいずれかになります。 オーバーレイは、他のkustomizationディレクトリをbasesとして参照するkustomization.yamlを含むディレクトリです。 ベースはオーバーレイを認識せず、複数のオーバーレイで使用できます。

オーバーレイディレクトリのkustomization.yamlは、複数のbasesを参照し、これらのベースで定義されたすべてのリソースを1つの構成に結合します。 さらに、特定の要件を満たすために、これらのリソースにカスタマイズを適用することも可能です。

以下はベースの例です:

# ベースを保持するディレクトリを作成
mkdir base
# base/deployment.yamlを作成
cat <<EOF > base/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
EOF

# base/service.yamlファイルを作成
cat <<EOF > base/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx
EOF
# base/kustomization.yamlを作成
cat <<EOF > base/kustomization.yaml
resources:
- deployment.yaml
- service.yaml
EOF

このベースは複数のオーバーレイで使用できます。 異なるオーバーレイで、異なるnamePrefixやその他の横断的なフィールドを追加できます。 以下は、同じベースを使用する2つのオーバーレイです:

mkdir dev
cat <<EOF > dev/kustomization.yaml
resources:
- ../base
namePrefix: dev-
EOF

mkdir prod
cat <<EOF > prod/kustomization.yaml
resources:
- ../base
namePrefix: prod-
EOF

Kustomizeを使用してオブジェクトを適用/表示/削除する方法

kubectlコマンドで--kustomizeまたは-kを使用して、kustomization.yamlによって管理されるリソースを認識します。 -kは、次のようにkustomizationディレクトリを指す必要があることに注意してください。

kubectl apply -k <kustomization directory>/

次のkustomization.yamlがあるとします:

# deployment.yamlファイルを作成
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
EOF

# kustomization.yamlを作成
cat <<EOF >./kustomization.yaml
namePrefix: dev-
labels:
  - pairs:
      app: my-nginx
    includeSelectors: true 
resources:
- deployment.yaml
EOF

次のコマンドを実行して、Deploymentオブジェクトdev-my-nginxを適用します:

> kubectl apply -k ./
deployment.apps/dev-my-nginx created

次のいずれかのコマンドを実行して、Deploymentオブジェクトdev-my-nginxを表示します:

kubectl get -k ./
kubectl describe -k ./

次のコマンドを実行して、Deploymentオブジェクトdev-my-nginxを、マニフェストが適用された場合のクラスターの状態と比較します:

kubectl diff -k ./

次のコマンドを実行して、Deploymentオブジェクトdev-my-nginxを削除します:

> kubectl delete -k ./
deployment.apps "dev-my-nginx" deleted

Kustomizeの機能リスト

フィールド説明
bases[]stringこのリスト内の各エントリは、kustomization.yamlファイルを含むディレクトリに解決される必要があります
commonAnnotationsmap[string]stringすべてのリソースに追加するアノテーション
commonLabelsmap[string]stringすべてのリソースとセレクターに追加するラベル
configMapGenerator[]ConfigMapArgsこのリスト内の各エントリはConfigMapを生成します
configurations[]stringこのリスト内の各エントリは、Kustomize Transformerの設定を含むファイルに解決される必要があります
crds[]stringこのリスト内の各エントリは、Kubernetes型のOpenAPI定義ファイルに解決される必要があります
generatorOptionsGeneratorOptionsすべてのConfigMapとSecretジェネレーターの動作を変更します
images[]Image各エントリは、パッチを作成せずに1つのイメージの名前、タグ、ダイジェストを変更するためのものです
labelsmap[string]string対応するセレクターを自動的に注入せずにラベルを追加します
namePrefixstringこのフィールドの値は、すべてのリソースの名前の前に付加されます
nameSuffixstringこのフィールドの値は、すべてのリソースの名前の後に付加されます
patchesJson6902[]Patchこのリスト内の各エントリは、KubernetesオブジェクトとJSONパッチに解決される必要があります
patchesStrategicMerge[]stringこのリスト内の各エントリは、KubernetesオブジェクトのStrategic Mergeパッチに解決される必要があります
replacements[]Replacementsリソースのフィールドから値をコピーして、指定された任意の数のターゲットに適用します
resources[]stringこのリスト内の各エントリは、既存のリソース設定ファイルに解決される必要があります
secretGenerator[]SecretArgsこのリスト内の各エントリはSecretを生成します
vars[]Var各エントリは、1つのリソースのフィールドからテキストをキャプチャするためのものです

次の項目