# `ctrl/k8s` — the cluster, and what runs on it Same layout as every other project here: a kind config, a kustomize `base/`, and an `overlays/dev/` that patches it. ``` kind-config.yaml.tpl the cluster itself — nodes, ports base/ the components, as plain manifests overlays/dev/ how this rig differs from the base ``` ## Why the cluster config is a template Every other project checks in a literal `kind-config.yaml`, because there is exactly one `unt` and one `nvi`. A rig is copied and renamed to make a second environment, and both the cluster name and the host port block follow the directory name — so a literal would make every copy collide on both. `ctrl/cluster.sh` renders it with `sed`, substituting `${CLUSTER}`, `${NODE_IMAGE}`, `${HTTP_PORT}` and `${HOST_WORKDIR}`. Not `envsubst`: that is `gettext-base`, which a minimal Debian does not have, and Docker being the only prerequisite is the one promise rig makes. **To change the cluster, edit this file** — more nodes, other port mappings — then `make cluster reset`: a kind config is fixed at creation, not re-applied. `lib/config.sh` reads the node count back out of it, so nothing restates it. A project that builds its own cluster through rig passes its own file as `KIND_CONFIG=`; it is rendered the same way. ## `base/` — replace these **The two components in `base/` are examples, not the system.** They exist so the real manifests have a shape to be written against. The real ones are expected to be versioned **separately from the installer** — they change on a different cadence, by different people, under different review. Point `MANIFESTS_DIR` in `ctrl/.env` at their overlay and rig stops owning them: ``` MANIFESTS_DIR=../platform-manifests/overlays/dev ``` Until then it defaults to `ctrl/k8s/overlays/dev`. ### The three states a component can be in Switching between them should be a one-line change, never a rewrite. The DNS name stays the same in every case, so callers never know the difference: | state | what exists | when | | --- | --- | --- | | **real** | an image built from source, hot-reloaded | the one thing you are working on | | **mock** | a stub returning canned responses (`example-mock.yaml`) | everything else — most of the estate | | **remote** | no pod at all, just a Service (`example-remote.yaml`) | when the real system is reachable and you want it | Most components should be **mock**. What has to be faithful is the topology — names, ports, dependency order, who can reach whom, how it fails. The workloads are noise, and mocking them is what makes several copies of a large estate fit on one laptop.