Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/Skidbladnir

.nornir/tier0-common-infra-for-idiots.md

tier0 common-infra — for idiots (bring up a cluster's shared services, step by step)

Class: idiot. Every step, nothing assumed. Goal: watch Skidbladnir figure out the correct order to start a cluster's shared services, and render one of them to real Kubernetes YAML — all on your laptop, no cluster.

What are we even doing?

Before your apps can run, a cluster needs four "plumbing" services:

  1. ingress-nginx — the front door (handles web traffic on ports 80/443).
  2. cert-manager — makes HTTPS certificates.
  3. holger-registry — stores your build artifacts.
  4. openbao — a safe for secrets (passwords, tokens).

Some depend on others: the registry and the vault both need certificates first. Skidbladnir works out that order for you and calls the groups waves.

Step 1 — see the bring-up order (the "waves")

Type and press Enter:

cargo test --release common_infra_waves_are_dependency_ordered

This proves the order is exactly:

wave 0: cert-manager, ingress-nginx    <- the two with no dependencies, start first
wave 1: holger-registry, openbao       <- these wait for wave 0

You start everything in wave 0 at once, wait, then start wave 1. If someone breaks a dependency, this test goes red — that's the point.

Step 2 — turn one service into real Kubernetes YAML

cargo test --release openbao_infra_spec_renders_a_k8s_statefulset_service_pvc

This takes the openbao description and renders it to actual Kubernetes manifests: a StatefulSet (because a secret store keeps data, it's "stateful"), a Service, and a PersistentVolumeClaim (a 10Gi disk). All as plain text — no cluster touched.

Step 3 — see the vault's "structure plan"

The vault pod is just the start; you also have to set up its structure (who's allowed to read which secrets). Skidbladnir writes that as a plan you can read before applying:

cargo test --release --features openbao populate_plan_for_platform_is_ordered_and_env_scoped

This proves the plan: first switch on Kubernetes login, then for each environment (say prod and staging) make a rule that lets only that environment read only its own secrets. prod can never read staging's secrets — the test checks that too.

Step 4 — render ingress-nginx's FULL set of Kubernetes objects

A real ingress controller isn't just one thing — it needs an identity (ServiceAccount), permission rules (RBAC), settings (ConfigMap), the program (Deployment), a way in from outside (LoadBalancer Service), and a name (IngressClass). Watch Skidbladnir render all nine as plain YAML:

cargo test --release ingress_nginx_renders_the_full_production_object_set

And prove the permissions actually reach the program (the RBAC binds to the exact identity the Deployment runs as — a common real-world mistake this test catches):

cargo test --release ingress_nginx_rbac_binds_the_service_account_to_its_roles

The full set is actually 18 objects — the extra nine are the "admission webhook", which double-checks every Ingress you create is valid before Kubernetes accepts it. That webhook needs an HTTPS certificate; rather than depend on cert-manager, two little Jobs make + install the cert themselves. This test proves the webhook is pointed at the right place and the cert Jobs are wired:

cargo test --release ingress_nginx_admission_webhook_points_at_admission_service_and_wires_cert

Step 5 — render cert-manager (it's actually THREE programs)

cert-manager (the thing that makes HTTPS certificates) isn't one program — it's three: the main controller, a "webhook" that checks your requests, and a "cainjector". Each needs its own identity + permissions. Watch Skidbladnir render all 28 objects and prove every program runs with the exact permissions it was granted:

cargo test --release cert_manager_renders_all_three_components_full_graph
cargo test --release cert_manager_rbac_binds_each_sa_to_its_deployment

cert-manager also needs to teach Kubernetes new object types (Certificate, Issuer, …). Authoring the FULL rules for those is a big job we deliberately left for later — so the render marks them "SCHEMA DEFERRED" (registered, but accepting anything for now). This test proves we didn't secretly half-author them:

cargo test --release cert_manager_crds_are_registered_with_schema_deferred

Why this is safe to run on a laptop

Nothing here talks to a real cluster or a real vault. The order, the YAML, and the plan are all worked out as data first (that's the "renderer half"). Actually applying them to a live cluster/vault is a separate, later step (the "deferred back half"). So you can test the whole thing green, offline, before anything real happens.