Update Longhorn docs for two-worker topology
This commit is contained in:
+44
-20
@@ -18,11 +18,21 @@ metal — your three Talos nodes — nothing provides that on its own, the
|
||||
same gap MetalLB fills for IP addresses rather than storage.
|
||||
|
||||
**Longhorn** is that provider: it turns a plain disk on each node into one
|
||||
pool of storage, and — because your cluster has three nodes — it
|
||||
replicates each volume across more than one of them. Lose a node, and the
|
||||
data backing any volume that had a replica elsewhere is still there. This
|
||||
is also why Longhorn is genuinely a **three-node** story: with one node,
|
||||
"replicated storage" has nothing to replicate *to*.
|
||||
pool of storage, and replicates each volume across more than one node. Lose
|
||||
a node, and the data backing any volume that had a replica elsewhere is
|
||||
still there. This is why Longhorn needs more than one storage-providing
|
||||
node at all: with only one, "replicated storage" has nothing to replicate
|
||||
*to*.
|
||||
|
||||
This cluster deliberately keeps storage off the three Raspberry Pi control
|
||||
planes — they have no data disk and are not meant to run application
|
||||
workloads (see [`docs/02-talos-bootstrap.md`](02-talos-bootstrap.md)).
|
||||
Longhorn instead runs only on the two dedicated Proxmox workers, each with
|
||||
its own local NVMe-backed disk on a separate physical host (Gimli and
|
||||
Titus). `defaultReplicaCount: 2` in
|
||||
[`apps/longhorn/values.yaml`](../apps/longhorn/values.yaml) matches that:
|
||||
with exactly two storage nodes, two replicas is the most redundancy
|
||||
possible — losing either worker still leaves one complete copy.
|
||||
|
||||
## What's already running
|
||||
|
||||
@@ -33,23 +43,35 @@ umbrella-chart pattern as MetalLB, just without any extra templates of its
|
||||
own this time.
|
||||
|
||||
The interesting configuration already happened at the Talos layer, back in
|
||||
[`talos/patch-longhorn.yaml`](../talos/patch-longhorn.yaml): each node
|
||||
found, formatted, and mounted its own ≥900GB disk at
|
||||
`/var/mnt/longhorn`. [`apps/longhorn/values.yaml`](../apps/longhorn/values.yaml)
|
||||
points Longhorn's `defaultDataPath` at that exact path — this is the thing
|
||||
that makes Longhorn use *that* disk instead of carving space out of each
|
||||
node's root filesystem (small, and on Talos, not meant for this kind of
|
||||
data anyway).
|
||||
[`talos/patch-longhorn.yaml`](../talos/patch-longhorn.yaml): each worker
|
||||
found, formatted, and mounted its own ≥300GiB disk at `/var/mnt/longhorn`.
|
||||
[`apps/longhorn/values.yaml`](../apps/longhorn/values.yaml) points Longhorn's
|
||||
`defaultDataPath` at that exact path — this is the thing that makes Longhorn
|
||||
use *that* disk instead of carving space out of each node's root filesystem
|
||||
(small, and on Talos, not meant for this kind of data anyway).
|
||||
[`talos/patch-worker.yaml`](../talos/patch-worker.yaml) also labels each
|
||||
worker `node.longhorn.io/create-default-disk=true`, which is what actually
|
||||
limits default-disk creation to these two nodes instead of every node in
|
||||
the cluster — without it, Longhorn would try (and fail) to create a
|
||||
default disk on the Raspberry Pi control planes too.
|
||||
|
||||
## Verify it's actually working
|
||||
|
||||
```sh
|
||||
kubectl -n longhorn-system get pods
|
||||
kubectl -n longhorn-system get pods -o wide
|
||||
```
|
||||
|
||||
Expect a `longhorn-manager` and `longhorn-csi-plugin` Pod on each of your
|
||||
three nodes, plus one `instance-manager` per node once a volume exists,
|
||||
all `Running`.
|
||||
Expect a `longhorn-manager` and `longhorn-csi-plugin` Pod on each of the
|
||||
two workers (not the control planes), plus one `instance-manager` per
|
||||
worker once a volume exists, all `Running`. Confirm Longhorn agrees which
|
||||
nodes are eligible storage nodes:
|
||||
|
||||
```sh
|
||||
kubectl -n longhorn-system get nodes.longhorn.io -o wide
|
||||
```
|
||||
|
||||
Only the two workers should show `READY=true`, `ALLOWSCHEDULING=true`,
|
||||
`SCHEDULABLE=true`.
|
||||
|
||||
```sh
|
||||
kubectl get storageclass
|
||||
@@ -86,13 +108,15 @@ once the pre-installed pieces are confirmed working, not a requirement to
|
||||
move on.
|
||||
|
||||
> **Ask Claude:** "what would happen to that PVC's data if I lost one of
|
||||
> my three nodes right now?" — worth being able to answer before you trust
|
||||
> this with anything real.
|
||||
> my two storage workers right now?" — worth being able to answer before you
|
||||
> trust this with anything real.
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] `kubectl -n longhorn-system get pods` shows manager/CSI Pods
|
||||
`Running` on all three nodes
|
||||
- [ ] `kubectl -n longhorn-system get pods -o wide` shows manager/CSI Pods
|
||||
`Running` on both workers, and none on the control planes
|
||||
- [ ] `kubectl -n longhorn-system get nodes.longhorn.io` shows exactly the
|
||||
two workers as schedulable storage nodes
|
||||
- [ ] `kubectl get storageclass` shows a default `longhorn` StorageClass
|
||||
- [ ] (Optional) Gave the demo app a real PVC and confirmed it's `Bound`
|
||||
with a healthy, replicated Longhorn volume behind it
|
||||
|
||||
Reference in New Issue
Block a user