Move to a three-node cluster with a Talos VIP; add Longhorn
Every node is now both control plane and worker, giving real tolerance for losing any single machine (etcd quorum needs 3, not 1). A Talos VIP gives the cluster one stable address regardless of which node answers. Also pre-installs Longhorn for replicated storage, backed by a Talos UserVolume on each node's second disk (>=900GB, non-system) rather than the default path — mirroring the pattern from the homescale repo. Docs renumbered to make room for 06-longhorn.md; checklist, glossary, network map, and CLAUDE.md's guided-bootstrap instructions updated to match, including asking the user for node IPs, VIP, and disk info before generating any Talos config. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
92c3ad3191
commit
110bd97cca
+37
-21
@@ -1,25 +1,27 @@
|
||||
# Guided bootstrap checklist
|
||||
|
||||
A single-page, ordered checklist covering the entire path from bare
|
||||
machine to a working GitOps loop. It's meant to be worked through **with
|
||||
machines to a working GitOps loop. It's meant to be worked through **with
|
||||
Claude**, one item at a time — ask Claude to walk you through this list,
|
||||
and it will run each step with you, wait for your output, confirm it
|
||||
worked, and only then move to the next one. See `CLAUDE.md` at the repo
|
||||
root for how Claude is primed to do this.
|
||||
|
||||
Each item names the doc it's drawn from, in case you want the full
|
||||
explanation before or after running it. Replace `<NODE_IP>`,
|
||||
`YOUR_GITHUB_USERNAME`, and the MetalLB IP addresses with your real values
|
||||
throughout — Claude will remind you if you paste a command still
|
||||
containing a placeholder, and will ask you for the IP addresses directly
|
||||
in Phase 5 rather than guessing them.
|
||||
explanation before or after running it. Replace `<NODE1_IP>`/`<NODE2_IP>`/`<NODE3_IP>`,
|
||||
`<VIP_IP>`, `YOUR_GITHUB_USERNAME`, and the MetalLB IP addresses with your
|
||||
real values throughout — Claude will remind you if you paste a command
|
||||
still containing a placeholder, and will ask you for all of these directly
|
||||
in Phases 2 and 5 rather than guessing them.
|
||||
|
||||
## Phase 1 — Prerequisites ([`01`](01-prerequisites.md))
|
||||
|
||||
- [ ] Target machine chosen, reachable on the network, with a stable
|
||||
(ideally DHCP-reserved) IP address
|
||||
- [ ] Talos amd64 ISO downloaded, machine booted from it, sitting at the
|
||||
boot screen
|
||||
- [ ] Three target machines chosen, each network-reachable, each with a
|
||||
stable (ideally DHCP-reserved) IP address, each with a second disk
|
||||
≥900GB set aside for Longhorn
|
||||
- [ ] Custom Talos schematic built at factory.talos.dev with `iscsi-tools`
|
||||
and `util-linux-tools`, ISO downloaded
|
||||
- [ ] All three machines booted from that ISO, sitting at the boot screen
|
||||
- [ ] `talosctl version --client` runs successfully
|
||||
- [ ] `kubectl version --client` runs successfully
|
||||
- [ ] `argocd version --client` runs successfully
|
||||
@@ -27,12 +29,16 @@ in Phase 5 rather than guessing them.
|
||||
|
||||
## Phase 2 — Talos bootstrap ([`02`](02-talos-bootstrap.md), [`talos/README.md`](../talos/README.md))
|
||||
|
||||
- [ ] `talosctl gen config gitops-starter https://<NODE_IP>:6443 --output-dir _out --config-patch-control-plane @talos/patch-controlplane.yaml` run — `_out/controlplane.yaml`, `worker.yaml`, `talosconfig` exist
|
||||
- [ ] **Ask Claude** to help pick: your three nodes' IP addresses (or
|
||||
confirm DHCP reservations) and a separate VIP address — all based on
|
||||
your actual LAN/DHCP setup
|
||||
- [ ] `talosctl gen config gitops-starter https://<VIP_IP>:6443 --output-dir _out --config-patch-control-plane @talos/patch-controlplane.yaml --config-patch-control-plane @talos/patch-longhorn.yaml` run — `_out/controlplane.yaml`, `worker.yaml`, `talosconfig` exist
|
||||
- [ ] `TALOSCONFIG` exported (or `talosctl config endpoint`/`node` set) to `_out/talosconfig`
|
||||
- [ ] `talosctl apply-config --insecure --nodes <NODE_IP> --file _out/controlplane.yaml` run, node rebooted
|
||||
- [ ] `talosctl bootstrap --nodes <NODE_IP>` run — **exactly once**
|
||||
- [ ] `talosctl kubeconfig --nodes <NODE_IP> .` run, `KUBECONFIG` pointed at the result
|
||||
- [ ] `kubectl get nodes` shows one node, `Ready`
|
||||
- [ ] For **each** of the three nodes: `talosctl get disks --insecure --nodes <NODE_IP>` confirms two disks, then `talosctl apply-config --insecure --nodes <NODE_IP> --file _out/controlplane.yaml` run, node rebooted
|
||||
- [ ] `talosctl bootstrap --nodes <NODE1_IP>` run — **exactly once**, against **exactly one** node
|
||||
- [ ] `talosctl kubeconfig --nodes <VIP_IP> .` run, `KUBECONFIG` pointed at the result
|
||||
- [ ] `kubectl get nodes` shows **all three** nodes, `Ready`
|
||||
- [ ] `docs/network.md` updated with all three node addresses and the VIP
|
||||
|
||||
## Phase 3 — Argo CD install ([`03`](03-installing-argocd.md), [`argocd/README.md`](../argocd/README.md))
|
||||
|
||||
@@ -45,13 +51,15 @@ in Phase 5 rather than guessing them.
|
||||
|
||||
## Phase 4 — Hand the cluster to Git ([`04`](04-app-of-apps.md))
|
||||
|
||||
- [ ] `spec.source.repoURL` fixed in all three placeholder files: run
|
||||
- [ ] `spec.source.repoURL` fixed in all four placeholder files: run
|
||||
`grep -rl YOUR_GITHUB_USERNAME .` to find them
|
||||
(`argocd/app-of-apps/app-of-apps.yaml`, `apps/demo.yaml`, `apps/metallb.yaml`)
|
||||
(`argocd/app-of-apps/app-of-apps.yaml`, `apps/demo.yaml`,
|
||||
`apps/metallb.yaml`, `apps/longhorn.yaml`)
|
||||
- [ ] Edit committed and pushed to your fork's `main` branch
|
||||
- [ ] `kubectl apply -f argocd/app-of-apps/app-of-apps.yaml`
|
||||
- [ ] `argocd app list` shows `app-of-apps`, `Synced`/`Healthy`
|
||||
- [ ] `argocd app list` shows `demo` and `metallb`, appeared automatically, both `Synced`/`Healthy`
|
||||
- [ ] `argocd app list` shows `demo`, `metallb`, and `longhorn`, appeared
|
||||
automatically, all `Synced`/`Healthy`
|
||||
- [ ] `kubectl -n demo get pods,svc` shows the demo app's Pod running
|
||||
(Service `EXTERNAL-IP` still `<pending>` — expected for now)
|
||||
|
||||
@@ -68,7 +76,15 @@ in Phase 5 rather than guessing them.
|
||||
- [ ] `argocd-server` Service patched to `LoadBalancer` with your chosen Argo CD address (`kubectl -n argocd patch svc argocd-server ...`)
|
||||
- [ ] Argo CD UI reachable at `https://<that-address>` with no port-forward running
|
||||
|
||||
## Phase 6 — Prove the loop ([`06`](06-your-first-change.md))
|
||||
## Phase 6 — Longhorn: real storage ([`06`](06-longhorn.md))
|
||||
|
||||
- [ ] `kubectl -n longhorn-system get pods` shows manager/CSI Pods
|
||||
`Running` on all three 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
|
||||
|
||||
## Phase 7 — Prove the loop ([`07`](07-your-first-change.md))
|
||||
|
||||
- [ ] Edited the `<h1>` text in `apps/demo/configmap.yaml`
|
||||
- [ ] Committed and pushed
|
||||
@@ -85,6 +101,6 @@ push" and the page updating. If you can't yet, that's the sign to ask
|
||||
Claude for a walkthrough of whichever phase felt shaky before calling this
|
||||
finished.
|
||||
|
||||
From here: [`07-adding-new-apps.md`](07-adding-new-apps.md) to add
|
||||
something of your own, or [`08-growing-up.md`](08-growing-up.md) for the
|
||||
From here: [`08-adding-new-apps.md`](08-adding-new-apps.md) to add
|
||||
something of your own, or [`09-growing-up.md`](09-growing-up.md) for the
|
||||
bigger next steps (more nodes, ingress, secrets management).
|
||||
|
||||
Reference in New Issue
Block a user