概要

kustomizeを利用するとベースのyamlからパッチをして、「ほとんどの部分は同じだが一箇所だけリソースが異なる」といったようなリソースを作成することができます。差分だけ記述すれば済むため、yamlの定義ははシンプルで管理しやすくなります。環境ごとに多数のリソースを扱うといった場合は特に有効です。

1 基本

kustomizeでnamespacenameのプリフィックス、ポストフィックス、labelannotationをつけることは簡単です。以下のファイルを用意します。

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

kustomization.yaml

resources:
- deployment.yaml
namespace: myns
namePrefix: pre-
nameSuffix: -suf
commonLabels:
  label1: lab1
  label2: lab2
commonAnnotations:
  annotation1: ann1
  annotation2: ann2

kustomizeを実行します。

$ kubectl kustomize ./
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    annotation1: ann1
    annotation2: ann2
  labels:
    label1: lab1
    label2: lab2
  name: pre-my-nginx-suf
  namespace: myns
spec:
  replicas: 2
  selector:
    matchLabels:
      label1: lab1
      label2: lab2
      run: my-nginx
  template:
    metadata:
      annotations:
        annotation1: ann1
        annotation2: ann2
      labels:
        label1: lab1
        label2: lab2
        run: my-nginx
    spec:
      containers:
      - image: nginx
        name: my-nginx
        ports:
        - containerPort: 80

kustomization.yamlの指定通りにnamenamespaceが挿入されていることが分かります。commonAnnotationによってDeploymentのmetadataはもちろんですがpodTemplateのmetadataにも挿入されます。commonLabelsについても同様ですが、selectorにも挿入される点がcommonAnnotationとはことなります。

2 configMapGenerator

2-1 基本

configMapGeneratorを利用するとfilesに指定したファイルから簡単にconfigMapを生成することができます。

foo.propaerties

FOO=foo

hoge.propaerties

HOGE=hoge

kustomization.yaml

configMapGenerator:
- name: example-configmap-1
  files:
  - hoge.properties
  - foo.properties

この構成でコマンドを実行します。

$ kubectl kustomize ./
apiVersion: v1
data:
  foo.properties: |
        FOO=foo
  hoge.properties: |
        HOGE=hoge
kind: ConfigMap
metadata:
  name: example-configmap-1-gfc789ggc8

propertiesファイルに記載された内容がconfigMapdataとして登録されていることが分かります。nameには独特なhash値がサフィックスとして付与されていますが、この値はdataの値によって変わり、ランダム値というわけではありません。

2-2 Deploymentへの適用

configMapGeneratornameでdeploymentから参照することで、deploymentからcofigmapを使用させることができます。

以下のdeployment.yamlを用意します。kustomization.yaml*.propertyファイルは2-1と同様のため省略。

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

この状態でkustomizeします。

$ kubectl kustomize ./
apiVersion: v1
data:
  foo.properties: |
        FOO=foo
  hoge.properties: |
        HOGE=hoge
kind: ConfigMap
metadata:
  name: example-configmap-1-gfc789ggc8
---
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-gfc789ggc8
        name: config

configMapが生成されており、それがdeploymentの方で参照されているのがわかります。

3 secretGenerator

configMapGeneratorに似ていますが、secretsもsecretGeneratorを利用することで生成することができます。

password.txt

username=admin
password=secret

kustomization.yaml

secretGenerator:
- name: example-secret-1
  files:
  - password.txt

この状態でkustomizeします。

$ kubectl kustomize ./
apiVersion: v1
data:
  password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg==
kind: Secret
metadata:
  name: example-secret-1-2kdd8ckcc7
type: Opaque

configMapGenerator同様dataの値によってnameにサフィックスが付きます。secretの場合はdataの要素がbase64エンコードされています。

deploymentから参照可能な点もconfigMapGenerator同様です。

4 generatorOptions

generatorOptionsを利用するとconfigMapGeneratorsecretGeneratorで生成するリソースに共通の設定をまとめて定義することが可能です。

kustomization.yaml

configMapGenerator:
- name: example-configmap-3
  literals:
  - FOO=Bar
- name: example-configmap-4
  literals:
  - FOO=Bar
secretGenerator:
- name: example-secret-1
  files:
  - password.txt
generatorOptions:
  disableNameSuffixHash: true
  labels:
    type: generated
  annotations:
    note: generated

password.txtはsecretGeneratorで定義したものと同様のため省略します。この状態でkustomizeします。

$ kubectl kustomize ./
apiVersion: v1
data:
  FOO: Bar
kind: ConfigMap
metadata:
  annotations:
    note: generated
  labels:
    type: generated
  name: example-configmap-3
---
apiVersion: v1
data:
  FOO: Bar
kind: ConfigMap
metadata:
  annotations:
    note: generated
  labels:
    type: generated
  name: example-configmap-4
---
apiVersion: v1
data:
  password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg==
kind: Secret
metadata:
  annotations:
    note: generated
  labels:
    type: generated
  name: example-secret-1
type: Opaque

disableNameSuffixHashによって各リソースのnameのサフィックスが無効化されています。またconfigmap/secretに共通のlabels/annotations定義が付与されています。

5 patchesStrategicMerge

以下のようなyamlを準備します。

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

increase_replicas.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 3

