# ── Node IPs (3-CP HA topology) ─────────────────────────────────────────────── CP1_IP := 192.168.1.166 # talos-cp-1 CP2_IP := 192.168.1.213 # talos-cp-2 (storage: 3 disks) CP3_IP := 192.168.1.162 # talos-cp-3 CP_VIP := 192.168.1.166 # controlplane VIP (currently .166) # ── Paths ───────────────────────────────────────────────────────────────────── 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 KUBECONFIG := cluster-config/kubeconfig CLUSTER_NAME := homelab CP_ENDPOINT := https://$(CP_VIP):6443 # Use talosctl (not corectl). Needs TALOSCONFIG env var pointing to talosconfig file. TALOSCTL := talosctl 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: @echo "Homelab cluster (3-CP HA: .166/.213/.163) — available targets" @echo "" @echo " Status & Services" @echo " nodes kubectl get nodes" @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" @echo "" @echo " Logs" @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=)" @echo "" @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" @echo "" @echo " Reboot" @echo " reboot-all reboot all 3 CPs" @echo " reboot-cp1/2/3 reboot specific CP" @echo "" @echo " Port-forwards" @echo " pf-grafana localhost:3000 → Grafana" @echo " pf-longhorn localhost:8080 → Longhorn UI" @echo " pf-prometheus localhost:9090 → Prometheus UI" @echo "" @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" # ── Status ──────────────────────────────────────────────────────────────────── .PHONY: nodes nodes: $(KUBECTL) get nodes -o wide .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 .PHONY: status-cp status-cp: status-all .PHONY: services-cp1 services-cp1: $(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) service .PHONY: services-cp2 services-cp2: $(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) service .PHONY: services-cp3 services-cp3: $(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) service # ── Logs (3-CP) ─────────────────────────────────────────────────────────────── .PHONY: logs-cp1 logs-cp1: $(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) logs kubelet -f .PHONY: logs-cp2 logs-cp2: $(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) logs kubelet -f .PHONY: logs-cp3 logs-cp3: $(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) logs kubelet -f .PHONY: dmesg-cp1 dmesg-cp1: $(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) dmesg --follow .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: ifndef SVC $(error SVC is not set — run: make log-svc-cp1 SVC=) endif $(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) logs $(SVC) -f .PHONY: log-svc-cp2 log-svc-cp2: ifndef SVC $(error SVC is not set — run: make log-svc-cp2 SVC=) endif $(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) logs $(SVC) -f .PHONY: log-svc-cp3 log-svc-cp3: ifndef SVC $(error SVC is not set — run: make log-svc-cp3 SVC=) 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) .PHONY: apply-cp apply-cp: apply-all .PHONY: reboot-all reboot-all: reboot-cp1 reboot-cp2 reboot-cp3 @echo "✓ All 3 control planes rebooting" .PHONY: reboot-cp1 reboot-cp1: $(TALOSCTL) -n $(CP1_IP) --endpoints $(CP1_IP) reboot .PHONY: reboot-cp2 reboot-cp2: $(TALOSCTL) -n $(CP2_IP) --endpoints $(CP2_IP) reboot .PHONY: reboot-cp3 reboot-cp3: $(TALOSCTL) -n $(CP3_IP) --endpoints $(CP3_IP) reboot .PHONY: reboot-cp reboot-cp: reboot-all # 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= W_IP=) endif $(TALOSCTL) --nodes $(W_IP) reboot # ── Inspect ─────────────────────────────────────────────────────────────────── # Positional args: make node-ls 192.168.1.166 /etc/kubernetes/manifests .PHONY: node-ls node-ls: $(TALOSCTL) -n $(word 2,$(MAKECMDGOALS)) --endpoints $(word 2,$(MAKECMDGOALS)) ls $(word 3,$(MAKECMDGOALS)) .PHONY: node-read node-read: $(TALOSCTL) -n $(word 2,$(MAKECMDGOALS)) --endpoints $(word 2,$(MAKECMDGOALS)) read $(word 3,$(MAKECMDGOALS)) # Absorb positional arguments %: @: # ── 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