The Kustomization File

An overview of the content of a kustomization file.

The kustomization file is a YAML specification of a Kubernetes Resource Model (KRM) object called a Kustomization. A kustomization describes how to generate or transform other KRM objects.

Although most practical kustomization files don’t actually look this way, a kustomization.yaml file is basically four lists:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- {pathOrUrl}
- ...

generators:
- {pathOrUrl}
- ...

transformers:
- {pathOrUrl}
- ...

validators:
- {pathOrUrl}
- ...

The order in each of these lists is relevant and respected.

There are other fields too, e.g. commonLabels, namePrefixes, patches, etc. These fields are convenience fields, shorthand for longer transformer configuration stanzas, and are discussed later. They’re what’s used most often, but it’s useful to first cover the fundamentals before discussing the conveniences.

In all cases the {pathOrUrl} list entry can specify

  • a file system path to a YAML file containing one or more KRM objects, or
  • a directory (local or in a remote git repo) that contains a kustomization.yaml file.

In the latter case, the kustomization is recursively built (aka hydrated) into a flat list of KRM objects that’s effectively injected into the encapsulating list in order. When this happens, the encapsulating kustomization can be called an overlay, and what it refers to can be called a base.

A typical layout:

app1/
  kustomization.yaml
    | resources:
    | - ../base
    | patches:
    | - patch1.yaml
  patch1.yaml

app2/
  kustomization.yaml
    | resources:
    | - ../base
    | patches:
    | - patch2.yaml
  patch2.yaml

base/
  kustomization.yaml
    | resources:
    | - deployment.yaml
    | - configMap.yaml
  deployment.yaml
  configMap.yaml

Under resources, the result of reading KRM yaml files or executing recursive kustomizations becomes the list of input objects to the current build stage.

Under generators, transformers and validators, the result of reading/hydrating is a list of KRM objects that configure operations that kustomize is expected to perform.

Some of these fields allow YAML inlining, allowing a KRM object to be declared directly in the kustomization.yaml file (in practice this is mainly useful in the transformers field).

These configurations specify some executable (e.g. a plugin) along with that executable’s configuration. For example, a replica count transformer’s configuration must specify both an executable capable of parsing and modifying a Deployment, and the actual numerical value (or increment) to use in the Deployment’s replicas field.

Ordering

A build stage first processes resources, then it processes generators, adding to the resource list under consideration, then it processes transformers to modify the list, and finally runs validators to check the list for whatever error.

Conveniences

The resources field is a convenience. One can omit resources field and instead use a generator that accepts a file path list, expanding it as needed. Such a generator would read the file system, doing the job that kustomize does when processing the resources field.

All the other fields in a kustomization file (configMapGenerator, namePrefix, patches, etc.) are conveniences as well, as they are shorthand for: run a particular generator or transformer with a particular configuration.

Likewise, a validator is just a transformer that doesn’t transform, but can (just like a transformer) fail the build with an error message. Coding up a validator is identical to coding up a transformer. The only difference is in how it’s used by kustomize; kustomize attempts to disallow validators from making changes.

The next section explains why the generators field is also just a convenience.

Generators and Transformers

In the code, the interfaces distinguishing a generator from a transformer are:

// Generator creates an instance of ResMap.
type Generator interface {
  Generate() (ResMap, error)
}

// Transformer can modify an instance of ResMap.
type Transformer interface {
  Transform(m ResMap) error
}

In these interfaces, a ResMap is a list of kubernetes Resources with ancillary map-like lookup and modification methods.

A generator cannot be a transformer, because it doesn’t accept an input other than its own configuration. Configuration for both generators and transformers are done via a distinct (and common) interface.

A transformer doesn’t implement Generator, but it’s capable of behaving like one.

This is because ResMap has the methods

Append(*Resource)
Replace(*Resource)
Remove(ResId)
Clear()
  ...etc.

i.e. the ResMap interface allows for growing and shrinking the Resource list, as well as mutating each Resource on it.

A transformer (specifically the author of a transformer) can call these methods - creating, sorting, destroying, etc.

