# How to replace deprecated Kustomize fields with kustomize edit fix

> Clear Kustomize deprecation warnings: what kustomize edit fix rewrites, how to prove the output didn't change, and how to move vars to replacements.

Published: 2026-11-05
Author: k8wiz Team
URL: https://k8wiz.com/articles/replace-deprecated-kustomize-fields-with-kustomize-edit-fix

If your repository has been around since Kustomize v3 or v4, `kustomize build` probably prints a few lines like these before the YAML.

```text
# Warning: 'bases' is deprecated. Please use 'resources' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
# Warning: 'patchesStrategicMerge' is deprecated. Please use 'patches' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
# Warning: 'commonLabels' is deprecated. Please use 'labels' instead. Run 'kustomize edit fix' to update your Kustomization automatically.
```

The builds still work, so these warnings tend to sit in CI logs for years. Cleaning them up is low risk if you do it in the right order, and the tool that suggests the fix does most of the work. This guide covers what `kustomize edit fix` changes, how to check that the rendered manifests stay identical, and how to handle the one field it won't convert unless you ask, `vars`. The details below come from the Kustomize v5.8 source.

## Which fields are deprecated

Kustomize v5 warns about six fields. Each has a replacement that does the same job, usually with more options.

| Deprecated field | Use instead |
| --- | --- |
| `bases` | `resources` |
| `imageTags` | `images` |
| `patchesStrategicMerge` | `patches` |
| `patchesJson6902` | `patches` |
| `commonLabels` | `labels` |
| `vars` | `replacements` |

Kustomize prints the warnings on stderr, so the YAML on stdout stays valid and `kustomize build . | kubectl apply -f -` keeps working. That is also why nobody notices them. The warnings start with `#`, but they never reach the YAML stream.

## Step 1: start from a clean tree and save the current output

`kustomize edit fix` rewrites `kustomization.yaml` in place, and with the `--vars` option it also rewrites your resource files. Start with a clean Git working tree so you can review every change with `git diff` and throw it away if something looks wrong.

Then render every kustomization you plan to touch and keep the output. This is the baseline you compare against at the end.

```bash
git status --short
mkdir -p /tmp/kfix
for dir in base overlays/dev overlays/prod; do
  kustomize build "$dir" > "/tmp/kfix/$(echo "$dir" | tr / _).before.yaml"
done
```

Adjust the list of directories to your repository. Include every overlay, because an overlay renders its bases too, and a change in a base shows up in each overlay's output.

## Step 2: run kustomize edit fix in each directory

The command works on the kustomization file in the current directory only. It doesn't follow `resources` into bases, so run it once per directory.

```bash
for dir in base overlays/dev overlays/prod; do
  (cd "$dir" && kustomize edit fix)
done
```

For each directory it prints a summary of the conversions it handles.

```text
Fixed fields:
  patchesJson6902 -> patches
  patchesStrategicMerge -> patches
  commonLabels -> labels

To convert vars -> replacements, run the command `kustomize edit fix --vars`
```

The summary is the same fixed text every time. It lists what the command can convert, not what it found in your file, so read the diff to see what actually changed.

Here is what the command does to each field. It moves `bases` entries to the end of `resources` and `imageTags` entries into `images`. It turns each `patchesJson6902` entry into a `patches` entry with the same `target` and `path`. Each `patchesStrategicMerge` entry becomes a `patches` entry with `path` when it names a file, or with an inline `patch` when it holds YAML. It also fills in `apiVersion` and `kind` if your file left them out, and moves a generator's old `envSource` into `envSources`.

## Step 3: check the commonLabels conversion

`commonLabels` needs a closer look, because the conversion keeps a behavior many people don't realize they rely on. `commonLabels` adds its labels to resource metadata and to selectors and pod templates. The newer `labels` field only touches selectors when you ask it to.

So `kustomize edit fix` writes the old labels as a `labels` entry with `includeSelectors: true`. A file that started like this:

```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  app.kubernetes.io/name: shop
resources:
  - deployment.yaml
  - service.yaml
```

ends up with the same meaning as this:

```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml
labels:
  - pairs:
      app.kubernetes.io/name: shop
    includeSelectors: true
```

