Compare commits
2 Commits
6dbc83a449
...
6a005dae3b
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a005dae3b | |||
| de5b1b7ea8 |
@@ -8,13 +8,13 @@
|
||||
#
|
||||
# spr depends on rig, never the other way round. Building and deleting a cluster
|
||||
# is rig's job, so up and down hand straight to rig/ctrl/cluster.sh, carrying the
|
||||
# four things that make this cluster spr's rather than rig's defaults:
|
||||
# the things that make this cluster spr's rather than rig's defaults:
|
||||
#
|
||||
# CLUSTER=spr rooms deploy into the kind-spr context
|
||||
# KIND_CONFIG spr's own shape, which maps the rooms' gateway NodePorts
|
||||
# KIND_CONFIG spr's own kind config, which maps the rooms' gateway NodePorts
|
||||
# REGISTRY_MODE=none rooms load images straight into the node
|
||||
# PROFILE=minimal pinned here, so a change to rig's own ctrl/.env can never
|
||||
# quietly add addons to spr's cluster
|
||||
# PROFILE= ADDONS= set empty here, so rig's own ctrl/.env can never quietly
|
||||
# pick a profile or add addons to spr's cluster
|
||||
#
|
||||
# status stays here: it answers a question about rooms, not about the cluster.
|
||||
set -e
|
||||
@@ -26,7 +26,8 @@ rig() {
|
||||
CLUSTER=spr \
|
||||
KIND_CONFIG="$SCRIPT_DIR/k8s/kind-config.yaml" \
|
||||
REGISTRY_MODE=none \
|
||||
PROFILE=minimal \
|
||||
PROFILE= \
|
||||
ADDONS= \
|
||||
bash "$RIG_CTRL/cluster.sh" "$@"
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ the fact that steps four and five were also going to fail. Run now, it should be
|
||||
`ok` and `done` all the way down, and that is the point: it is the scoreboard,
|
||||
not the installer.
|
||||
|
||||
`make cluster up` builds the default `minimal` profile — one node, no addons,
|
||||
`make cluster up` builds rig's built-in defaults — one node, no addons,
|
||||
boots fast. You do not need it to develop anything, but you do want to know that
|
||||
kind, the kubeconfig context and the derived port block work *before* a new
|
||||
project has any problems of its own to confuse them with. `make cluster down`
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# make cluster up -> ctrl/cluster.sh up
|
||||
#
|
||||
# Config layers, weakest first: built-in defaults < ctrl/versions.env (pinned
|
||||
# toolchain) < ctrl/env.d/<profile>.env (optional shape) < ctrl/.env (local,
|
||||
# toolchain) < ctrl/env.d/<profile>.env (optional) < ctrl/.env (local,
|
||||
# gitignored) < the environment. So `make cluster up PROFILE=<name>` beats them all.
|
||||
#
|
||||
# Start with: make setup (then: make cluster up && make docs)
|
||||
|
||||
@@ -138,14 +138,14 @@ directory beside it.
|
||||
**rig needs no profile.** With none named it runs on built-in defaults: one node,
|
||||
no addons, a local registry, the newest Kubernetes version it pins. A profile is
|
||||
an optional overlay — a file in `ctrl/env.d/`, named by `PROFILE` — for when you
|
||||
want a different shape.
|
||||
want different addons or registry.
|
||||
|
||||
rig ships **examples**, not active profiles, because each one is a use case rather
|
||||
than something every rig needs. Copy one to use it:
|
||||
|
||||
| example | shape |
|
||||
| example | what it changes |
|
||||
| --- | --- |
|
||||
| `client.env.example` | multi-node, audit on, images through a mirror of a corporate registry |
|
||||
| `client.env.example` | images through a mirror of a corporate registry |
|
||||
| `offline.env.example` | air-gapped: everything from a preloaded local registry |
|
||||
| `data.env.example` | databases and a scheduler: postgres, redis, airflow |
|
||||
|
||||
@@ -156,17 +156,9 @@ PROFILE=data make addons install
|
||||
make addons # what the active profile wants, and what exists
|
||||
```
|
||||
|
||||
A profile names a **cluster shape** — a file in `ctrl/k8s/` — rather than
|
||||
restating node count and audit as variables:
|
||||
|
||||
| shape | nodes | audit | used by |
|
||||
| --- | --- | --- | --- |
|
||||
| `kind-config.yaml.tpl` | 1 | off | the default; the `data` example |
|
||||
| `kind-config.audit.yaml.tpl` | 1 | on | the `offline` example |
|
||||
| `kind-config.client.yaml.tpl` | 3 | on | the `client` example |
|
||||
|
||||
Both numbers are read back out of the chosen file, so the YAML is the only place
|
||||
that decides and there is nothing to drift. The layout under `ctrl/k8s/` is the
|
||||
The **cluster itself** is one file, `ctrl/k8s/kind-config.yaml.tpl` (one node).
|
||||
To change it — more nodes, other port mappings — edit it and `make cluster
|
||||
reset`. The node count is read back out of it, so there is nothing to drift. The layout under `ctrl/k8s/` is the
|
||||
same as every other project here — a kind config, a kustomize `base/`, an
|
||||
`overlays/dev/` — see [`ctrl/k8s/README.md`](ctrl/k8s/README.md).
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ load_config
|
||||
|
||||
echo
|
||||
echo "config"
|
||||
echo " profile ${PROFILE_NAME} (nodes=${NODES} audit=${AUDIT})"
|
||||
echo " profile ${PROFILE_NAME} (nodes=${NODES})"
|
||||
echo " cluster ${CLUSTER} (context ${KUBECONTEXT})"
|
||||
echo " registry ${REGISTRY_MODE}"
|
||||
echo " ingress ${INGRESS_MODE}"
|
||||
|
||||
@@ -23,15 +23,14 @@ up() {
|
||||
echo "cluster '$CLUSTER' exists — converging"
|
||||
else
|
||||
# Say what this profile locks in BEFORE spending minutes building it:
|
||||
# the audit policy is an apiserver flag and cannot be changed later.
|
||||
# the kind config is fixed at creation and cannot be changed later.
|
||||
echo "creating cluster '$CLUSTER' from profile '$PROFILE_NAME'"
|
||||
echo " shape ${KIND_CONFIG_SHOWN}"
|
||||
echo " kind config ${KIND_CONFIG}"
|
||||
echo " nodes $NODES"
|
||||
echo " image $NODE_IMAGE"
|
||||
echo " audit $AUDIT"
|
||||
echo " ingress $INGRESS_MODE"
|
||||
echo " registry $REGISTRY_MODE"
|
||||
echo " (audit is fixed at creation — 'make cluster reset' to change it)"
|
||||
echo " (fixed at creation — edit the kind config, then 'make cluster reset')"
|
||||
echo
|
||||
|
||||
render_kind_config | kind create cluster --config -
|
||||
@@ -69,7 +68,7 @@ down() {
|
||||
}
|
||||
|
||||
# The escape hatch for a wedged cluster, and the only way to change a
|
||||
# creation-time setting such as the audit policy.
|
||||
# creation-time setting such as the node count or port mappings.
|
||||
reset() {
|
||||
down
|
||||
echo
|
||||
|
||||
@@ -3,16 +3,11 @@
|
||||
# directory and name it — PROFILE=client in ctrl/.env, or on the command line. It
|
||||
# then overlays the defaults; anything it does not set, they still supply.
|
||||
#
|
||||
# client — the regulated-estate shape. Multi-node so taints, affinity and
|
||||
# topology are real; apiserver audit on; images through a pull-through cache of
|
||||
# the corporate registry.
|
||||
#
|
||||
# Costs roughly 4-6 GB. Check `make cluster list` before starting this alongside
|
||||
# other work — see the memory note in the README.
|
||||
# client — images through a pull-through cache of the corporate registry, with
|
||||
# TLS and metrics addons. More nodes or port mappings: edit k8s/kind-config.yaml.tpl.
|
||||
|
||||
PROFILE_NAME=client
|
||||
K8S_VERSION=v1_36
|
||||
KIND_CONFIG=kind-config.client.yaml.tpl
|
||||
ADDONS="metallb cert-manager metrics-server"
|
||||
REGISTRY_MODE=mirror
|
||||
INGRESS_MODE=hostport
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
PROFILE_NAME=data
|
||||
K8S_VERSION=v1_36
|
||||
KIND_CONFIG=kind-config.yaml.tpl
|
||||
# Order matters: addons.sh installs in the order listed, and airflow refuses to
|
||||
# start without a metadata database, so postgres comes first.
|
||||
ADDONS="metallb postgres redis airflow"
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
PROFILE_NAME=offline
|
||||
K8S_VERSION=v1_36
|
||||
KIND_CONFIG=kind-config.audit.yaml.tpl
|
||||
ADDONS="metallb"
|
||||
REGISTRY_MODE=local
|
||||
INGRESS_MODE=hostport
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
# `ctrl/k8s` — cluster shape, and what runs on it
|
||||
# `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, audit
|
||||
kind-config.yaml.tpl the cluster itself — nodes, ports
|
||||
base/ the components, as plain manifests
|
||||
overlays/dev/ how this rig differs from the base
|
||||
audit-policy.yaml mounted into the apiserver by the audit shapes
|
||||
```
|
||||
|
||||
## Why the cluster config is a template
|
||||
@@ -22,21 +21,12 @@ directory name — so a literal would make every copy collide on both.
|
||||
`gettext-base`, which a minimal Debian does not have, and Docker being the only
|
||||
prerequisite is the one promise rig makes.
|
||||
|
||||
**The chosen file is the source of truth for node count and audit.**
|
||||
`lib/config.sh` reads both back out of it, so a profile names a shape and does
|
||||
not restate what the YAML already says.
|
||||
**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.
|
||||
|
||||
| file | nodes | audit | profiles |
|
||||
| --- | --- | --- | --- |
|
||||
| `kind-config.yaml.tpl` | 1 | off | the default; the `data` example |
|
||||
| `kind-config.audit.yaml.tpl` | 1 | on | the `offline` example |
|
||||
| `kind-config.client.yaml.tpl` | 3 | on | the `client` example |
|
||||
|
||||
With no profile the default shape is used; a profile picks another with
|
||||
`KIND_CONFIG`. Adding a shape is adding a file — there is no dispatcher to edit.
|
||||
|
||||
Audit is an apiserver flag and therefore fixed at creation: changing it is
|
||||
`make cluster reset`, not a re-apply.
|
||||
A project that builds its own cluster through rig passes its own file as
|
||||
`KIND_CONFIG=<path>`; it is rendered the same way.
|
||||
|
||||
## `base/` — replace these
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
# Apiserver audit policy. Mounted into the control plane at creation when a
|
||||
# profile sets AUDIT=on — an apiserver flag, so it cannot be added to a running
|
||||
# cluster without recreating it.
|
||||
#
|
||||
# Deliberately modest: enough to make "who changed what, and when" answerable
|
||||
# during onboarding without filling the disk. Read the log with:
|
||||
# docker exec <cluster>-control-plane cat /var/log/kubernetes/audit.log
|
||||
apiVersion: audit.k8s.io/v1
|
||||
kind: Policy
|
||||
|
||||
# Never log the request body for these — they contain credentials.
|
||||
omitStages:
|
||||
- RequestReceived
|
||||
|
||||
rules:
|
||||
# Secrets/configmaps: record that access happened, never the contents.
|
||||
- level: Metadata
|
||||
resources:
|
||||
- group: ""
|
||||
resources: ["secrets", "configmaps"]
|
||||
|
||||
# Authn/authz decisions — the part an auditor actually asks about.
|
||||
- level: Metadata
|
||||
nonResourceURLs:
|
||||
- /apis*
|
||||
- /api*
|
||||
|
||||
# Mutations to workloads and policy: full request, so a diff is reconstructable.
|
||||
- level: Request
|
||||
verbs: ["create", "update", "patch", "delete"]
|
||||
resources:
|
||||
- group: ""
|
||||
resources: ["pods", "services", "serviceaccounts", "namespaces"]
|
||||
- group: "apps"
|
||||
- group: "networking.k8s.io"
|
||||
- group: "rbac.authorization.k8s.io"
|
||||
|
||||
# Everything else that changes state: metadata only.
|
||||
- level: Metadata
|
||||
verbs: ["create", "update", "patch", "delete"]
|
||||
|
||||
# Reads are dropped entirely — otherwise controller polling drowns the log.
|
||||
- level: None
|
||||
verbs: ["get", "list", "watch"]
|
||||
@@ -1,57 +0,0 @@
|
||||
# Cluster shape: one node, apiserver audit ON. Used by the `offline` profile.
|
||||
#
|
||||
# Audit is an apiserver flag, so it is fixed when the cluster is created —
|
||||
# changing it means `make cluster reset`, not a re-apply. That is why it is a
|
||||
# property of the cluster file rather than something switched at runtime.
|
||||
#
|
||||
# k8s >= 1.31 uses kubeadm v1beta4, where extraArgs is a LIST of name/value
|
||||
# pairs. The older map form is silently ignored — it does not error, audit
|
||||
# simply never turns on.
|
||||
#
|
||||
# Substituted by ctrl/cluster.sh: CLUSTER, NODE_IMAGE, HTTP_PORT, HOST_WORKDIR
|
||||
# (named without the ${...} braces so this line survives the substitution)
|
||||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
name: ${CLUSTER}
|
||||
|
||||
containerdConfigPatches:
|
||||
- |-
|
||||
[plugins."io.containerd.grpc.v1.cri".registry]
|
||||
config_path = "/etc/containerd/certs.d"
|
||||
|
||||
kubeadmConfigPatches:
|
||||
- |
|
||||
kind: ClusterConfiguration
|
||||
apiServer:
|
||||
extraArgs:
|
||||
- name: audit-policy-file
|
||||
value: /etc/kubernetes/audit/policy.yaml
|
||||
- name: audit-log-path
|
||||
value: /var/log/kubernetes/audit.log
|
||||
- name: audit-log-maxage
|
||||
value: "7"
|
||||
extraVolumes:
|
||||
- name: audit-policy
|
||||
hostPath: /etc/kubernetes/audit
|
||||
mountPath: /etc/kubernetes/audit
|
||||
readOnly: true
|
||||
- name: audit-log
|
||||
hostPath: /var/log/kubernetes
|
||||
mountPath: /var/log/kubernetes
|
||||
readOnly: false
|
||||
|
||||
nodes:
|
||||
- role: control-plane
|
||||
image: ${NODE_IMAGE}
|
||||
# hostPath is resolved by the HOST dockerd, so this must be a host path even
|
||||
# when cluster.sh runs inside the installer container. HOST_WORKDIR says where
|
||||
# this rig lives on the host; bare on a host it is just the repo root.
|
||||
extraMounts:
|
||||
- hostPath: ${HOST_WORKDIR}/ctrl/k8s/audit-policy.yaml
|
||||
containerPath: /etc/kubernetes/audit/policy.yaml
|
||||
readOnly: true
|
||||
extraPortMappings:
|
||||
- containerPort: 30080
|
||||
hostPort: ${HTTP_PORT}
|
||||
listenAddress: "0.0.0.0"
|
||||
protocol: TCP
|
||||
@@ -1,55 +0,0 @@
|
||||
# Cluster shape: three nodes, apiserver audit ON. Used by the `client` profile —
|
||||
# the regulated-estate shape.
|
||||
#
|
||||
# Multi-node so taints, affinity and topology spread are real rather than
|
||||
# vacuously satisfied by a single node. It costs roughly 4-6 GB; run
|
||||
# `make cluster list` before starting this alongside other work.
|
||||
#
|
||||
# Substituted by ctrl/cluster.sh: CLUSTER, NODE_IMAGE, HTTP_PORT, HOST_WORKDIR
|
||||
# (named without the ${...} braces so this line survives the substitution)
|
||||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
name: ${CLUSTER}
|
||||
|
||||
containerdConfigPatches:
|
||||
- |-
|
||||
[plugins."io.containerd.grpc.v1.cri".registry]
|
||||
config_path = "/etc/containerd/certs.d"
|
||||
|
||||
kubeadmConfigPatches:
|
||||
- |
|
||||
kind: ClusterConfiguration
|
||||
apiServer:
|
||||
extraArgs:
|
||||
- name: audit-policy-file
|
||||
value: /etc/kubernetes/audit/policy.yaml
|
||||
- name: audit-log-path
|
||||
value: /var/log/kubernetes/audit.log
|
||||
- name: audit-log-maxage
|
||||
value: "7"
|
||||
extraVolumes:
|
||||
- name: audit-policy
|
||||
hostPath: /etc/kubernetes/audit
|
||||
mountPath: /etc/kubernetes/audit
|
||||
readOnly: true
|
||||
- name: audit-log
|
||||
hostPath: /var/log/kubernetes
|
||||
mountPath: /var/log/kubernetes
|
||||
readOnly: false
|
||||
|
||||
nodes:
|
||||
- role: control-plane
|
||||
image: ${NODE_IMAGE}
|
||||
extraMounts:
|
||||
- hostPath: ${HOST_WORKDIR}/ctrl/k8s/audit-policy.yaml
|
||||
containerPath: /etc/kubernetes/audit/policy.yaml
|
||||
readOnly: true
|
||||
extraPortMappings:
|
||||
- containerPort: 30080
|
||||
hostPort: ${HTTP_PORT}
|
||||
listenAddress: "0.0.0.0"
|
||||
protocol: TCP
|
||||
- role: worker
|
||||
image: ${NODE_IMAGE}
|
||||
- role: worker
|
||||
image: ${NODE_IMAGE}
|
||||
@@ -1,4 +1,5 @@
|
||||
# Cluster shape: one node, no audit. Used by the `minimal` and `data` profiles.
|
||||
# The cluster. One node by default — add nodes or port mappings by editing this
|
||||
# file, then `make cluster reset`.
|
||||
#
|
||||
# A TEMPLATE rather than a plain kind-config.yaml because a rig is copied and
|
||||
# renamed to make a second environment, and both the cluster name and the host
|
||||
@@ -9,8 +10,8 @@
|
||||
#
|
||||
# Substituted by ctrl/cluster.sh: CLUSTER, NODE_IMAGE, HTTP_PORT, HOST_WORKDIR
|
||||
# (named without the ${...} braces so this line survives the substitution)
|
||||
# Node count and audit are READ BACK from this file by lib/config.sh, so this
|
||||
# YAML is the source of truth for both — there is no second place to update.
|
||||
# The node count is READ BACK from this file by lib/config.sh, so this YAML is
|
||||
# the source of truth for it — there is no second place to update.
|
||||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
name: ${CLUSTER}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
# built-in defaults below; fill only what nothing else set
|
||||
# ctrl/versions.env pinned toolchain + image digests (committed)
|
||||
# ctrl/env.d/<profile> cluster shape — OPTIONAL, examples ship as *.env.example
|
||||
# ctrl/env.d/<profile> addons, registry — OPTIONAL, examples ship as *.env.example
|
||||
# ctrl/.env machine-local values and secrets (gitignored)
|
||||
# the caller's env `make cluster up PROFILE=<name>` (always wins)
|
||||
#
|
||||
@@ -19,9 +19,8 @@
|
||||
|
||||
# Values a user can reasonably override per-invocation. Anything set in the
|
||||
# environment when load_config runs is restored after the files are read.
|
||||
# NODES and AUDIT are deliberately NOT here: they are properties of the chosen
|
||||
# ctrl/k8s/kind-config*.yaml.tpl and are read back out of it below, so there is
|
||||
# one place that decides the shape of the cluster rather than two that can drift.
|
||||
# NODES is deliberately NOT here: it is read back out of the kind config below,
|
||||
# so the file is the one place that decides it.
|
||||
#
|
||||
# REGISTRY_PORT and MANIFESTS_DIR were missing here while ctrl/.env set them, so
|
||||
# the caller's env silently LOST to the file for those two — the one precedence
|
||||
@@ -136,32 +135,18 @@ load_config() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The cluster's shape is a file in ctrl/k8s/, named by the profile. Adding a
|
||||
# shape is adding a file; there is no dispatcher to edit.
|
||||
#
|
||||
# A host that needs its own shape — extra port mappings, more nodes — passes
|
||||
# an absolute path instead, and rig renders it exactly like one of its own:
|
||||
# ${CLUSTER} and ${NODE_IMAGE} are substituted either way. The shape stays in
|
||||
# the host's tree, because what a host's cluster needs is the host's business;
|
||||
# rig only knows how to build whatever it is handed.
|
||||
KIND_CONFIG="${KIND_CONFIG:-kind-config.yaml.tpl}"
|
||||
case "$KIND_CONFIG" in
|
||||
/*) KIND_CONFIG_PATH="$KIND_CONFIG"; KIND_CONFIG_SHOWN="$KIND_CONFIG" ;;
|
||||
*) KIND_CONFIG_PATH="./k8s/${KIND_CONFIG}"; KIND_CONFIG_SHOWN="ctrl/k8s/${KIND_CONFIG}" ;;
|
||||
esac
|
||||
if [ ! -f "$KIND_CONFIG_PATH" ]; then
|
||||
echo "no such cluster shape: ${KIND_CONFIG_SHOWN}" >&2
|
||||
echo "rig's own: $(ls k8s/kind-config*.yaml.tpl 2>/dev/null | xargs -n1 basename | tr '\n' ' ')" >&2
|
||||
echo "or pass an absolute path to a shape of your own" >&2
|
||||
# The cluster is one file: k8s/kind-config.yaml.tpl. To change it, edit it.
|
||||
# KIND_CONFIG is only "use this file instead", for a project that builds its
|
||||
# own cluster through rig (a path relative to ctrl/, or absolute).
|
||||
KIND_CONFIG="${KIND_CONFIG:-./k8s/kind-config.yaml.tpl}"
|
||||
if [ ! -f "$KIND_CONFIG" ]; then
|
||||
echo "no kind config at KIND_CONFIG=${KIND_CONFIG}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read the shape back out of the YAML rather than trusting a profile to
|
||||
# restate it. check.sh sizes the memory warning on NODES, and cluster.sh
|
||||
# prints AUDIT before spending minutes building something that cannot be
|
||||
# changed afterwards — both would mislead if the numbers drifted.
|
||||
NODES=$(grep -c '^ - role:' "$KIND_CONFIG_PATH")
|
||||
if grep -q 'audit-policy-file' "$KIND_CONFIG_PATH"; then AUDIT=on; else AUDIT=off; fi
|
||||
# Read the node count back out of the file rather than restating it:
|
||||
# check.sh and the memory tool size their budget on NODES.
|
||||
NODES=$(grep -c '^ - role:' "$KIND_CONFIG")
|
||||
|
||||
# What one node costs, measured rather than guessed. On 2026-09-11 a minimal
|
||||
# control-plane node ran at 620 MiB idle and ~728 MiB with a small mock, plus
|
||||
@@ -175,7 +160,7 @@ load_config() {
|
||||
NODE_MB=800
|
||||
}
|
||||
|
||||
# Render a cluster shape to stdout. sed rather than envsubst: envsubst is
|
||||
# Render the kind config to stdout. sed rather than envsubst: envsubst is
|
||||
# gettext-base, absent from a minimal Debian, and Docker is meant to be the only
|
||||
# prerequisite. The variable list is explicit so a template cannot quietly start
|
||||
# depending on something the caller does not set.
|
||||
@@ -188,7 +173,7 @@ render_kind_config() {
|
||||
-e "s|\${NODE_IMAGE}|${NODE_IMAGE}|g" \
|
||||
-e "s|\${HTTP_PORT}|${HTTP_PORT}|g" \
|
||||
-e "s|\${HOST_WORKDIR}|${host_workdir}|g" \
|
||||
"$KIND_CONFIG_PATH"
|
||||
"$KIND_CONFIG"
|
||||
}
|
||||
|
||||
_config_restore() {
|
||||
|
||||
@@ -99,7 +99,9 @@ test_value() {
|
||||
# profile, template or pinned version to be present for this to run.
|
||||
PROFILE) config_profiles | head -1 ;;
|
||||
K8S_VERSION) (set -a; source ./versions.env; compgen -v NODE_IMAGE_v | sort -V | head -1 | sed 's/^NODE_IMAGE_//') ;;
|
||||
KIND_CONFIG) ls k8s/kind-config*.yaml.tpl 2>/dev/null | sort | head -1 | xargs -r basename ;;
|
||||
# An absolute path, as a project passing its own file does. Never equal
|
||||
# to the default, so the check cannot pass by accident.
|
||||
KIND_CONFIG) echo "$PWD/k8s/kind-config.yaml.tpl" ;;
|
||||
*_PORT) echo "19999" ;;
|
||||
CLUSTER) echo "selftest-name" ;;
|
||||
MANIFESTS_DIR) echo "../elsewhere/overlays/dev" ;;
|
||||
|
||||
@@ -32,7 +32,7 @@ digraph rig_environment {
|
||||
fontcolor="#8892a8"
|
||||
|
||||
versions [label="versions.env\npinned toolchain" fillcolor="#121829"]
|
||||
profile [label="env.d/<profile>.env\nnodes · CNI · audit · addons" fillcolor="#121829"]
|
||||
profile [label="env.d/<profile>.env\noptional: addons · registry" fillcolor="#121829"]
|
||||
localenv [label="ctrl/.env\nsecrets, overrides" fillcolor="#121829"]
|
||||
shell [label="the environment\nPROFILE=client make …" fillcolor="#1a3a1a" fontcolor="#00c853"]
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
<title>profile</title>
|
||||
<polygon fill="#121829" stroke="#1e2a4a" points="781.5,-318.58 612.5,-318.58 612.5,-282.58 781.5,-282.58 781.5,-318.58"/>
|
||||
<text xml:space="preserve" text-anchor="middle" x="697" y="-303.63" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">env.d/<profile>.env</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="697" y="-290.13" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">nodes · CNI · audit · addons</text>
|
||||
<text xml:space="preserve" text-anchor="middle" x="697" y="-290.13" font-family="Helvetica,sans-Serif" font-size="11.00" fill="#e8eaf0">optional: addons · registry</text>
|
||||
</g>
|
||||
<!-- versions->profile -->
|
||||
<g id="edge6" class="edge">
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@@ -302,15 +302,15 @@ make cluster up <span class="c"># build the cluster for the active profile</spa
|
||||
|
||||
<h3>3 · make cluster up</h3>
|
||||
<p>Builds the cluster for the active profile. It prints what the profile
|
||||
locks in <i>before</i> spending the time, because the CNI and the audit
|
||||
policy are fixed at creation and cannot be changed afterwards.</p>
|
||||
locks in <i>before</i> spending the time, because the kind config is
|
||||
fixed at creation and cannot be changed afterwards.</p>
|
||||
<p>Re-running is safe and, more importantly, <b>convergent</b>: if a first
|
||||
attempt was interrupted before the CNI was installed, running it again
|
||||
finishes the job rather than reporting "already exists" and leaving every
|
||||
node permanently NotReady.</p>
|
||||
<pre><code>make cluster up <span class="c"># built-in defaults — no profile needed</span>
|
||||
make cluster up PROFILE=client <span class="c"># after copying env.d/client.env.example: three nodes, audit, cached registry</span>
|
||||
make cluster reset <span class="c"># destroy and rebuild — the only way to change CNI or audit</span>
|
||||
make cluster up PROFILE=client <span class="c"># after copying env.d/client.env.example: cached registry</span>
|
||||
make cluster reset <span class="c"># destroy and rebuild — how an edited kind config takes effect</span>
|
||||
</code></pre>
|
||||
|
||||
<h3>4 · make docs</h3>
|
||||
@@ -416,19 +416,20 @@ docker load < rig.tgz && make cluster up PROFILE=offline <span clas
|
||||
|
||||
<section class="section" id="profiles">
|
||||
<h2>Profiles</h2>
|
||||
<p class="lede">Cluster shape is declared, not baked in.</p>
|
||||
<p class="lede">Optional overlays — rig needs none.</p>
|
||||
<div class="prose">
|
||||
<table>
|
||||
<tr><th>profile</th><th>nodes</th><th>audit</th><th>registry</th><th>for</th></tr>
|
||||
<tr><td><code>minimal</code></td><td>1</td><td>off</td><td>none</td><td>first boot; assumes nothing</td></tr>
|
||||
<tr><td><code>client</code></td><td>3</td><td>on</td><td>mirror</td><td>the regulated shape</td></tr>
|
||||
<tr><td><code>offline</code></td><td>1</td><td>on</td><td>local</td><td>air-gapped</td></tr>
|
||||
<tr><th>example</th><th>registry</th><th>for</th></tr>
|
||||
<tr><td><i>none</i></td><td>local</td><td>the built-in defaults; no profile needed</td></tr>
|
||||
<tr><td><code>client.env.example</code></td><td>mirror</td><td>images through a corporate registry</td></tr>
|
||||
<tr><td><code>offline.env.example</code></td><td>local</td><td>air-gapped</td></tr>
|
||||
<tr><td><code>data.env.example</code></td><td>local</td><td>postgres, redis, airflow</td></tr>
|
||||
</table>
|
||||
|
||||
<div class="note"><p><b>The audit policy cannot be changed later.</b> It is an
|
||||
apiserver flag, fixed when the cluster is created. <code>cluster up</code>
|
||||
prints what a profile locks in before spending the time, and
|
||||
<code>make cluster reset</code> is the way out.</p></div>
|
||||
<div class="note"><p><b>The kind config cannot be re-applied.</b> Edit
|
||||
<code>ctrl/k8s/kind-config.yaml.tpl</code>; it takes effect when the cluster is created. <code>cluster up</code> prints what it
|
||||
locks in before spending the time, and <code>make cluster reset</code> is
|
||||
the way out.</p></div>
|
||||
|
||||
<h3>LoadBalancer services</h3>
|
||||
<p>Real manifests use <code>type: LoadBalancer</code>, because a real
|
||||
|
||||
@@ -36,7 +36,7 @@ derive_port_base ()
|
||||
render_kind_config ()
|
||||
{
|
||||
local host_workdir="${HOST_WORKDIR:-$(cd .. && pwd)}";
|
||||
sed -e "s|\${CLUSTER}|${CLUSTER}|g" -e "s|\${NODE_IMAGE}|${NODE_IMAGE}|g" -e "s|\${HTTP_PORT}|${HTTP_PORT}|g" -e "s|\${HOST_WORKDIR}|${host_workdir}|g" "$KIND_CONFIG_PATH"
|
||||
sed -e "s|\${CLUSTER}|${CLUSTER}|g" -e "s|\${NODE_IMAGE}|${NODE_IMAGE}|g" -e "s|\${HTTP_PORT}|${HTTP_PORT}|g" -e "s|\${HOST_WORKDIR}|${host_workdir}|g" "$KIND_CONFIG"
|
||||
}
|
||||
|
||||
# ── configuration, frozen for profile 'default' ──
|
||||
@@ -47,7 +47,6 @@ load_config() {
|
||||
done
|
||||
declare -g ADDONS=""
|
||||
declare -gx AIRFLOW_IMAGE="apache/airflow:2.10.4"
|
||||
declare -g AUDIT="off"
|
||||
declare -gx CERT_MANAGER_VERSION="v1.21.1"
|
||||
declare -g CLUSTER="rig"
|
||||
declare -gx COMPOSE_SHA256="db1889184726840f75c4f9c001048430d4f25b3be3cb084d3ddd762bc0aed576"
|
||||
@@ -64,9 +63,7 @@ load_config() {
|
||||
declare -gx JQ_URL="https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-amd64"
|
||||
declare -gx JQ_VERSION="1.8.2"
|
||||
declare -g K8S_VERSION="v1_36"
|
||||
declare -g KIND_CONFIG="kind-config.yaml.tpl"
|
||||
declare -g KIND_CONFIG_PATH="./k8s/kind-config.yaml.tpl"
|
||||
declare -g KIND_CONFIG_SHOWN="ctrl/k8s/kind-config.yaml.tpl"
|
||||
declare -g KIND_CONFIG="./k8s/kind-config.yaml.tpl"
|
||||
declare -gx KIND_SHA256="50030de23cf40a18505f20426f6a8506bedf13c6e509244bd1fa9463721b0f54"
|
||||
declare -gx KIND_URL="https://github.com/kubernetes-sigs/kind/releases/download/v0.32.0/kind-linux-amd64"
|
||||
declare -gx KIND_VERSION="v0.32.0"
|
||||
|
||||
@@ -36,7 +36,7 @@ derive_port_base ()
|
||||
render_kind_config ()
|
||||
{
|
||||
local host_workdir="${HOST_WORKDIR:-$(cd .. && pwd)}";
|
||||
sed -e "s|\${CLUSTER}|${CLUSTER}|g" -e "s|\${NODE_IMAGE}|${NODE_IMAGE}|g" -e "s|\${HTTP_PORT}|${HTTP_PORT}|g" -e "s|\${HOST_WORKDIR}|${host_workdir}|g" "$KIND_CONFIG_PATH"
|
||||
sed -e "s|\${CLUSTER}|${CLUSTER}|g" -e "s|\${NODE_IMAGE}|${NODE_IMAGE}|g" -e "s|\${HTTP_PORT}|${HTTP_PORT}|g" -e "s|\${HOST_WORKDIR}|${host_workdir}|g" "$KIND_CONFIG"
|
||||
}
|
||||
|
||||
# ── configuration, frozen for profile 'default' ──
|
||||
@@ -47,7 +47,6 @@ load_config() {
|
||||
done
|
||||
declare -g ADDONS=""
|
||||
declare -gx AIRFLOW_IMAGE="apache/airflow:2.10.4"
|
||||
declare -g AUDIT="off"
|
||||
declare -gx CERT_MANAGER_VERSION="v1.21.1"
|
||||
declare -g CLUSTER="rig"
|
||||
declare -gx COMPOSE_SHA256="db1889184726840f75c4f9c001048430d4f25b3be3cb084d3ddd762bc0aed576"
|
||||
@@ -64,9 +63,7 @@ load_config() {
|
||||
declare -gx JQ_URL="https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-amd64"
|
||||
declare -gx JQ_VERSION="1.8.2"
|
||||
declare -g K8S_VERSION="v1_36"
|
||||
declare -g KIND_CONFIG="kind-config.yaml.tpl"
|
||||
declare -g KIND_CONFIG_PATH="./k8s/kind-config.yaml.tpl"
|
||||
declare -g KIND_CONFIG_SHOWN="ctrl/k8s/kind-config.yaml.tpl"
|
||||
declare -g KIND_CONFIG="./k8s/kind-config.yaml.tpl"
|
||||
declare -gx KIND_SHA256="50030de23cf40a18505f20426f6a8506bedf13c6e509244bd1fa9463721b0f54"
|
||||
declare -gx KIND_URL="https://github.com/kubernetes-sigs/kind/releases/download/v0.32.0/kind-linux-amd64"
|
||||
declare -gx KIND_VERSION="v0.32.0"
|
||||
|
||||
Reference in New Issue
Block a user