Files
vps-k8s/docs/02-talos-bootstrap.md
T
Maxwell MorrisandClaude Sonnet 5 110bd97cca 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>
2026-08-22 18:25:38 +01:00

6.3 KiB

02 — Bootstrapping Talos

At the end of this doc, you'll have a three-node Kubernetes cluster, running nothing but Kubernetes itself (plus the storage prep Longhorn needs later). No Argo CD yet — that's next.

Why Talos, specifically

Most guides have you install a general-purpose Linux distribution, then install Kubernetes on top by hand or with a tool like kubeadm — meaning there's a whole normal OS underneath, with a package manager, an SSH daemon, and every other thing that can drift out of a known-good state or need patching. Talos throws that away: it's an OS whose only job is running Kubernetes. There's no SSH, no shell to log into, no packages to manage — you configure it entirely by sending it a machine config file over the network (the talosctl commands below), and it applies that config the same declarative way Kubernetes applies your app manifests. Less surface area, less to secure, less to keep in sync by hand — the same philosophy as the rest of this stack, one layer lower.

Three nodes, each both control plane and worker

A "real" Kubernetes cluster has multiple nodes — some running the control plane (the brain: API server, scheduler, the cluster's own database, called etcd) and others as workers (running your actual apps) — so that losing one machine doesn't take the whole cluster down. This repo starts with three nodes, each acting as both control plane and worker, which gets you real resilience — survive losing any one machine — without needing more than three.

Why three specifically, and not two: etcd (the control plane's database) uses quorum — a majority vote among its members — to agree on cluster state, and a majority only means something with an odd number of voters. With one control-plane node, losing it loses the cluster outright. Two doesn't help: losing either one leaves one survivor, which is not a majority of two. Three is the smallest number where losing any one still leaves two — a majority — able to keep agreeing on state. This is also why docs/09-growing-up.md — once you're past this doc — specifically warns against going to four control-plane nodes later: four doesn't improve on three's fault tolerance, it just makes quorum math worse.

The VIP: one address for a cluster that moves

With three control-plane nodes, "where's the API server?" no longer has one fixed answer — it's whichever nodes happen to be up right now. Talos's VIP (Virtual IP) feature solves this: the three nodes continuously elect one of themselves to answer on one shared IP address you choose, and re-elect within seconds if that node goes down. Everything that talks to this cluster — talosctl, kubectl, the Application manifests in this repo — points at the VIP, never at one node's own address. See the vip block in talos/patch-controlplane.yaml.

Ask Claude: "help me pick the VIP address for my cluster" before you generate any config — same kind of decision as the MetalLB pool in docs/05-metallb.md: a real, unused address on your LAN, outside your DHCP range, that Claude can't guess on its own.

Preparing storage for Longhorn

Each node also gets a second disk reserved for Longhorn, this repo's pre-installed storage layer — handled by talos/patch-longhorn.yaml, applied at the same time as the control-plane patch below. Read that file's comments; the short version is that Talos finds, formats, and mounts a disk for Longhorn on its own, using rules you set (not the system disk, at least 900GB), so there's no manual partitioning step here.

Steps

Full exact commands live in talos/README.md — read that alongside this doc; this section explains what's happening at each stage, that one has copy-paste blocks. You'll repeat most of these steps three times, once per node — talosctl README.md calls out exactly which commands are "once" vs. "once per node."

  1. Generate machine configuration. talosctl gen config produces Talos's config files for your cluster, with both talos/patch-controlplane.yaml (scheduling + the VIP) and talos/patch-longhorn.yaml (storage prep) baked in — read both files, they explain themselves. This produces one controlplane.yaml, applied identically to all three nodes; there's no separate worker config in this setup, since every node is both.

  2. Apply the config to each node. Each node, freshly booted from your custom Talos ISO, is sitting in "maintenance mode" with no configuration. talosctl apply-config sends it the config from step 1. Run this once per node, pointed at that node's own address. Each node reboots, installs Talos to its system disk, formats and mounts its second disk for Longhorn, and comes up running for real.

  3. Bootstrap etcd. talosctl bootstrap initializes the cluster's data store. This is a one-time, one-node-ever operation, run against exactly one of your three nodes — even though all three will end up running etcd, only one of them needs telling to start the cluster; the other two join the existing one once it exists.

  4. Retrieve your kubeconfig. talosctl kubeconfig downloads the credentials you'll use to talk to Kubernetes with kubectl — the Kubernetes equivalent of the talosconfig you got in step 1. Point it at the VIP, not at any one node.

  5. Verify. kubectl get nodes should show all three nodes, Ready.

Ask Claude: "what's the difference between a kubeconfig and a talosconfig, and why are they separate files?" is a good one to ask once you've got both — the split trips people up the first time.

Checklist

  • VIP address chosen, with Claude's help, for your LAN
  • _out/controlplane.yaml and talosconfig generated, with both patches applied
  • Config applied to all three nodes; each has rebooted, installed Talos, and mounted its Longhorn disk
  • talosctl bootstrap run exactly once, against exactly one node
  • kubeconfig retrieved, pointed at the VIP
  • kubectl get nodes shows all three nodes Ready

Once all three nodes are Ready, continue to docs/03-installing-argocd.md.