Kustomize(v5.2)からpatchesにマルチリソースファイルを指定できる

こんにちは、[Intimate Merger](https://corp.intimatemerger.com/) のFukudaです。
今回はKustomizeのpatchesに関する記事です。

# 概要

⭐️Kustomize v5.2 から`patches`でマルチリソースファイルを指定できるようになりました⭐️

Kustomize v5.0 から`patchesStrategicMerge`と`patchesJson6902`が非推奨になりました。
代わりとして`patches`の使用が推奨されています。
しかし、v5リリースで`patches`への移行に完全に対応できるものではありませんでした。
これがついに対応され、移行できる形になったので共有します！

## 補足情報
- 現在のKustomizeのAPIバージョンは`kustomize.config.k8s.io/v1beta1`
  - `patchesStrategicMerge`と`patchesJson6902`は非推奨機能として残っています
- `kustomize.config.k8s.io/v1`で非推奨機能は削除される予定
  - `kustomize/v5`以降のメジャーバージョンアップで、APIバージョンが`kustomize.config.k8s.io/v1`に更新
- 詳しくはKustomize/v5.0の[Deprecations](https://github.com/kubernetes-sigs/kustomize/releases/tag/kustomize%2Fv5.0.0#:~:text=in%20release%20v5.0.1.-,Deprecations,-%234723%2C%20%234923)をご覧ください

# ファイルを準備

ファイル構成

```
manifests
├── deployment.yaml
├── deployment_patches.yaml
└── kustomization.yaml
```

## 各ファイルの説明

`kustomization.yaml`は管理するリソースをまとめたマニフェスト

- `kustomization.yaml`(`patchesStrategicMerge`)
  - `patchesStrategicMerge`を使ってマージ
- `kustomization.yaml`(`patches`)
  - `patches`を使ってマージ
- `deployment.yaml`
  - 下記のリソースを作成するためのマニフェスト
    - `nginx-deployment-1`
    - `nginx-deployment-2`
- `deployment_patches.yaml`
  - `deveployment.yaml`のリソースにマージ
  - マージによるリソースの変更点
    - `nginx-deployment-1`にポート81を生やす
    - `nginx-deployment-2`のレプリカ数を2→10に増やす

### `kustomization.yaml`(`patchesStrategicMerge`)

```kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patchesStrategicMerge:
- deployment_patches.yaml
```

### `kustomization.yaml`(`patches`)

```kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patches:
- path: deployment_patches.yaml
```

### `deployment.yaml`

```deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-1
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.24.0
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-2
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.24.0
        ports:
        - containerPort: 80
```

### `deployment_patches.yaml`

```deployment_patches.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-1
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.24.0
        ports:
        - containerPort: 81
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-2
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 10
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.24.0
        ports:
        - containerPort: 80
```


# 実際に試してみましょう

検証に使用したKustomizeはv5.1.1とv5.2.1です。

Kustomize v5.2 未満で`pathes`を使ってマルチリソースファイルをマージしようとするとエラーが発生します。
回避策として非推奨機能の`patchesStrategicMerge`を使用する必要がありました。

## 期待される出力

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-1
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.24.0
        ports:
        - containerPort: 81
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-2
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 10
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.24.0
        ports:
        - containerPort: 80
```

## Kustomize v5.1.1

### `kustomization.yaml`(`patches`)を使用

```kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patches:
- path: deployment_patches.yaml
```

ビルドするとエラーが発生します。
このエラーに関しての[Issue](https://github.com/kubernetes-sigs/kustomize/issues/5040)が上がっていました。
`patches`がマルチリソースファイルに対応できていないようです。

```shell
$ kustomize build manifests
Error: trouble configuring builtin PatchTransformer with config: `
path: deployment_patches.yaml
`: unable to parse SM or JSON patch from [apiVersion: apps/v1
                (マニフェストの内容なので省略)
]
```


### `kustomization.yaml`(`patchesStrategicMerge`)を使用

```kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patchesStrategicMerge:
- deployment_patches.yaml
```

非推奨機能の`patchesStrategicMerge`を使って<a href="#kustomize-v511-を使って-build">上記エラー</a>を回避できます。
ビルドすると `patchesStrategicMerge`の非推奨警告 と 期待される出力 が表示されました。

```shell
$ kustomize build manifests
# Warning: 'patchesStrategicMerge' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
(期待される出力が表示)
```

これがKustomize v5.2未満でマルチリソースファイルを使ってビルドする方法です。

## Kustomize v5.2.1

Kustomize v5.2 で<a href="#kustomize-v511-を使って-build">上記エラー</a>の[修正PR](https://github.com/kubernetes-sigs/kustomize/pull/5194)が取り込まれています。

### `kustomization.yaml`(`patches`)を使用

```kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
patches:
- path: deployment_patches.yaml
```

ビルドすると期待される出力が表示されます。

```shell
$ kustomize build manifests
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-1
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.24.0
        ports:
        - containerPort: 81
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment-2
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 10
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.24.0
        ports:
        - containerPort: 80
```

# まとめ

`patches`を使ってマルチリソースファイルが利用できるようになりました🎉

弊社では、非推奨機能を使っていることに歯痒さを感じていました。
今回のバグ修正のおかげでスッキリとした気分で開発が進められます😀

`patchesStrategicMerge`は非推奨なので`patches`へ移行しましょう！！！

# あとがき

読んでいただいてありがとうございます。
以上、Kustomize(v5.2)のpatchesに関する記事でした。

引き続きアドベントカレンダーの記事を読んでいただけると嬉しいです。
次回はpoetryに関する記事のようです。

https://qiita.com/advent-calendar/2023/intimatemerger

# 参考

- https://github.com/kubernetes-sigs/kustomize/releases/tag/kustomize%2Fv5.0.0
- https://github.com/kubernetes-sigs/kustomize/releases/tag/kustomize%2Fv5.2.0
- https://github.com/kubernetes-sigs/kustomize/issues/5040
- https://github.com/kubernetes-sigs/kustomize/pull/5194