kustomizeのvarsとvarReferenceの動きが分かりづらかったの試した

## varsとvarReference？なるほどよく分からん
kustomizeで変数を扱える vars というものがある。噂によると containers配下 か env 配下しか変数を展開できないらしい。

varReference を使えば色々できる雰囲気は分かったけど、[kubectlのページ](https://kubectl.docs.kubernetes.io/pages/reference/kustomize.html#vars)
や[サンプル](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/transformerconfigs/crd/README.md) を見ても「フンフンなるほど」とどこまで適用されるのか分からん状態だったので試してみました。

## まずは環境整備
service.yamlの中身はこんな感じです。

```:service.yaml
apiVersion: v1
kind: Service
metadata:
  name: wordpress-aaa
  labels:
    app: wordpress-variable
spec:
  ports:
    - port: 80
  selector:
    app: wordpress
  type: LoadBalancer
```

deployment.yamlにどこまで展開されるか見てみたいと思います。

```:deployment.yaml
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: $(APP)
  labels:
    app: $(APP)
spec:
  selector:
    matchLabels:
      app: $(APP)
  strategy:
    type: $(APP)
  template:
    metadata:
      labels:
        app: $(APP)
    spec:
      containers:
      - image: $(APP)
        name: $(APP)
        ports:
        - containerPort: $(APP)
          name: $(NAME)
        volumeMounts:
        - name: wordpress-persistent-storage-$(NAME)
          mountPath: /var/www/html/$(NAME)
        env:
        - name: $(APP)
          value: $(APP)
      volumes:
      - name: wordpress-persistent-storage-$(NAME)
        emptyDir: {}
```

kustomization.yaml は以下の状態です。
resourcesでservice.yamlとdeployment.yamlを読み込むのと、varsで展開先を指定している

```:kustomization.yaml
resources:
- service.yaml
- deployment.yaml

vars:
- name: APP
  objref:
    kind: Service
    name: wordpress-aaa
    apiVersion: v1
  fieldref:
    fieldpath: metadata.labels.app
- name: NAME
  objref:
    kind: Service
    name: wordpress-aaa
    apiVersion: v1
  fieldref:
    fieldpath: metadata.name
```

## 検証１：varsを試す

この状態で `kustomize build .` を打つと以下になりました。
変化点は以下です。

- metadata.labels.app の $(APP)
- spec.template.spec.containers[0].env[0].value の $(APP)
- spec.template.spec.containers[0].volumeMounts[0].mountPath の $(NAME)

これらが、fieldrefで指定した値（metadata.labels.app, metadata.name）がnameの変数名
（APP, NAME） に格納され、予め規定された場所に展開されるようです。

```
$ kustomize build .
apiVersion: v1
kind: Service
metadata:
  labels:
    app: wordpress-variable
  name: wordpress-aaa
spec:
  ports:
  - port: 80
  selector:
    app: wordpress
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wordpress-variable
  name: $(APP)
spec:
  selector:
    matchLabels:
      app: $(APP)
  strategy:
    type: $(APP)
  template:
    metadata:
      labels:
        app: $(APP)
    spec:
      containers:
      - env:
        - name: $(APP)
          value: wordpress-variable
        image: $(APP)
        name: $(APP)
        ports:
        - containerPort: $(APP)
          name: $(NAME)
        volumeMounts:
        - mountPath: /var/www/html/wordpress-aaa
          name: wordpress-persistent-storage-$(NAME)
      volumes:
      - emptyDir: {}
        name: wordpress-persistent-storage-$(NAME)
```

なるほど。デフォルトのvarsだとこの程度なのね。

## 検証２：varReferenceを試す

kustomization.yamlに以下を追加します。

```:kustomization.yaml
configurations:
- varReference.yaml
```

varReference.yamlを以下で作成します。

```:varReference.yaml
varReference:
- path: spec/selector/matchLabels/app
  kind: Deployment
```

この状態で `kustomize build .` を打つと以下になりました。
変化点は以下です。

- spec.selector.matchLabels.app の $(APP) が wordpress に置き換わっている
- $(APP) は metadata.labels.app の wordpress を取得している

なるほど。そういう関係性になってるのね。ということは

```
$ kustomize build .
apiVersion: v1
kind: Service
metadata:
  labels:
    app: wordpress
  name: wordpress-aaa
spec:
  ports:
  - port: 80
  selector:
    app: wordpress-aaa
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wordpress
  name: $(APP)
spec:
  selector:
    matchLabels:
      app: wordpress
  strategy:
    type: $(APP)
  template:
    metadata:
      labels:
        app: $(APP)
    spec:
      containers:
      - env:
        - name: $(APP)
          value: wordpress
        image: $(APP)
        name: $(APP)
        ports:
        - containerPort: $(APP)
          name: $(NAME)
        volumeMounts:
        - mountPath: /var/www/html/wordpress-aaa
          name: wordpress-persistent-storage-$(NAME)
      volumes:
      - emptyDir: {}
        name: wordpress-persistent-storage-$(NAME)
```

## 検証３：varReferenceをさらに試す

varReference.yamlにAPPとNAME変数の展開先を指定してみる

```:varReference.yaml
varReference:
- path: spec/selector/matchLabels/app
  kind: Deployment
- path: spec/template/spec/volumes/name
  kind: Deployment
```

この状態で `kustomize build .` を打つと以下になりました。
変化点は以下です。

- spec.template.spec.volumes.name に NAME 値が展開されました

```
$ kustomize build .
apiVersion: v1
kind: Service
metadata:
  labels:
    app: wordpress
  name: wordpress-aaa
spec:
  ports:
  - port: 80
  selector:
    app: wordpress-aaa
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wordpress
  name: $(APP)
spec:
  selector:
    matchLabels:
      app: wordpress
  strategy:
    type: $(APP)
  template:
    metadata:
      labels:
        app: $(APP)
    spec:
      containers:
      - env:
        - name: $(APP)
          value: wordpress
        image: $(APP)
        name: $(APP)
        ports:
        - containerPort: $(APP)
          name: $(NAME)
        volumeMounts:
        - mountPath: /var/www/html/wordpress-aaa
          name: wordpress-persistent-storage-$(NAME)
      volumes:
      - emptyDir: {}
        name: wordpress-persistent-storage-wordpress-aaa
```

## 検証４：varReferenceをさらにさらに試す

varReference.yamlにAPPとNAME変数の展開先を全部指定してみる

```:varReference.yaml
varReference:
- path: spec/selector/matchLabels/app
  kind: Deployment
- path: spec/strategy/type
  kind: Deployment
- path: spec/template/metadata/labels/app
  kind: Deployment
- path: spec/template/spec/containers/env/name
  kind: Deployment
- path: spec/template/spec/containers/image
  kind: Deployment
- path: spec/template/spec/containers/name
  kind: Deployment
- path: spec/template/spec/containers/ports/containerPort
  kind: Deployment
- path: spec/template/spec/containers/ports/name
  kind: Deployment
- path: spec/template/spec/containers/volumeMounts/name
  kind: Deployment
- path: spec/template/spec/volumes/name
  kind: Deployment
```

この状態で `kustomize build .` を打つと以下になりました。
想定通り全部展開されました。

```
$ kustomize build .
apiVersion: v1
kind: Service
metadata:
  labels:
    app: wordpress
  name: wordpress-aaa
spec:
  ports:
  - port: 80
  selector:
    app: wordpress-aaa
  type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: wordpress
  name: $(APP)
spec:
  selector:
    matchLabels:
      app: wordpress
  strategy:
    type: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
      - env:
        - name: wordpress
          value: wordpress
        image: wordpress
        name: wordpress
        ports:
        - containerPort: wordpress
          name: wordpress-aaa
        volumeMounts:
        - mountPath: /var/www/html/wordpress-aaa
          name: wordpress-persistent-storage-wordpress-aaa
      volumes:
      - emptyDir: {}
        name: wordpress-persistent-storage-wordpress-aaa
```

## まとめ

- vars で変数を定義する
    - 変数は fieldref.fieldpath で指定した値が格納される
- resouces などで読み込む yaml に変数名を書く
- varReference で展開先を指定する
    - 展開先に指定された変数名に応じて変数が展開される