Kustomizeでvarsの代わりにreplacementsを使う

Kustomize v3.8までなら、varsを使うことで次のように特定の箇所の値を別の箇所に上書きすることができ、例えば

# test.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: test
  labels:
    app.kubernetes.io/name: THIS-IS-TEST-SERVICE-NAME # ☆この値を上書きに使いたい
spec:
  type: NodePort
  ports:
    - nodePort: 32000
      port: 80
  selector:
    run: test
---
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    app.kubernetes.io/name: $(TEST_SERVICE_NAME) # ★ここを上書きする
spec:
  containers:
    - name: nginx
      image: nginx
      env:
        - name: testenv
          value: $(TEST_SERVICE_NAME) # ★ここも上書きする
# kustomization.yaml
resources:
  - test.yml

vars:
  # ☆上書きに使う値の情報
  - name: TEST_SERVICE_NAME
    objref:
      apiVersion: v1
      kind: Service
      name: test
    fieldref:
      fieldpath: metadata.labels.[app.kubernetes.io/name]

というマニフェストファイル群に対してkustomize build .すると、次のように上書きすることができていた。

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: THIS-IS-TEST-SERVICE-NAME # ☆この値を上書きに使う
  name: test
spec:
  ports:
  - nodePort: 32000
    port: 80
  selector:
    run: test
  type: NodePort
---
apiVersion: v1
kind: Pod
metadata:
  labels:
    app.kubernetes.io/name: THIS-IS-TEST-SERVICE-NAME # ★上書きされた
  name: test
spec:
  containers:
  - env:
    - name: testenv
      value: THIS-IS-TEST-SERVICE-NAME # ★上書きされた
    image: nginx
    name: nginx

しかし、Kustomize v3.9以降からはエラーになるようになってしまった。

Error: field specified in var '{TEST_SERVICE_NAME ~G_v1_Service {metadata.labels.[app.kubernetes.io/name]}}' not found in corresponding resource

どうやら、varsで指定するfieldpathに . が含まれているような場合について、解釈できなくなってしまったようだった。

もともと2020年1月くらいからvarsをこれ以上使い続けるのは…みたいなIssueもたっていて、

github.com

最近のKustomizeでは代替になるreplacementsという機能が実装されていたので、それを使ってみることにした。


※以降はKustomize v4.2.0で動作確認した

上に書いたような例をreplacementsで実現しようとすると、次のようになる。

# test.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: test
  labels:
    app.kubernetes.io/name: THIS-IS-TEST-SERVICE-NAME # ☆この値を上書きに使う
spec:
  type: NodePort
  ports:
    - nodePort: 32000
      port: 80
  selector:
    run: test
---
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    app.kubernetes.io/name: TO_BE_REPLACED # ★ここを上書きする (TO_BE_REPLACEDの部分は何でも良い)
spec:
  containers:
    - name: nginx
      image: nginx
      env:
        - name: testenv
          value: TO_BE_REPLACED # ★ここも上書きする (TO_BE_REPLACEDの部分は何でも良い)
# kustomization.yaml
resources:
  - test.yml

replacements:
  - source:
      # ☆上書きに使う値の情報
      version: v1
      kind: Service
      name: test
      fieldPath: metadata.labels.[app.kubernetes.io/name]
    targets:
      # ★上書きされる対象の情報
      - select:
          version: v1
          kind: Pod
          name: test
        fieldPaths:
          - metadata.labels.[app.kubernetes.io/name]
          - spec.containers.0.env.0.value

こうしてkustomize build .を実行すると、冒頭に書いた例と同様に上書きされたマニフェストファイルが生成される。

varsの場合と異なり、「上書きに使う値」「上書きされる対象」のどちらのパスも明記する必要があるので若干めんどくさくなったように思ったが、よく言えば「どの部分が上書きされてしまうのか?」が一覧できるようになったので、慣れればreplacementsのほうが管理しやすくなるのかもしれない。