Skip to content

blesswinsamuel/kgen

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

kgen

kgen is a Go library for generating Kubernetes manifests with Go code.

Why?

I used Helm for a while to generate Kubernetes manifests for my homelab. Helm is a great tool, but maintaining complex templates became painful, especially without strong IDE autocomplete and type checking.

I then tried cdk8s. It was a big step up from Helm because of type safety and better editing ergonomics, but it requires code generation for custom resources. The large number of generated files slowed down my IDE, and generation felt slow for my use cases since it runs through JavaScript under the hood.

Since many operators that ship CRDs are written in Go (and expose Go structs), I wanted a simpler path: write manifests directly in Go using existing types. That is why I created kgen.

Features

  • Write Kubernetes manifests in Go and build your own abstractions using the full power of the language.
  • Use Kubernetes Go structs directly (for example from client-go) with IDE autocomplete and type checking.
  • Support custom resources without code generation. Import and use structs from third-party repositories directly. See this example.
  • Render existing Helm charts alongside your Go-defined resources. See this example.
  • Faster than cdk8s in my experience, especially when rendering large numbers of resources.
  • Can be used as a Helm-template alternative for packaging Kubernetes resources. Instead of templates, expose a Go package that renders resources from props. See this example.

Tradeoff: Helm does not require a Go compiler, but kgen does.

Examples

Check the examples directory for examples.

Documentation

See GoDoc for full API documentation.

Basic Usage

kgen is a library. Use it in your Go program to define resources and render manifests.

package main

import (
	certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/utils/ptr"

	"github.com/blesswinsamuel/kgen"
)

func main() {
	// 1. Create a schemeBuilder with all the custom resources you plan to generate.
	// It should also have "k8s.io/client-go/kubernetes/scheme".AddToScheme to include the core k8s resources.
	schemeBuilder := runtime.SchemeBuilder{
		scheme.AddToScheme,
		certmanagerv1.AddToScheme, // if you want to generate cert-manager resources
	}
	// 2. Create a builder instance passing `schemeBuilder` to start adding resources. You can also pass a custom logger here.
	builder := kgen.NewBuilder(kgen.BuilderOptions{
		SchemeBuilder: schemeBuilder,
	})
	// 3. Create a scope to organize resources. kgen can be configured to output the k8s resources added to each scope to separate files. See kgen.RenderManifestsOptions.
	// You can also set the kubernetes namespace for the scope.
	// If you don't set the namespace, the resources will have the default namespace, unless you set it in the resource objects themselves.
	whoamiScope := builder.CreateScope("whoami", kgen.ScopeProps{Namespace: "whoami"})
	// 4. Add resources to the scope. You can add any k8s resource object that implements the runtime.Object interface.
	whoamiScope.AddApiObject(&appsv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{Name: "whoami-deployment"},
		Spec: appsv1.DeploymentSpec{
			Replicas: ptr.To[int32](1),
			Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "whoami"}},
			Template: corev1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"app": "whoami"}},
				Spec: corev1.PodSpec{
					Containers: []corev1.Container{
						{
							Name:  "whoami-container",
							Image: "containous/whoami",
						},
					},
				},
			},
		},
	})
	// Notes:
	// - You can add more resources to the scope using whoamiScope.AddApiObject(...)
	// - You can create more scopes (can be nested as well) and add resources to them.
	// - You can also add resources to the builder directly without a scope using builder.AddApiObject(...).
	//   But the filenames might be empty in the output depending on the output format.
	//   So it's recommended to use scopes.
	// - You can also add existing helm charts to be rendered along with the resources. Check the complex example under examples directory for an example.

	// 5. Render the resources to k8s yaml files.
	//    You can also customize the output format (one YAML file per scope, one YAML file per resource, etc). See kgen.RenderManifestsOptions in godoc.
	builder.RenderManifests(kgen.RenderManifestsOptions{
		Outdir:       "k8s-rendered",
		DeleteOutDir: true,
	})
}

Run go run . to generate manifests in the k8s-rendered directory. See here for the output generated by the example above.

Bonus tips

  • Commit rendered manifests to Git (ideally from CI). This article is a great reference.
  • Use kapp to apply manifests to your cluster. It can show diffs against cluster state and has been faster than Helm in my experience. Here is a command I use: kapp deploy -a homelab -f k8s-rendered --diff-changes --diff-mask=false --diff-context=2 --apply-default-update-strategy=fallback-on-replace --color
  • Build your own abstractions for Kubernetes resources using normal Go code. See here for a complex example.

FAQ

Why name it kgen?

I use kapp for applying the manifests, so I thought kgen would be a good name for the tool that generates the manifests.

Why panic everywhere?

Although this is a library, it is usually used by a CLI-style program in CI/CD or local automation. If there is an error, we want the run to fail loudly. If you have a use case where panicking is not appropriate, open an issue and I can reconsider the behavior.

Contributing

Feel free to open an issue or a PR for any feature requests, bug reports, or improvements.

About

Go library for generating Kubernetes manifests with type-safe Go code, including CRD support, scoped output, and optional Helm chart rendering.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages