Files
jeffryandClaude Opus 5 cc66e227a3 the published surface, on a fresh root
This repository is now the public half of a split: six documents saying what to
decide, and one gap. How the cluster is built moved to jeffry/homelab-impl, which
is private because its README is an inventory of chart versions and image tags.

History starts here deliberately, and not as tidiness. The previous history
contained that inventory, and this repository is public — a deletion commit would
have removed it from the tree and left it in the log. A fresh root can only carry
what is in it.

Two pointers rewritten rather than deleted: private-access.md and .loom/README.md
both directed a reader to TAILSCALE.md and README.md at the root, which are now
private. They now say a fuller reference exists, that it is private, and how to
ask — because a public page naming a private thing as its answer is the failure
this project has now hit four times.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 15:19:14 -04:00

1.8 KiB

What a volume here can and cannot do

local-path is the only StorageClass and it is the default. Everything below follows from that, and none of it is negotiable without adding replicated storage, which is not deployed.


A volume belongs to one machine, permanently

Every volume carries a hard affinity to the node backing it. So anything with a volume inherits the availability of one machine, and the only variable left is which one.

Anything that assumes it can be rescheduled freely is assuming something this cluster does not provide.

Choose the node deliberately rather than letting it land. A volume that lands somewhere by accident becomes a single point of failure nobody picked — which happened once, and the service could not come back when that node died.

A volume cannot be grown

ALLOWVOLUMEEXPANSION is false. Growing one means dump and restore, or manual migration — not an edit.

Size with headroom. This is the constraint most likely to be discovered late.

Where this does not bite

Postgres run by the operator is shared-nothing and replicates at the database level, so a cluster of two survives losing a node even though neither volume can move. The node affinity is intended there rather than tolerated. See databases.

What would change this

Replicated storage — Longhorn being the obvious candidate — is deliberately not deployed. A substantial thing to operate on three nodes, and the downtime has not yet cost anything. Revisit when it does.


Checking this is still true

Verified 2026-09-03.

kubectl get sc                             # local-path, default, ALLOWVOLUMEEXPANSION false
kubectl get pvc -A
kubectl get pv -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeAffinity