Kustomize is a tool for composing kubernetes manifests. It helps you to not repeat yourself when configuring many resources which are similar and staging those resources accross environments whciih are similar.

It is not a templating language.

In general this is a good thing. There are other tools whcih can help you with templating, kustomize just helps with boilerplate reduction.

I ran into a situation recently where I found it desirable to have both a CronJob and a Job resource which were mighty similar. A CronJob resource in kubernetes might look like

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: my-cronjob
spec:
  concurrencyPolicy: Forbid
  jobTemplate:
    metadata:
      name: my-job
    spec:
      template:
        spec:
          containers:
            image: busybox
            name: job
            foo: bar
          initContainers:
            image: busybox
            name: jobinit
          restartPolicy: Never
  schedule: '*/1 * * * *'
  startingDeadlineSeconds: 300

And a job might look something like

apiVersion: batch/v1
kind: Job
metadata:
  name: my-job
spec:
  template:
    metadata:
      name: my-job
    spec:
      template:
        spec:
          containers:
            image: busybox
            name: job
            foo: bar
          initContainers:
            image: busybox
            name: jobinit
          restartPolicy: Never

So, extremely similar, a lot of shared boilerplate. Kustomize generally works on the principle of applying merge patches to existing resources. It doesn’t direcly support any kind of resource sharing/loading that would help us to reuse this boilerplate. yaml does have something that will help us though, anchors and aliases. We can use these together with the core kubernetes resouce List to share the job template between the two resources, like so:

apiVersion: v1
kind: List
items:
- apiVersion: batch/v1beta1
  kind: CronJob
  metadata:
    name: my-cronjob
  spec:
    concurrencyPolicy: Forbid
    jobTemplate:
      metadata:
        name: my-job
      spec: &jobspec
        template:
          spec:
            containers:
              image: busybox
              name: job
              foo: bar
            initContainers:
              image: busybox
              name: jobinit
            restartPolicy: Never
    schedule: '*/1 * * * *'
    startingDeadlineSeconds: 300
- apiVersion: batch/v1
  kind: Job
  metadata:
    name: data-vaults-templated-job
  spec: *jobspec

Note the anchor &jobspec and alias *jobspec. Using this as a base for a kustomization will output a compound yaml stream containig both resources with the job alias fully inflated.

What if you only want to use one of these resources at a time?

For this the best solution I’ve found is to specify an overlay kustomization which deletes the resource you are not interested in. You can achieve this using either supported patch format, I’ll use a strategic merge patch for this example. The overlay kustomization.yaml looks like this:

bases:
  - ../base
patchesStrategicMerge:
  - deleteCronJob.yml

The deletion patch looks like this

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: my-cronjob
$patch: delete

When we run this through kustomize build the output is a single Job resource.

Kustomize is a great tool, which can suffer from quite poor documentation, I pieced this together from various PRs, issues and source. It is also deliberately very limited, but if you stick with it, I think you can make some really nice terse compositions which certainly reduce boilerplate and increase readibility.