Writing Your First tazuna.yaml
This guide walks first-time adopters of Tazuna through writing their first tazuna.yaml and installing one add-on into one Kubernetes cluster.
We use a small Deployment written with kustomize as the example, applied to a cluster through Tazuna. In real-world usage you would have ingress-nginx, cert-manager, ArgoCD, and so on lined up here, but a single manifest is enough to understand the first one.
By the end of this guide you will have:
- A
tazuna.yamland a kustomize directory pair in your own repository - Confirmed that
tazuna checkreports thetazuna.yamlas valid - Able to verify “what will be installed” with
tazuna buildwithout touching the cluster - That content reflected into the cluster via
tazuna apply
Prerequisites
Prepare One Kubernetes Cluster
Tazuna does not create the cluster itself. Preparing the control plane is a prerequisite. For experimenting, any lightweight cluster you can run locally is sufficient.
- If you want to keep things local: stand up a single-node cluster with KinD or minikube
- If you want to try against a remote first: a managed cluster like EKS / GKE / AKS, or a verification cluster brought up with
kubeadm
Any of these works as long as kubectl get nodes returns Ready.
Prepare the tazuna Binary
Either download the binary from the releases page and place it on PATH, or install with go install. See Getting Started for details.
You are ready once tazuna version works.
Check the kubeconfig current-context
Tazuna operates against the cluster currently pointed to by the kubeconfig context. Before doing anything, make absolutely sure your current-context points to the cluster you want to install into.
kubectl config current-context
kubectl get nodes
In environments where you switch between multiple clusters, mistaking this is the most typical entry point for incidents. context_matches is a mechanism to catch such mistakes, but we will not use it in the first walk-through (later guides cover it).
What We Will Build
In this guide, we will create the following directory layout.
my-cluster/
├── tazuna.yaml
└── kustomize/
└── nginx/
├── kustomization.yaml
└── deployment.yaml
tazuna.yaml declares “what to install,” and kustomize/nginx/ is the actual content. For this guide, knowing just these two layers is enough.
1. Create the kustomize Directory
First, prepare the side that Tazuna calls into — the “thing you want to install” written with kustomize. For practice, we use a minimal configuration with just one nginx Deployment.
my-cluster/kustomize/nginx/kustomization.yaml:
resources:
- deployment.yaml
my-cluster/kustomize/nginx/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
namespace: default
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
ports:
- containerPort: 80
At this point you could install the same content into the cluster with kubectl apply -k my-cluster/kustomize/nginx, without using Tazuna at all. Understanding Tazuna becomes easier if you think of it as just an extra declarative-management layer placed on top.
2. Write tazuna.yaml
Next, write tazuna.yaml — “the only input file” for Tazuna.
my-cluster/tazuna.yaml:
apiVersion: tazuna.pepabo.com/v1
kind: Tazuna
spec:
manifests:
- name: nginx
type: kustomize
path: ./kustomize/nginx
At first, you only need to set these three fields.
name— the identifier for this Manifest. State entries and log lines use this name. Use alphanumerics, hyphens, and underscores.type— which backend Tazuna uses for this Manifest. Here we specifykustomize. Other options includehelmfileandoras(see Manifest type).path— the directory holding the actual content. Written as a path relative to the directory wheretazuna.yamlitself resides.
Note that path is resolved relative to the location of tazuna.yaml itself, not the cwd where the command was run. We chose this so that calling tazuna from anywhere in the repository produces the same result.
3. Verify Validity With check
Once you have finished writing the file, first validate tazuna.yaml without touching the cluster, using tazuna check.
cd my-cluster
tazuna check
If ok is printed, the following checks have all passed.
- The file can be parsed as YAML
nameis set, unique, and uses only allowed characters- The location referenced by
pathactually exists
Anything that fails here can all be caught before touching the cluster. It is also a command that fits naturally as the first step in CI.
4. Inspect the Output Without Touching the Cluster Using build
Next, use tazuna build to write “what would be installed by tazuna apply” to stdout, without touching the cluster at all.
tazuna build
Kubernetes manifests equivalent to kustomize build are emitted. In this example, the Deployment/nginx you just wrote should come out as-is.
build does not require a connection to the cluster. Use it when you want to review whether what is about to be applied is really what you intended, or to feed the rendering result into other tools.
5. Reflect Into the Cluster With apply
Once you reach this point, you are just one command away from the real action. Confirm once more that current-context points to the target cluster, then run tazuna apply.
kubectl config current-context # It must point to the target cluster
tazuna apply
Tazuna performs the following steps in order.
- Loads and validates
tazuna.yaml - Walks
manifests[]in declaration order - Hands each Manifest to its corresponding Manager (here, the kustomize Manager)
- The kustomize Manager renders
pathand reflects the result into the cluster - Records the reflected result inside the cluster as State
State is placed in a ConfigMap (tazuna-state-<manifest-name>) under the tazuna namespace inside the cluster. The tazuna namespace is created automatically if it does not exist, so you do not need to create it beforehand.
Verify That the Apply Took Effect
You can use kubectl as you normally would, and you can also verify from the Tazuna side.
kubectl get deployment -n default nginx
tazuna state list
tazuna state list shows the resources Tazuna currently records as “installed by me.” In this guide, you should see a single Deployment/nginx entry. The resources listed here are also what tazuna destroy can later safely remove.
Common Pitfalls
Here are some common things people stumble over when writing their first one.
- Misunderstanding the
pathbase — it is relative to the directory containingtazuna.yamlitself. Writing it as a path relative to yourcd’d location is a common cause of CI / local behavior diverging. - Mistaking which cluster — make it a habit to check
kubectl config current-contextimmediately beforeapply.context_matcheslets you prevent this structurally, but start by making visual confirmation a habit. - Mistaking kustomize errors for Tazuna errors — when
tazuna buildfails, in most cases the underlying error is from kustomize, propagated as-is. Runningkustomize build ./pathdirectly to isolate is the fastest way to triage. - Mixing in things applied via hand
kubectl apply— if you mix Tazuna-driven apply with manual operations against the same cluster, State and reality will drift apart. If you do mix, just remember thattazuna state diffcan later show the differences.
Next Steps
The next guide will add more Manifests to the tazuna.yaml you built here, covering installing multiple add-ons into a cluster in order. From there we will gradually move into --tags-based filtering, splitting via includes, and preventing the-wrong-cluster accidents with context_matches.