Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.yaml and a kustomize directory pair in your own repository
  • Confirmed that tazuna check reports the tazuna.yaml as valid
  • Able to verify “what will be installed” with tazuna build without 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 specify kustomize. Other options include helmfile and oras (see Manifest type).
  • path — the directory holding the actual content. Written as a path relative to the directory where tazuna.yaml itself 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
  • name is set, unique, and uses only allowed characters
  • The location referenced by path actually 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.

  1. Loads and validates tazuna.yaml
  2. Walks manifests[] in declaration order
  3. Hands each Manifest to its corresponding Manager (here, the kustomize Manager)
  4. The kustomize Manager renders path and reflects the result into the cluster
  5. 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 path base — it is relative to the directory containing tazuna.yaml itself. Writing it as a path relative to your cd’d location is a common cause of CI / local behavior diverging.
  • Mistaking which cluster — make it a habit to check kubectl config current-context immediately before apply. context_matches lets you prevent this structurally, but start by making visual confirmation a habit.
  • Mistaking kustomize errors for Tazuna errors — when tazuna build fails, in most cases the underlying error is from kustomize, propagated as-is. Running kustomize build ./path directly 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 that tazuna state diff can 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.