2026-08-18 15:08:03 -07:00
|
|
|
# ── Node IPs (3-CP HA topology) ───────────────────────────────────────────────
|
|
|
|
|
CP1_IP := 192.168.1.166 # talos-cp-1
|
2026-08-18 15:08:04 -07:00
|
|
|
CP2_IP := 192.168.1.214 # talos-cp-2 (storage: 3 disks)
|
2026-08-18 15:08:03 -07:00
|
|
|
CP3_IP := 192.168.1.162 # talos-cp-3
|
|
|
|
|
CP_VIP := 192.168.1.166 # controlplane VIP (currently .166)
|
2026-07-11 19:16:34 -07:00
|
|
|
|
|
|
|
|
# ── Paths ─────────────────────────────────────────────────────────────────────
|
2026-08-18 15:08:03 -07:00
|
|
|
TALOSCONFIG := cluster-config/talosconfig
|
|
|
|
|
CP1_CONFIG := cluster-config/talos-cp-1.yaml
|
|
|
|
|
CP2_CONFIG := cluster-config/talos-cp-2.yaml
|
|
|
|
|
CP3_CONFIG := cluster-config/talos-cp-3.yaml
|
2026-07-11 19:16:34 -07:00
|
|
|
KUBECONFIG := cluster-config/kubeconfig
|
|
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
CLUSTER_NAME := homelab
|
|
|
|
|
CP_ENDPOINT := https://$(CP_VIP):6443
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
# Use talosctl (not corectl). Needs TALOSCONFIG env var pointing to talosconfig file.
|
|
|
|
|
TALOSCTL := talosctl
|
2026-07-11 19:16:34 -07:00
|
|
|
KUBECTL := kubectl --kubeconfig $(KUBECONFIG)
|
|
|
|
|
|
|
|
|
|
# Derive IP and config from worker number N (used by generic targets).
|
|
|
|
|
# $(W$(N)_IP) expands to e.g. $(W2_IP) when N=2.
|
|
|
|
|
W_IP = $(W$(N)_IP)
|
|
|
|
|
W_CONFIG = cluster-config/worker-$(N).yaml
|
|
|
|
|
|
|
|
|
|
.DEFAULT_GOAL := help
|
|
|
|
|
|
|
|
|
|
# ── Help ──────────────────────────────────────────────────────────────────────
|
|
|
|
|
.PHONY: help
|
|
|
|
|
help:
|
2026-08-18 15:08:04 -07:00
|
|
|
@echo "Homelab cluster (3-CP HA: .166/.214/.162) — available targets"
|
2026-07-11 19:16:34 -07:00
|
|
|
@echo ""
|
2026-08-18 15:08:03 -07:00
|
|
|
@echo " Status & Services"
|
2026-07-11 19:16:34 -07:00
|
|
|
@echo " nodes kubectl get nodes"
|
2026-08-18 15:08:03 -07:00
|
|
|
@echo " status-all etcd members on all 3 CPs"
|
|
|
|
|
@echo " status-cp1/2/3 etcd members on specific CP"
|
|
|
|
|
@echo " services-cp1/2/3 list Talos services on specific CP"
|
2026-07-11 19:16:34 -07:00
|
|
|
@echo ""
|
|
|
|
|
@echo " Logs"
|
2026-08-18 15:08:03 -07:00
|
|
|
@echo " logs-cp1/2/3 stream kubelet logs from CP{1,2,3}"
|
|
|
|
|
@echo " dmesg-cp1/2/3 stream kernel dmesg from CP{1,2,3}"
|
|
|
|
|
@echo " log-svc-cp1/2/3 stream service logs (SVC=<name>)"
|
2026-07-11 19:16:34 -07:00
|
|
|
@echo ""
|
2026-08-18 15:08:03 -07:00
|
|
|
@echo " Config Apply"
|
|
|
|
|
@echo " apply-all apply configs to all 3 CPs (talos-cp-{1,2,3}.yaml)"
|
|
|
|
|
@echo " apply-cp1/2/3 apply config to specific CP"
|
2026-07-11 19:16:34 -07:00
|
|
|
@echo ""
|
2026-08-18 15:08:03 -07:00
|
|
|
@echo " Reboot"
|
|
|
|
|
@echo " reboot-all reboot all 3 CPs"
|
|
|
|
|
@echo " reboot-cp1/2/3 reboot specific CP"
|
2026-07-11 19:16:34 -07:00
|
|
|
@echo ""
|
|
|
|
|
@echo " Port-forwards"
|
|
|
|
|
@echo " pf-grafana localhost:3000 → Grafana"
|
|
|
|
|
@echo " pf-longhorn localhost:8080 → Longhorn UI"
|
2026-08-18 15:08:03 -07:00
|
|
|
@echo " pf-prometheus localhost:9090 → Prometheus UI"
|
2026-07-11 19:16:34 -07:00
|
|
|
@echo ""
|
2026-08-18 15:08:03 -07:00
|
|
|
@echo " IPs"
|
|
|
|
|
@echo " CP1 (talos-cp-1): $(CP1_IP) — NVMe, wg0/wg1, VIP"
|
|
|
|
|
@echo " CP2 (talos-cp-2): $(CP2_IP) — 3 Longhorn disks"
|
|
|
|
|
@echo " CP3 (talos-cp-3): $(CP3_IP) — NVMe"
|
2026-07-11 19:16:34 -07:00
|
|
|
|
|
|
|
|
# ── Status ────────────────────────────────────────────────────────────────────
|
|
|
|
|
.PHONY: nodes
|
|
|
|
|
nodes:
|
|
|
|
|
$(KUBECTL) get nodes -o wide
|
|
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: status-all
|
|
|
|
|
status-all: status-cp1 status-cp2 status-cp3
|
|
|
|
|
|
|
|
|
|
.PHONY: status-cp1
|
|
|
|
|
status-cp1:
|
|
|
|
|
$(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) etcd members
|
|
|
|
|
|
|
|
|
|
.PHONY: status-cp2
|
|
|
|
|
status-cp2:
|
|
|
|
|
$(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) etcd members
|
|
|
|
|
|
|
|
|
|
.PHONY: status-cp3
|
|
|
|
|
status-cp3:
|
|
|
|
|
$(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) etcd members
|
|
|
|
|
|
2026-07-11 19:16:34 -07:00
|
|
|
.PHONY: status-cp
|
2026-08-18 15:08:03 -07:00
|
|
|
status-cp: status-all
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: services-cp1
|
|
|
|
|
services-cp1:
|
|
|
|
|
$(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) service
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: services-cp2
|
|
|
|
|
services-cp2:
|
|
|
|
|
$(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) service
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: services-cp3
|
|
|
|
|
services-cp3:
|
|
|
|
|
$(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) service
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
# ── Logs (3-CP) ───────────────────────────────────────────────────────────────
|
|
|
|
|
.PHONY: logs-cp1
|
|
|
|
|
logs-cp1:
|
|
|
|
|
$(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) logs kubelet -f
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: logs-cp2
|
|
|
|
|
logs-cp2:
|
|
|
|
|
$(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) logs kubelet -f
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: logs-cp3
|
|
|
|
|
logs-cp3:
|
|
|
|
|
$(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) logs kubelet -f
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: dmesg-cp1
|
|
|
|
|
dmesg-cp1:
|
|
|
|
|
$(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) dmesg --follow
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: dmesg-cp2
|
|
|
|
|
dmesg-cp2:
|
|
|
|
|
$(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) dmesg --follow
|
|
|
|
|
|
|
|
|
|
.PHONY: dmesg-cp3
|
|
|
|
|
dmesg-cp3:
|
|
|
|
|
$(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) dmesg --follow
|
|
|
|
|
|
|
|
|
|
# Usage: make log-svc-cp1 SVC=etcd
|
|
|
|
|
.PHONY: log-svc-cp1
|
|
|
|
|
log-svc-cp1:
|
2026-07-11 19:16:34 -07:00
|
|
|
ifndef SVC
|
2026-08-18 15:08:03 -07:00
|
|
|
$(error SVC is not set — run: make log-svc-cp1 SVC=<service-name>)
|
2026-07-11 19:16:34 -07:00
|
|
|
endif
|
2026-08-18 15:08:03 -07:00
|
|
|
$(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) logs $(SVC) -f
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: log-svc-cp2
|
|
|
|
|
log-svc-cp2:
|
2026-07-11 19:16:34 -07:00
|
|
|
ifndef SVC
|
2026-08-18 15:08:03 -07:00
|
|
|
$(error SVC is not set — run: make log-svc-cp2 SVC=<service-name>)
|
2026-07-11 19:16:34 -07:00
|
|
|
endif
|
2026-08-18 15:08:03 -07:00
|
|
|
$(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) logs $(SVC) -f
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: log-svc-cp3
|
|
|
|
|
log-svc-cp3:
|
|
|
|
|
ifndef SVC
|
|
|
|
|
$(error SVC is not set — run: make log-svc-cp3 SVC=<service-name>)
|
|
|
|
|
endif
|
|
|
|
|
$(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) logs $(SVC) -f
|
|
|
|
|
|
|
|
|
|
# ── Config Apply (3-CP) ───────────────────────────────────────────────────────
|
|
|
|
|
.PHONY: apply-all
|
|
|
|
|
apply-all: apply-cp1 apply-cp2 apply-cp3
|
|
|
|
|
@echo "✓ All 3 control planes configured"
|
|
|
|
|
|
|
|
|
|
.PHONY: apply-cp1
|
|
|
|
|
apply-cp1:
|
|
|
|
|
$(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) apply-config -f $(CP1_CONFIG)
|
|
|
|
|
|
|
|
|
|
.PHONY: apply-cp2
|
|
|
|
|
apply-cp2:
|
|
|
|
|
$(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) apply-config -f $(CP2_CONFIG)
|
|
|
|
|
|
|
|
|
|
.PHONY: apply-cp3
|
|
|
|
|
apply-cp3:
|
|
|
|
|
$(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) apply-config -f $(CP3_CONFIG)
|
2026-07-11 19:16:34 -07:00
|
|
|
|
|
|
|
|
.PHONY: apply-cp
|
2026-08-18 15:08:03 -07:00
|
|
|
apply-cp: apply-all
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: reboot-all
|
|
|
|
|
reboot-all: reboot-cp1 reboot-cp2 reboot-cp3
|
|
|
|
|
@echo "✓ All 3 control planes rebooting"
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: reboot-cp1
|
|
|
|
|
reboot-cp1:
|
|
|
|
|
$(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) reboot
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: reboot-cp2
|
|
|
|
|
reboot-cp2:
|
|
|
|
|
$(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) reboot
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
.PHONY: reboot-cp3
|
|
|
|
|
reboot-cp3:
|
|
|
|
|
$(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) reboot
|
2026-07-11 19:16:34 -07:00
|
|
|
|
|
|
|
|
.PHONY: reboot-cp
|
2026-08-18 15:08:03 -07:00
|
|
|
reboot-cp: reboot-all
|
2026-07-11 19:16:34 -07:00
|
|
|
|
|
|
|
|
# Usage: make reboot-worker N=2 W2_IP=192.168.1.162
|
|
|
|
|
.PHONY: reboot-worker
|
|
|
|
|
reboot-worker:
|
|
|
|
|
ifndef N
|
|
|
|
|
$(error N is not set — run: make reboot-worker N=<num> W<N>_IP=<ip>)
|
|
|
|
|
endif
|
|
|
|
|
$(TALOSCTL) --nodes $(W_IP) reboot
|
|
|
|
|
|
|
|
|
|
# ── Inspect ───────────────────────────────────────────────────────────────────
|
2026-08-18 15:08:03 -07:00
|
|
|
# Positional args: make node-ls 192.168.1.166 /etc/kubernetes/manifests
|
2026-07-11 19:16:34 -07:00
|
|
|
.PHONY: node-ls
|
|
|
|
|
node-ls:
|
2026-08-18 15:08:03 -07:00
|
|
|
$(TALOSCTL) -n $(word 2,$(MAKECMDGOALS)) --endpoints $(word 2,$(MAKECMDGOALS)) ls $(word 3,$(MAKECMDGOALS))
|
2026-07-11 19:16:34 -07:00
|
|
|
|
|
|
|
|
.PHONY: node-read
|
|
|
|
|
node-read:
|
2026-08-18 15:08:03 -07:00
|
|
|
$(TALOSCTL) -n $(word 2,$(MAKECMDGOALS)) --endpoints $(word 2,$(MAKECMDGOALS)) read $(word 3,$(MAKECMDGOALS))
|
2026-07-11 19:16:34 -07:00
|
|
|
|
2026-08-18 15:08:03 -07:00
|
|
|
# Absorb positional arguments
|
2026-07-11 19:16:34 -07:00
|
|
|
%:
|
|
|
|
|
@:
|
|
|
|
|
|
|
|
|
|
# ── Maintenance ───────────────────────────────────────────────────────────────
|
|
|
|
|
.PHONY: clean-pods
|
|
|
|
|
clean-pods:
|
|
|
|
|
@echo "--- removing Failed/Evicted pods ---"
|
|
|
|
|
$(KUBECTL) delete pods -A --field-selector=status.phase=Failed --ignore-not-found
|
|
|
|
|
@echo "--- force-deleting stuck Terminating pods ---"
|
|
|
|
|
@$(KUBECTL) get pods -A | awk '/Terminating/{print $$1, $$2}' | \
|
|
|
|
|
xargs -r -n2 sh -c '$(KUBECTL) delete pod -n $$0 $$1 --force --grace-period=0' || true
|
|
|
|
|
|
|
|
|
|
# ── Port-forwards ─────────────────────────────────────────────────────────────
|
|
|
|
|
.PHONY: pf-query
|
|
|
|
|
pf-grafana:
|
|
|
|
|
$(KUBECTL) port-forward -n logging svc/grafana 3000:80
|
|
|
|
|
|
|
|
|
|
.PHONY: pf-minio
|
|
|
|
|
pf-minio:
|
|
|
|
|
$(KUBECTL) port-forward -n storage svc/minio 9001:9001 &
|
|
|
|
|
$(KUBECTL) port-forward -n storage svc/minio 9000:9000 &
|
|
|
|
|
|
|
|
|
|
.PHONY: pf-loki
|
|
|
|
|
pf-loki:
|
|
|
|
|
$(KUBECTL) port-forward -n logging svc/loki 3100:3100
|
|
|
|
|
|
|
|
|
|
.PHONY: pf-iam
|
|
|
|
|
pf-iam:
|
|
|
|
|
$(KUBECTL) port-forward -n iam svc/authentik-server 7000:80
|
|
|
|
|
|
|
|
|
|
.PHONY: pf-portainer
|
|
|
|
|
pf-portainer:
|
|
|
|
|
$(KUBECTL) port-forward -n dashboard svc/portainer 9000:9000
|
|
|
|
|
|
|
|
|
|
.PHONY: pf-prometheus
|
|
|
|
|
pf-prometheus:
|
|
|
|
|
$(KUBECTL) port-forward -n monitoring svc/prometheus-kube-prometheus-prometheus 9090:9090
|
|
|
|
|
|
|
|
|
|
.PHONY: pf-longhorn
|
|
|
|
|
pf-longhorn:
|
|
|
|
|
$(KUBECTL) port-forward -n longhorn-system svc/longhorn-frontend 8080:80
|
|
|
|
|
|
|
|
|
|
# ── CLI ───────────────────────────────────────────────────────────────────────
|
|
|
|
|
.PHONY: cli
|
|
|
|
|
cli:
|
|
|
|
|
$(MAKE) -C core-cli install
|