At the time of writing, the ResMap is being converted to a mutable list RNodes, objects that integrate KRM with a new kubernetes-specific YAML library called kyaml. As more programs speak kyaml, kustomize’s role will evolve too.

Transformers have a general generative power.

A kustomization overlay, could, say, fix common oversights made in cluster configuration.

For example, a transformer could scan all resources, looking for the need for a PodDisruptionBudget, and conditionally add it and hook it up as a guard rail for the user.

Everything is a transformer

Every field in a kustomization file could be expressed as a transformer, so any kustomization file can be converted to a kustomization file with one transformers: field.

So why keep all these fields?

The fields in kustomization file are useful for ordering and signalling, e.g. these particular things are transformers, and should run after the generators, but before the validators.

Also, they make common use cases easier to express.

E.g. the following two YAML stanzas do the exactly the same thing if added to a kustomization file:

namePrefix: bob-
transformers:
- |-
  apiVersion: builtin
  kind: PrefixSuffixTransformer
  metadata:
    name: myFancyNamePrefixer
  prefix: bob-
  fieldSpecs:
  - path: metadata/name

Transformed transformers

The arguments to resources are usually files containing instances of Deployment, Service, PodDisruptionBudget, etc., but they could also be transformer configurations.

In this case the transformer configurations are just grist for the kustomization mill, and can be modifed and passed up an overlay stack, and later be used to as input in a transformers field, whereupon they’ll be applied to any resources at that kustomization stage.

For example, the following file layout has two apps using a common pair of bases.

One base contains a deployment and a configMap. The other contains transformer configurations. This is a means to specify a set of reusable, custom transformer configs.

In between the apps and these bases are intermediate overlays that transform the base transformer configurations before they are used in the top level apps.

app1/
  kustomization.yaml
    | resources:
    | - ../base/resources
    | transformers:
    | - ../transformers1
    | patches:
    | - patch1.yaml
  patch1.yaml
    | {a patch for resources}

app2/
  kustomization.yaml
    | resources:
    | - ../base/resources
    | transformers:
    | - ../transformers2
    | patches:
    | - patch2.yaml
  patch2.yaml
    | {some other patch for the resources}

transformers1/
  kustomization.yaml
    | resources:
    | - ../base/transformers
  transformerPatch1.yaml
    | {a patch for the base transformer configs}

transformers2/
  kustomization.yaml
    | resources:
    | - ../base/transformers
  transformerPatch1.yaml
    | {some other patch for the base transformer configs}

base/
  transformers/
    kustomization.yaml
       | resources:
       | - transformerConfig1.yaml
       | - transformerConfig2.yaml
    transformerConfig1.yaml
    transformerConfig2.yaml
  resources/
    kustomization.yaml
       | resources:
       | - deployment.yaml
       | - configMap.yaml
    deployment.yaml
    configMap.yaml

This isn’t a recommended or disallowed practice, but something that’s allowed by how kustomization fields are processed.


bases

Add resources from a kustomization dir.

buildMetadata

Specify options for including information about the build in annotations or labels.

commonAnnotations

Add annotations to add all resources.

commonLabels

Add labels and selectors to add all resources.

components

Compose kustomizations.

configMapGenerator

Generate ConfigMap resources.

crds

Adding CRD support

generatorOptions

Control behavior of ConfigMap and Secret generators.

helmCharts

Helm chart inflation generator.

images

Modify the name, tags and/or digest for images.

labels

Add labels and optionally selectors to all resources.

namePrefix

Prepends the value to the names of all resources and references.

namespace

Adds namespace to all resources.

nameSuffix

Appends the value to the names of all resources and references.

openapi

Specify where kustomize gets its OpenAPI schema.

patches

Patch resources

patchesJson6902

Patch resources using the json 6902 standard

patchesStrategicMerge

Patch resources using the strategic merge patch standard.

replacements

Substitute field(s) in N target(s) with a field from a source.

replicas

Change the number of replicas for a resource.

resources

Resources to include.

secretGenerator

Generate Secret resources.

sortOptions

Change the strategy used to sort resources at the end of the Kustomize build.

vars

Substitute name references.


Last modified June 26, 2022: fix dead link (088bf1b)