5 minutes
Introducing kat: A TUI and rule-based rendering engine for Kubernetes manifests
I don’t know about you, but one of my favorite tools in the Kubernetes ecosystem is k9s
. It’s a terminal UI (TUI) for interacting with your Kubernetes clusters, and at work I have it open pretty much all of the time. After I started using it, I felt like my productivity skyrocketed, since anything you could want is just a few keystrokes away.
However, when it comes to rendering and validating manifests locally, I found myself frustrated with the existing tools (or lack thereof). For me, I found that working with manifest generators like helm
or kustomize
often involved a repetitive cycle:
- Run
helm template
,kustomize build
, or similar commands - Search through many pages of output looking for specific resources
- Find some issue and make a change to the source files
- Re-run the rendering commands
- Re-run whatever search I originally did
- Find another issue and make a change to the source files
- Repeat ad nauseam
So, I set out to build something that would make this process easier and more efficient. After a few months of work, I’m excited to introduce you to kat
!
What is kat
?
kat
automatically invokes manifest generators like helm
or kustomize
, and provides a persistent, navigable view of rendered resources, with support for live reloading, integrated validation, and more.
It is made of two main components, which can be used together or independently:
- A rule-based engine for automatically rendering and validating manifests
- A terminal UI for browsing and debugging rendered Kubernetes manifests
Together, these deliver a seamless development experience that maintains context and focus while iterating on Helm charts, Kustomize overlays, and other manifest generators.
If you’re interested in giving
kat
a try, there are installation and usage instructions available in the repo’s README: github.com/macropower/kat
Features
Manifest Browsing: Rather than outputting a single long stream of YAML, kat
organizes the output into a browsable list structure. Navigate through any number of rendered resources using their group/kind/ns/name metadata.
Live Reload: Just use the -w
flag to automatically re-render when you modify source files, without losing your current position or context when the output changes.
Integrated Validation: Run tools like kubeconform
, kyverno
, or custom validators automatically on rendered output through configurable hooks. Additionally, you can define custom “plugins”, which function the same way as k9s plugins (i.e. commands invoked with a keybind).
Flexible Configuration: kat
allows you to define profiles for different manifest generators (like Helm, Kustomize, etc.). Profiles can be automatically selected based on output of CEL expressions, allowing kat
to adapt to your project structure.
And Customization: kat
can be configured with your own keybindings, as well as custom themes!
How do I use it?
Let’s use a simple example with helm
to illustrate how kat
works.
Note that configuration for
helm
is included in kat’s default configuration.
First, we need to define a profile for helm
. This profile will specify how to render manifests using helm template
, as well as:
- Any init, preRender, and/or postRender hooks we want to apply
- Any plugins that should be available in this context
- Any UI settings that should differ from the global config
# yaml-language-server: $schema=./config.v1beta1.json
apiVersion: kat.jacobcolvin.com/v1beta1
kind: Configuration
profiles:
helm:
command: helm
args: [template, ., --generate-name]
env: []
# Reload on edits to YAML and template files.
source: >-
files.filter(f, pathExt(f) in [".yaml", ".yml", ".tpl"])
# Inherit helm environment variables from the caller process.
envFrom: &helmEnvFrom
- callerRef:
pattern: ^HELM_.+
hooks:
# Ensure that helm is installed.
init:
- command: helm
args: [version]
# Build any helm dependencies before rendering.
preRender:
- command: helm
args: [dependency, build]
envFrom: *helmEnvFrom
# Validate rendered resources with kubeconform.
postRender:
- command: kubeconform
args: ["-strict", "-summary"]
ui:
# Use a custom theme for the helm profile.
theme: "dracula"
plugins:
# Add a plugin to invoke helm dry-run when `H` is pressed.
dry-run:
description: invoke helm dry-run
keys:
- code: H
command: helm
args: [install, ., -g, --dry-run]
envFrom: *helmEnvFrom
Now, we can use this profile to render manifests. For example, if we have a Helm chart in the current directory, we can run:
kat . helm
Next, we can define a rule
, so that we automatically select the helm
profile when we run kat
in a directory containing a helm chart:
# yaml-language-server: $schema=./config.v1beta1.json
apiVersion: kat.jacobcolvin.com/v1beta1
kind: Configuration
profiles:
# ...
rules:
# If there is a chart file in the current directory, and
# it defines `apiVersion: v2`, use the `helm` profile.
- match: >-
files.exists(f,
pathBase(f) in ["Chart.yaml", "Chart.yml"] &&
yamlPath(f, "$.apiVersion") == "v2"
)
profile: helm
Now, if we have a Helm chart in the current directory, we can simply run:
kat
And kat
will automatically select the helm
profile, render, and validate the helm chart for us.
You can continue to define additional profiles and rules to handle other manifest generators like Kustomize, Jsonnet, CUE, KCL, and more. You can also express more complex rules using CEL expressions to match specific project structures or configurations (such as using flux-local if your project contains some Fluxtomizations).
To learn more, check out the README and kat’s CEL Expression Guide.
Conclusion
kat
solved my specific workflow problems when working with Kubernetes manifests locally. And while it may not be a perfect fit for everyone, I hope it can help others who find themselves in a similar situation.
If you’re interested in giving it a try, check out the repo here:
github.com/macropower/kat (please ⭐ if you like it!)
Also, a huge thanks to the authors of the following projects (that provided inspiration and/or code):
- k9s - A terminal UI to interact with your Kubernetes clusters.
- bat - A
cat(1)
clone with wings. - task - A task runner for Go.
- glow - Render markdown on the CLI, with pizzazz!
- soft-serve - The mighty, self-hostable Git server for the command line.
- wishlist - The SSH directory.
- viddy - A modern
watch
command. - charmbracelet/bubbletea - A powerful TUI framework for Go.
- …plus many other fantastic libraries from charm
- alecthomas/chroma - A general-purpose syntax highlighter in pure Go.
- google/cel-go - A fast, portable, and safe expression evaluation engine.
- goccy/go-yaml - YAML support for Go.
- fsnotify - Cross-platform filesystem notifications.
- invopop/jsonschema - JSON Schema generation.
- santhosh-tekuri/jsonschema - JSON Schema validation.