Leave `includeSelectors: true` in place for labels that are already deployed. The `spec.selector` of a Deployment can't change after creation, so dropping a label from the selector makes the next `kubectl apply` fail on every Deployment that has it. If you want new labels that stay out of selectors, add them as a separate `labels` entry without `includeSelectors`.

If the file already uses `labels` and one of the keys also appears in `commonLabels`, the command stops with an error naming that key. Remove the duplicate from one of the two fields and run it again.

## Step 4: compare the output

Render everything again and diff it against the baseline.

```bash
for dir in base overlays/dev overlays/prod; do
  name="$(echo "$dir" | tr / _)"
  kustomize build "$dir" > "/tmp/kfix/$name.after.yaml"
  diff -u "/tmp/kfix/$name.before.yaml" "/tmp/kfix/$name.after.yaml" && echo "$dir: no change"
done
```

`kustomize edit fix` runs a similar check itself. It builds the directory before and after the rewrite and prints a warning if the output differs or if the fixed file no longer builds. That check only covers the directory where you ran the command, though, and the loop above covers each overlay that builds on it.

An empty diff is what you want. If something changed, the most common cause is patch order. `kustomize edit fix` appends converted patches after any existing `patches` entries, all `patchesJson6902` entries first and then all `patchesStrategicMerge` entries. When two patches touch the same field, the later one wins, so reorder the `patches` list to match the order the old fields were applied in.

## Step 5: convert vars to replacements

`vars` needs the most care, which is why the plain command skips it. A var copies a value from one resource into `$(NAME)` references in others. Replacements do the same job with explicit field paths instead of text substitution.

Take a var that puts a Service name into a Deployment's environment.

```yaml
vars:
  - name: DB_HOST
    objref:
      apiVersion: v1
      kind: Service
      name: postgres
    fieldref:
      fieldpath: metadata.name
```

The Deployment then has `value: $(DB_HOST)` in its `env` list. The replacement version reads the same source field and names the target field directly.

```yaml
replacements:
  - source:
      kind: Service
      name: postgres
      fieldPath: metadata.name
    targets:
      - select:
          kind: Deployment
          name: api
        fieldPaths:
          - spec.template.spec.containers.[name=api].env.[name=DB_HOST].value
```

The target field still needs a value in the source file, but it can be anything. A placeholder such as `value: DB_HOST_PLACEHOLDER` makes the intent obvious, and Kustomize overwrites it during the build.

You can let Kustomize do this conversion with `kustomize edit fix --vars`. It finds every file under `resources` that contains `$(DB_HOST)`, adds a target for each place it appears and replaces the reference with `DB_HOST_PLACEHOLDER`. When the reference is only part of a value, such as `--db-host=$(DB_HOST)`, it adds `delimiter` and `index` options to the target so only that piece gets replaced. A reference in the middle of a string converts only when the same character sits on both sides of it. For a value like `postgres://$(DB_HOST):5432` the command stops with an error saying the var is not delimited. Move the host into its own field or env var first, then convert.

The command prints its own warning before doing this. Converting vars rewrites resource files, and the result may not render the same output. Run it in a clean tree, review the generated `replacements` block, then repeat the comparison from step 4. For a handful of vars, writing the replacements by hand often gives a shorter, clearer file.

## Step 6: keep the warnings from coming back

Once the diff is clean, commit the change and make CI fail if a deprecated field comes back. Because the warnings go to stderr, you can check for them without parsing the YAML.

```bash
#!/usr/bin/env bash
set -euo pipefail
status=0
for dir in base overlays/dev overlays/prod; do
  if kustomize build "$dir" 2>&1 >/dev/null | grep -q "is deprecated"; then
    echo "deprecated Kustomize fields in $dir" >&2
    status=1
  fi
done
exit "$status"
```

The redirection order matters in that `if` line. `2>&1 >/dev/null` sends stderr into the pipe and throws stdout away, so `grep` only sees the warnings.

If you also build with `kubectl apply -k`, keep in mind that kubectl ships its own copy of Kustomize, often a version or two behind the standalone CLI. kubectl has embedded Kustomize v5 since Kubernetes 1.27, and every field in this guide works there.
