50 lines
3.2 KiB
Markdown
50 lines
3.2 KiB
Markdown
# ctrl/addons.sh and ctrl/addons/*.sh
|
|
|
|
## addons.sh
|
|
|
|
Each addon is its own idempotent script — adding one is adding a file, not editing a dispatcher. `ADDONS` names them, in install order; the overlay's `addons/<name>.sh` is found before rig's `ctrl/addons/<name>.sh`, and every one runs from rig's `ctrl/` with `RIG_CTRL` exported, wherever its file lives (see [overlay.md](overlay.md)).
|
|
|
|
## The manifest beside the script
|
|
|
|
An addon's Kubernetes objects are a plain `<name>.yaml` beside its `<name>.sh`, not a heredoc inside it: the YAML reads, diffs and lints as YAML, and the script keeps only what YAML cannot do (secrets made once, a database created, waiting for a rollout). The script renders it with `render_manifest "$ADDON_DIR/<name>.yaml"` (`lib/config.sh`) and pipes it to `kubectl apply`.
|
|
|
|
`render_manifest` fills `${NAME}` and `${NAME:-default}` from the loaded config or the script's own variables, and fails on a name nothing sets, so a typo is an error rather than an empty image. `$VAR` and `$(VAR)` are left alone: they are the container's, as in postgres' `pg_isready -U $POSTGRES_USER`. selftest checks that every name a manifest uses is set somewhere. `ADDON_DIR` is taken before the script's `cd` into rig's `ctrl/`: `ADDON_DIR="$(cd "$(dirname "$0")" && pwd)"`.
|
|
|
|
## What rig ships, and what it does not
|
|
|
|
rig's own addons make the *cluster* work, and are useless outside one: metallb, cert-manager, metrics-server. Things a workload happens to need — a database, a cache, a scheduler — are the workload's, and which workload needs which is not rig's business, so they live with the overlay. `examples/data/addons/` has postgres, redis and airflow as a worked example; an overlay that wants them copies them in.
|
|
|
|
|
|
## cert-manager.sh
|
|
|
|
In a regulated estate almost everything is TLS, so the interesting question
|
|
during onboarding is "does this service present a cert my client trusts" — not
|
|
"can I reach a public ACME server". A local CA answers that offline, which is
|
|
also what makes the air-gapped profile usable.
|
|
|
|
## metallb.sh — why it matters
|
|
|
|
Real manifests use LoadBalancer, because a real cluster has one. On a bare kind
|
|
cluster those Services sit at `EXTERNAL-IP <pending>` forever with no error
|
|
anywhere — the deployment looks fine and simply is not reachable. Without MetalLB,
|
|
every such Service has to be edited to NodePort, which means the local manifests
|
|
stop matching the ones being modelled.
|
|
|
|
The address pool is derived from the kind Docker network at install time, not
|
|
hardcoded: Docker picks that subnet, it differs between machines, and a pool
|
|
outside it is silently unroutable.
|
|
|
|
## metallb.sh — waiting for the controller
|
|
|
|
`kubectl wait` on a selector errors out immediately when nothing matches yet, and
|
|
right after apply the ReplicaSet has not created the pod — so it loses a race it
|
|
looks like it should win. `rollout status` waits for the Deployment itself and
|
|
handles the not-yet-created case.
|
|
|
|
## metrics-server.sh
|
|
|
|
kind nodes serve kubelet metrics over a self-signed cert, so the standard
|
|
manifest never becomes ready without `--kubelet-insecure-tls`. That is fine here
|
|
(it is a local cluster) and is the single most common reason metrics-server sits
|
|
at 0/1 on kind.
|