Go generators in Kustomize allow you to create custom resources and modify existing ones by executing Go code.

Here’s a Kustomize generator written in Go that creates a ConfigMap with a specific key and value:

package main

import (
	"sigs.k8s.io/kustomize/kyaml/yaml/yamlmeta/meta"
	"sigs.k8s.io/kustomize/kyaml/yaml/yamlv2"
)

func main() {
	obj := &yamlv2.RNode{
		Content: []*yamlv2.RNode{
			yamlv2.NewMapNode("apiVersion", "v1"),
			yamlv2.NewMapNode("kind", "ConfigMap"),
			yamlv2.NewMapNode("metadata",
				yamlv2.NewMapNode("name", "my-custom-config"),
			),
			yamlv2.NewMapNode("data",
				yamlv2.NewMapNode("mykey", "myvalue"),
			),
		},
	}
	obj.SetLabels(meta.Labels{
		"kustomize.config.k8s.io/generator": "true",
	})
	yamlv2.Print(obj)
}

To use this generator, you would place the compiled Go binary in a generators directory within your Kustomize project and reference it in your kustomization.yaml:

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

generators:
- generators/my-go-generator

Running kustomize build . would then output the generated ConfigMap.

The core problem Kustomize exec plugins solve is the desire for programmatic, dynamic resource generation that goes beyond static YAML patching. Think about scenarios where you need to:

  • Generate secrets dynamically: Fetching values from an external secret store or generating them based on specific policies.
  • Create complex CRDs: Resources whose structure depends on external data or calculations.
  • Implement custom validation or mutation: Modifying resources based on rules not expressible in standard Kustomize transformers.
  • Integrate with external systems: Pulling data from APIs or databases to inform Kubernetes resource definitions.

An exec plugin works by Kustomize invoking an external executable (your Go program in this case) and piping the output of that executable back into the Kustomize build process. Kustomize treats the standard output of the executable as YAML, which can then be further processed by other transformers or included in the final manifest.

The sigs.k8s.io/kustomize/kyaml/yaml/yamlv2 package is your primary tool for programmatically manipulating YAML structures within Go. yamlv2.RNode represents a node in the YAML tree, and you can construct or traverse these nodes to build or modify your Kubernetes resources. Functions like yamlv2.NewMapNode are crucial for creating key-value pairs within your YAML.

The meta.Labels with "kustomize.config.k8s.io/generator": "true" is a special label that tells Kustomize that this output is a generated resource, not a patch or a base resource. This helps Kustomize manage the lifecycle and understanding of these dynamically created objects.

To compile the Go generator:

go build -o generators/my-go-generator main.go

Ensure your kustomization.yaml is in the root of your project and the generators directory is also in the root.

You can also use kyaml to execute your plugin and see its output directly:

./generators/my-go-generator | kustomize edit diff

This will show you the difference between the output of your generator and the current state (if any).

The yamlv2.Print(obj) function is what sends the generated YAML structure to standard output, making it available for Kustomize. You can add multiple yamlv2.RNode objects to the Content slice of a parent RNode to represent multiple resources or nested structures.

Consider a scenario where you need to generate a Secret containing a TLS certificate and key. Your Go generator could read these from files or environment variables and then construct the Secret object with the data field correctly base64 encoded.

The magic of kyaml is that it understands the structure of Kubernetes objects. When you create yamlv2.NewMapNode("apiVersion", "v1"), kyaml knows this is a field within a Kubernetes object. You can then add yamlv2.NewMapNode("kind", "ConfigMap") and so on, building the complete object.

One subtle but powerful aspect is how Kustomize handles the output of multiple generators. If your kustomization.yaml lists several generators, Kustomize will execute each one sequentially and merge their outputs. This allows for complex, layered generation where one generator might produce data that another generator consumes.

The next step after mastering custom generators is often exploring custom transformers, which allow you to modify existing resources based on logic rather than just creating new ones.

Want structured learning?

Take the full Kustomize course →