Skip to content

Commit

Permalink
Add different strategies for kustomize patches fields
Browse files Browse the repository at this point in the history
Signed-off-by: Guillaume Le Biller <[email protected]>
  • Loading branch information
glebiller committed Jun 16, 2021
1 parent 5f34704 commit 3e3b506
Showing 1 changed file with 158 additions and 64 deletions.
222 changes: 158 additions & 64 deletions site/content/en/references/kustomize/kustomization/patches/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: >
---

[strategic merge]: /references/kustomize/glossary#patchstrategicmerge
[JSON]: /references/kustomize/glossary#patchjson6902
[JSON6902]: /references/kustomize/glossary#patchjson6902

Patches (also call overlays) add or override fields on resources. They are provided using the
`patches` Kustomization field.
Expand All @@ -17,18 +17,14 @@ The `patches` field contains a list of patches to be applied in the order they a

Each patch may:

- be either a [strategic merge] patch, or a [JSON] patch
- be either a [strategic merge] patch, or a [JSON6902] patch
- be either a file, or an inline string
- target a single resource or multiple resources

The patch target selects resources by group, version, kind, name, namespace, labelSelector and
annotationSelector. Any resource which matches all the **specified** fields has the patch applied
The patch target selects resources by `group`, `version`, `kind`, `name`, `namespace`, `labelSelector` and
`annotationSelector`. Any resource which matches all the **specified** fields has the patch applied
to it (regular expressions).

A patch can refer to a resource by any of its previous names or kinds.
For example, if a resource has gone through name-prefix transformations, it can refer to the
resource by its current name, original name, or any intermediate name that it had.

```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
Expand All @@ -55,122 +51,220 @@ The `name` and `namespace` fields of the patch target selector are
automatically anchored regular expressions. This means that the value `myapp`
is equivalent to `^myapp$`.

Consider the following `deployment.yaml` common for both the examples:
With patches it is possible to override the kind or name of the resource it is
editing with the options allowNameChange and allowKindChange. For example:
```yaml
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
options:
allowNameChange: true
allowKindChange: true
```
By default, these fields are false and the patch will leave the kind and name of the resource untouched.

A patch can refer to a resource by any of its previous names or kinds.
For example, if a resource has gone through name-prefix transformations, it can refer to the
resource by its current name, original name, or any intermediate name that it had.

## Examples

Consider the following `deployment.yaml` common for all examples:
```yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: the-deployment
name: dummy-app
labels:
app.kubernetes.io/name: nginx
spec:
replicas: 5
selector:
matchLabels:
app.kubernetes.io/name: nginx
template:
containers:
- name: the-container
image: registry/conatiner:latest
metadata:
labels:
app.kubernetes.io/name: nginx
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- name: http
containerPort: 80
```

Another feature of patches is the option to override the kind or name of
the resource it is editing. By default, the patch will leave the kind and name
of the resource untouched. For example:
### Intents

- Make the container image point to a specific version and not to the latest container in the registry.
- Adding a standard label containing the deployed version.

There are multiple possible strategies that all achieve the same results.

### Patch using Inline Strategic Merge

```yaml
# kustomization.yaml
resources:
- deployment.yaml
patches:
- path: patch.yaml
target:
kind: Deployment
options:
allowNameChange: true
allowKindChange: true
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: dummy-app
labels:
app.kubernetes.io/version: 1.21.0
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: not-used
spec:
template:
spec:
containers:
- name: nginx
image: nginx:1.21.0
target:
labelSelector: "app.kubernetes.io/name=nginx"
```

## Example I
If a `target` is specified, the `name` contained in the metadata is required but not used.

### Intent
### Patch using Inline JSON6902

To Make the container image point to a specific version and not to the latest container in the
registry.
```yaml
# kustomization.yaml
resources:
- deployment.yaml
patches:
- patch: |-
- op: add
path: /metadata/labels/app.kubernetes.io~1version
value: 1.21.0
target:
group: apps
version: v1
kind: Deployment
- patch: |-
- op: replace
path: /spec/template/spec/containers/0/image
value: nginx:1.21.0
target:
labelSelector: "app.kubernetes.io/name=nginx"
```

The `target` field is always required for JSON6902 patches.
A special replacement character `~1` is used to replace `/` in label name.

### File Input
### Patch using Path Strategic Merge

```yaml
# kustomization.yaml
resources:
- deployment.yaml
patches:
- path: patch.yaml
- path: add-label.patch.yaml
- path: fix-version.patch.yaml
target:
labelSelector: "app.kubernetes.io/name=nginx"
```

As with the Inline Strategic Merge, the `target` field can be omitted.
In that case, the target resource is matched using
the `apiVersion`, `kind` and `name` from the patch.

```yaml
# patch.yaml
# add-label.patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: the-deployment
spec:
template:
containers:
- name: the-container
image: registry/conatiner:1.0.0
name: dummy-app
labels:
app.kubernetes.io/version: 1.21.0
```

### Build Output

```yaml
# fix-version.patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: the-deployment
name: not-used
spec:
replicas: 5
template:
containers:
- image: registry/conatiner:1.0.0
name: the-container
spec:
containers:
- name: nginx
image: nginx:1.21.0
```

## Example II
As with the Inline Strategic Merge, the `name` field in the patch is not used when a `target` is specified.

### Intent

To Make the container image point to a specific version and not to the latest container in the
registry.

### File Input
### Patch using Path JSON6902

```yaml
# kustomization.yaml
resources:
- deployment.yaml
patches:
- target:
kind: Deployment
name: the-deployment
path: patch.json
- path: add-label.patch.json
target:
group: apps
version: v1
kind: Deployment
- path: fix-version.patch.yaml
target:
labelSelector: "app.kubernetes.io/name=nginx"
```

As with Inline JSON6902, the `target` field is mandatory.

```yaml
# patch.json
# add-label.patch.json
[
{"op": "replace", "path": "/spec/template/containers/0/image", "value": "registry/conatiner:1.0.0"}
{"op": "add", "path": "/metadata/labels/app.kubernetes.io~1version", "value": "1.21.0"}
]
```

```yaml
# fix-version.patch.yaml
- op: replace
path: /spec/template/spec/containers/0/image
value: nginx:1.21.0
```

External patch file can be written both as YAML or JSON.
The content must follow the JSON6902 standard.

### Build Output

All four patches strategies lead to the exact same output:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: the-deployment
labels:
app.kubernetes.io/name: nginx
app.kubernetes.io/version: 1.21.0
name: dummy-app
spec:
replicas: 5
selector:
matchLabels:
app.kubernetes.io/name: nginx
template:
containers:
- image: registry/conatiner:1.0.0
name: the-container
```
metadata:
labels:
app.kubernetes.io/name: nginx
spec:
containers:
- image: nginx:1.21.0
name: nginx
ports:
- containerPort: 80
name: http
```

0 comments on commit 3e3b506

Please sign in to comment.