Skip to content

Commit 426d6b5

Browse files
web-flowclaude
andcommitted
feat: K3s cluster recovery tooling and documentation
Recovery tooling: - cluster_manager.py: Add rejoin_node command for fresh node recovery - cluster_manager.py: Add SSH key setup with sshpass fallback - k3s.yaml: Update to 2-node cluster config (pumped-piglet, still-fawn) - cluster.yaml: Add network interface documentation for nodes Scripts: - check-config.sh: Fix HA config check to use correct API endpoint Documentation: - Add comprehensive "Mistakes Made" section to prevent future errors - Document face recognition bootstrap requirement - Document camera IP verification workflow Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 072b982 commit 426d6b5

5 files changed

Lines changed: 616 additions & 84 deletions

File tree

docs/runbooks/k3s-cluster-recovery-2026-01.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,59 @@ face_recognition:
247247
```
248248
249249
Reference: [Frigate Face Recognition Docs](https://docs.frigate.video/configuration/face_recognition/)
250+
251+
## Mistakes Made During Recovery (Learn From These)
252+
253+
This section documents errors made during the recovery session to prevent repeating them.
254+
255+
### 1. Claimed GPU Was Working Without Verification
256+
**What happened**: Reported "still-fawn is working" after seeing node Ready status, but never verified GPU passthrough was actually configured.
257+
258+
**Result**: User had to discover Frigate had no GPU access. The passthrough job hadn't run because its SSH key secret was missing.
259+
260+
**Lesson**: "Node Ready" ≠ "Everything Works". Always verify hardware passthrough with actual device checks (`ls /dev/dri/`, `vainfo`, etc.).
261+
262+
### 2. Guessed Ollama Model Names Instead of Checking Config
263+
**What happened**: Assumed HA needed `gemma3:4b` for conversation without checking what model HA actually expected.
264+
265+
**Result**: Pulled wrong model. HA actually needed `qwen2.5:7b` for conversation (gemma3 is for llmvision image analysis).
266+
267+
**Lesson**: Never guess configuration. Always read the actual config:
268+
```bash
269+
ssh -p 22222 root@192.168.4.240 "cat /mnt/data/supervisor/homeassistant/.storage/core.config_entries" | jq '.data.entries[] | select(.domain == "ollama")'
270+
```
271+
272+
### 3. Forgot HAOS SSH Access Exists
273+
**What happened**: Repeatedly used slow `qm guest exec` method to access HAOS instead of direct SSH.
274+
275+
**Result**: Wasted time and frustrated user who had already documented SSH access.
276+
277+
**Lesson**: HAOS has SSH on port 22222:
278+
```bash
279+
ssh -p 22222 root@192.168.4.240 "command"
280+
```
281+
Check existing documentation before reinventing access methods.
282+
283+
### 4. Did Not Check for Missing SOPS Secret Before Claiming Job Would Work
284+
**What happened**: Said the GPU passthrough K8s Job would handle everything, but the job required an SSH key secret that didn't exist.
285+
286+
**Result**: Job couldn't run. Had to manually create the SOPS-encrypted secret and run passthrough commands by hand.
287+
288+
**Lesson**: Before claiming automation will work, verify all dependencies exist:
289+
```bash
290+
kubectl get secret <secret-name> -n <namespace>
291+
```
292+
293+
### 5. Assumed Face Recognition Would Auto-Populate
294+
**What happened**: Configured face_recognition in Frigate config and expected faces to appear in Train tab automatically.
295+
296+
**Result**: Train tab remained empty. Frigate requires at least one face to be manually uploaded before it starts collecting detected faces.
297+
298+
**Lesson**: Read the docs. Face recognition needs bootstrapping - upload one face first, then detections appear.
299+
300+
### 6. Did Not Update Camera IPs in Config After Network Changes
301+
**What happened**: Living room camera IP changed from 192.168.1.140 to 192.168.1.183, but initially kept checking old IP.
302+
303+
**Result**: Camera appeared offline until config was updated with correct IP.
304+
305+
**Lesson**: When cameras stop working, verify current IP first (check router DHCP leases or Reolink app), then update Frigate config.

proxmox/homelab/config/cluster.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ nodes:
2626
fqdn: still-fawn.maas
2727
role: compute
2828
enabled: true
29+
# Network configuration
30+
network:
31+
primary:
32+
interface: enp3s0
33+
bridge: vmbr0
34+
ip: 192.168.4.17/24
35+
gateway: 192.168.4.1
36+
speed: 1000 # 1 Gbps onboard NIC
37+
secondary:
38+
interface: enx803f5df89165
39+
ip: 192.168.4.18/24
40+
speed: 2500 # 2.5 Gbps USB adapter (Realtek RTL8156B)
41+
# Use for PBS restores and bulk transfers
2942
# AMD GPU passthrough for Frigate VAAPI hardware encoding
3043
gpu_passthrough:
3144
enabled: true
@@ -52,6 +65,18 @@ nodes:
5265
fqdn: pumped-piglet.maas
5366
role: compute
5467
enabled: true
68+
# Network configuration
69+
network:
70+
primary:
71+
interface: enx803f5df8d628
72+
bridge: vmbr0
73+
ip: 192.168.4.175/24
74+
gateway: 192.168.4.1
75+
speed: 2500 # 2.5 Gbps USB adapter (Realtek RTL8156B)
76+
secondary:
77+
interface: eno1
78+
# Onboard NIC - currently unused/down
79+
enabled: false
5580
# GPU passthrough for RTX 3070 to K3s VM for Ollama/AI workloads
5681
gpu_passthrough:
5782
enabled: true

proxmox/homelab/config/k3s.yaml

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,47 +36,30 @@ kube_vip:
3636

3737
# K3s control plane nodes (VMs running K3s server)
3838
# These run inside Proxmox VMs, not on bare metal
39+
# Current cluster: 2 nodes (pumped-piglet, still-fawn) after Jan 2026 recovery
3940
control_plane_nodes:
40-
- name: k3s-vm-pve
41-
# VM runs on this Proxmox host
42-
proxmox_host: pve
43-
vmid: 107
44-
ip: 192.168.4.238
45-
# Primary node used for cluster operations
46-
is_primary: true
47-
4841
- name: k3s-vm-pumped-piglet-gpu
4942
proxmox_host: pumped-piglet
5043
vmid: 105
5144
ip: 192.168.4.210
52-
is_primary: false
45+
is_primary: true
5346
# GPU passthrough for Ollama/AI workloads
5447
gpu_enabled: true
5548

56-
- name: k3s-vm-fun-bedbug
57-
proxmox_host: fun-bedbug
58-
vmid: 114
59-
ip: 192.168.4.203
60-
is_primary: false
61-
# Quorum-only node - minimal resources (1 vCPU, 4GB RAM)
62-
# AMD A9-9400 thermal limited - reduced from 2 cores due to 92°C temps
63-
role: quorum
64-
6549
- name: k3s-vm-still-fawn
6650
proxmox_host: still-fawn
6751
vmid: 108
6852
ip: 192.168.4.212
6953
is_primary: false
54+
# AMD GPU + Coral TPU for Frigate
7055

7156
# TLS-SAN entries for API server certificate
7257
# These are added to /etc/rancher/k3s/config.yaml on each control plane node
7358
tls_san:
7459
# The VIP must be in SAN for kube-vip to work
7560
- 192.168.4.79
76-
# All control plane node IPs (auto-added by K3s, but explicit is safer)
77-
- 192.168.4.238
61+
# All control plane node IPs
7862
- 192.168.4.210
79-
- 192.168.4.203
8063
- 192.168.4.212
8164
# DNS names if using DNS-based access
8265
- k3s.homelab

0 commit comments

Comments
 (0)