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>
148 lines
5.7 KiB
Markdown
148 lines
5.7 KiB
Markdown
# Talos bootstrap — command reference
|
||
|
||
This is the detailed, copy-pasteable companion to
|
||
[`docs/02-talos-bootstrap.md`](../docs/02-talos-bootstrap.md). Read that file
|
||
first for the explanations — this one is here so you have every exact
|
||
command in one place once you understand what they do.
|
||
|
||
Throughout, replace `<NODE1_IP>`, `<NODE2_IP>`, `<NODE3_IP>` with your three
|
||
machines' real IP addresses, and `<VIP_IP>` with the shared address you
|
||
picked (with Claude's help) for the cluster's VIP — see
|
||
[`docs/02-talos-bootstrap.md`](../docs/02-talos-bootstrap.md#the-vip-one-address-for-a-cluster-that-moves).
|
||
Give each machine a DHCP reservation (a fixed IP tied to its MAC address)
|
||
in your router or hypervisor before you start, so none of these addresses
|
||
change under the cluster. Talos bakes them into certificates during setup,
|
||
and changing one later means starting over for that node.
|
||
|
||
Steps 1–2 below run **once, total**. Steps 3 runs **once per node** (three
|
||
times). Steps 4–6 run **once, total**, against whichever node you like
|
||
(or, once it exists, the VIP).
|
||
|
||
All commands assume you're running them from the root of this repo.
|
||
|
||
## 1. Generate machine configuration
|
||
|
||
```sh
|
||
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
|
||
```
|
||
|
||
Note the cluster endpoint here is the **VIP**, not any one node's address
|
||
— every node needs to agree in advance on where the cluster "lives," and
|
||
that address has to be the one that keeps working no matter which node is
|
||
currently answering.
|
||
|
||
This writes three files into `_out/` (already covered by this repo's
|
||
`.gitignore` — they contain private keys and must never be committed):
|
||
|
||
- `controlplane.yaml` — the machine configuration for a control-plane
|
||
node, with both patches baked in. Applied identically to all three
|
||
nodes — there's no separate worker config in this setup, since every
|
||
node is both.
|
||
- `worker.yaml` — a plain worker config, generated automatically but
|
||
unused here since every node in this repo's setup is both control plane
|
||
and worker. Kept around for [`docs/09-growing-up.md`](../docs/09-growing-up.md),
|
||
where a fourth-and-beyond node uses exactly this file.
|
||
- `talosconfig` — *your* client credentials for talking to the Talos API on
|
||
this cluster (equivalent in spirit to a kubeconfig, but for Talos itself
|
||
rather than Kubernetes).
|
||
|
||
`gitops-starter` is the cluster name — an arbitrary label baked into the
|
||
generated certificates and config, used to tell clusters apart if you ever
|
||
manage more than one. Port 6443 is the standard Kubernetes API server port.
|
||
|
||
## 2. Point talosctl at this cluster
|
||
|
||
```sh
|
||
export TALOSCONFIG=_out/talosconfig
|
||
talosctl config endpoint <NODE1_IP> <NODE2_IP> <NODE3_IP>
|
||
```
|
||
|
||
`endpoint` is which machine(s) talosctl is willing to *talk to* — giving
|
||
it all three means it can still reach the cluster if any one of them is
|
||
down. You'll pass `--nodes` per-command below for which machine a given
|
||
command actually *applies to* — Talos always keeps those two concepts
|
||
separate.
|
||
|
||
## 3. Apply the configuration — once per node
|
||
|
||
Boot each machine from your custom Talos ISO (see
|
||
[docs/01-prerequisites.md](../docs/01-prerequisites.md)). Each boots into
|
||
"maintenance mode" — alive enough to accept a configuration, with nothing
|
||
installed yet. For **each** node in turn:
|
||
|
||
```sh
|
||
talosctl get disks --insecure --nodes <NODE_IP>
|
||
```
|
||
|
||
Confirm you see two disks: the one Talos will install itself to, and the
|
||
≥900GB one `talos/patch-longhorn.yaml`'s `UserVolumeConfig` will claim for
|
||
Longhorn. Then:
|
||
|
||
```sh
|
||
talosctl apply-config --insecure \
|
||
--nodes <NODE_IP> \
|
||
--file _out/controlplane.yaml
|
||
```
|
||
|
||
`--insecure` is required for this one command only: the node has no
|
||
certificates yet, so talosctl can't authenticate to it normally. This is
|
||
the one moment during setup where you're trusting the network — do this on
|
||
a network you control. The node will reboot, install Talos to its system
|
||
disk, format and mount its second disk for Longhorn, and come back up
|
||
running the configuration you gave it — now *with* certificates, so every
|
||
command after this uses the secure path.
|
||
|
||
Repeat this for `<NODE1_IP>`, `<NODE2_IP>`, and `<NODE3_IP>` before moving on.
|
||
|
||
## 4. Bootstrap etcd — once, total
|
||
|
||
Talos is installed on all three nodes and Kubernetes components are
|
||
starting, but the cluster has no data store yet. This one-time command
|
||
initializes it:
|
||
|
||
```sh
|
||
talosctl bootstrap --nodes <NODE1_IP>
|
||
```
|
||
|
||
Run this **exactly once**, against **exactly one** of your three nodes —
|
||
even though all three will end up running etcd as peers, only one needs
|
||
telling to *start* the cluster; the other two discover and join the
|
||
existing one. Running it again against an existing cluster can corrupt it.
|
||
|
||
## 5. Get your kubeconfig
|
||
|
||
```sh
|
||
talosctl kubeconfig --nodes <VIP_IP> .
|
||
```
|
||
|
||
Downloads a kubeconfig into the current directory (also gitignored —
|
||
it grants full cluster access), pointed at the VIP rather than any one
|
||
node. Merge it with `~/.kube/config` or point `KUBECONFIG` at it directly:
|
||
|
||
```sh
|
||
export KUBECONFIG=$PWD/kubeconfig
|
||
```
|
||
|
||
## 6. Verify
|
||
|
||
```sh
|
||
kubectl get nodes
|
||
```
|
||
|
||
Expect to see **three** nodes, `Ready`, within a couple of minutes (it
|
||
takes a moment for the default CNI — Talos ships Flannel out of the box —
|
||
to come up and clear each node's networking checks).
|
||
|
||
```
|
||
NAME STATUS ROLES AGE VERSION
|
||
talos-... Ready control-plane 90s v1.3x.x
|
||
talos-... Ready control-plane 85s v1.3x.x
|
||
talos-... Ready control-plane 80s v1.3x.x
|
||
```
|
||
|
||
If any node is stuck on `NotReady`, give it another minute before
|
||
troubleshooting — first boot does a lot of one-time work.
|