set_memory.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  template:
    spec:
      containers:
      - name: my-nginx
        resources:
          limits:
            memory: 512Mi

kustomization.yaml

resources:
- deployment.yaml
patchesStrategicMerge:
- increase_replicas.yaml
- set_memory.yaml

kustomizeを実行します。

kubectl kustomize ./
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

memorylimitsset_memory.yamlから、レプリカ数がincrease_replicas.yamlから参照されていることがわかります。

6 patchesJson6902

patchesStrategicMergeはすべてのリソース、フィールドをサポートしているわけではありません。任意のフィールドの変更を行う場合にはpatchesJson6902を利用します。replace/add/remove/move/copyといった操作が可能です。

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:
      moved: target
      copied: target
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
        env:
          - name: FOO
            value: replaced
          - name: BAR
            value: removed

kustomization.yaml

resources:
- deployment.yaml

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

patch.yaml

- op: replace
  path: /spec/replicas
  value: 3
- op: replace
  path: /spec/template/spec/containers/0/env/0/value
  value: "var"
- op: add
  path: /spec/template/spec/containers/0/hoge
  value: "fuga"
- op: remove
  path: /spec/template/spec/containers/0/env/1
- op: move
  from: /spec/template/spec/moved
  path: /spec/template/spec/containers/0/moved
- op: copy
  from: /spec/template/spec/copied
  path: /spec/template/spec/containers/0/copied

上記yamlを準備しkustomizeします。

$ kubectl kustomize ./
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:
      - copied: target
        env:
        - name: FOO
          value: var
        hoge: fuga
        image: nginx
        moved: target
        name: my-nginx
        ports:
        - containerPort: 80
      copied: target

patchesStrategicMergeで行ったレプリカ数の変更(replace)がpatchesJson6902の場合でも行えていることが分かります。

要素追加(add)を行いたい場合にはpathに任意のパスとvalueを設定します、出力結果にhoge要素が追加されていることから効果が分かります。

要素削除(remove)の場合にはpathのみ指定します。元のdeployment.yamlからenvの1番目の要素が消えていることが分かります。

要素移動(move)する場合にはfrompath要素により行います。もともとspec直下にあったmoved要素がcoutainers[0]へ移動していることが分かります。

要素複製(copy)もmoveと同様frompathを指定します。copyの場合にはspec直下の値はそのまま残っている点がmoveと異なります。

参考までにJson6902に仕様は以下となります。 https://datatracker.ietf.org/doc/html/rfc6902

7 vars

varsは、yaml中の対象の値で指定の文字列を置き換えることができます。

以下のファイルを準備します。

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)"]

kustomization.yaml

namePrefix: dev-
nameSuffix: "-001"

resources:
- deployment.yaml
- service.yaml

vars:
- name: MY_SERVICE_NAME
  objref:
    kind: Service
    name: my-nginx
    apiVersion: v1

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx

以上のファイルを用意しkustomizeします。

$ kubectl kustomize ./
apiVersion: v1
kind: Service
metadata:
  labels:
    run: my-nginx
  name: dev-my-nginx-001
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx
---
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

kustomization.yamlで定義したとおり、ServiceとDeployment両方のnameにプリフィックスとサフィックスが付与されています。また注目すべきはDeploymentのcommandです。kustomize前には$(MY_SERVICE_NAME)となっていた部分がServiceのnameと同じ値で置き換えられています。

8 configurations

configurationsを利用すると任意のリソースに対してkustomization.yamlで定義した変換ルールを適用できます。以下のyamlを準備します。

resources.yaml

apiVersion: animal/v1
kind: Gorilla
metadata:
  name: gg
---
apiVersion: animal/v1
kind: AnimalPark
metadata:
  name: ap
spec:
  gorillaRef:
    name: gg
    kind: Gorilla
    apiVersion: animal/v1

nameReference.yaml

nameReference:
  - kind: Gorilla
    fieldSpecs:
      - kind: AnimalPark
        path: spec/gorillaRef/name

kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - resources.yaml

namePrefix: sample-

configurations:
  - nameReference.yaml

この状態でkustomizeすると以下のようになります。

$ kubectl kustomize ./
apiVersion: animal/v1
kind: AnimalPark
metadata:
  name: sample-ap
spec:
  gorillaRef:
    apiVersion: animal/v1
    kind: Gorilla
    name: sample-gg
---
apiVersion: animal/v1
kind: Gorilla
metadata:
  name: sample-gg

出力結果のmetadata.nameについてはkustomization.yamlnamePrefixで定義したとおりのプリフィックスが付与されています。しかし、spec.gorillaRef.nameについてはnameReference.yamlで対象としているためにプリフィックスが付与されています。kustomization.yamlと同じ変換ルールを異なる要素にも適用したい場合に有用です。

9 images

対象のリソースのimageをパッチする場合にはimagesを使用します。以下のyamlを準備します。

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

kustomization.yaml

resources:
- deployment.yaml
images:
- name: nginx
  newName: alpine
  newTag: "3.6"

この状態でkustomizeすると以下のようになります。

$ 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: alpine:3.6
        name: my-nginx
        ports:
        - containerPort: 80

kustomization.yamlの通りimageがパッチされています。imagesは配列で指定可能なため、複数のコンテナのimageをパッチすることも可能です。imagesにはあくまでimagenameを入れるようにしてください。リソースのnameではありません。