diff --git a/scripts/capacity-advisor b/scripts/capacity-advisor index 0877c05..2d21869 100755 --- a/scripts/capacity-advisor +++ b/scripts/capacity-advisor @@ -35,12 +35,20 @@ missing_count = int(missing_match.group(1)) if missing_match else 0 pressure = any(token in lowered for token in ["diskpressure", "memorypressure", "node pressure"]) worker_storage_warn = "worker storage" in lowered and "warn" in lowered -non_system_control_plane = False control_plane_section = text.split("## control-plane", 1)[-1] +control_plane_tainted = "node-role.kubernetes.io/control-plane" in control_plane_section and ":NoSchedule" in control_plane_section +app_control_plane_pods = [] +legacy_control_plane_pods = [] + for line in control_plane_section.splitlines(): - if re.match(r"\s*(argocd|website-production|demos-static|heimdall|security-lab|monitoring)\s+", line): - non_system_control_plane = True - break + match = re.match(r"\s*([a-z0-9-]+)\s+([^\s]+)\s+([A-Za-z]+)\s*$", line) + if not match: + continue + namespace, pod_name, status = match.groups() + if namespace == "arr-stack": + legacy_control_plane_pods.append((namespace, pod_name, status)) + elif namespace in {"argocd", "website-production", "demos-static", "heimdall", "n8n", "security-lab", "monitoring"}: + app_control_plane_pods.append((namespace, pod_name, status)) print("Jeannie Capacity Advisor") print("========================") @@ -55,7 +63,28 @@ if missing_count: "code/config: add resources to app manifests or Helm values", ) ) -if non_system_control_plane: +if legacy_control_plane_pods: + count = len(legacy_control_plane_pods) + recommendations.append( + ( + "Remove stale Kubernetes ARR workloads", + f"{count} legacy arr-stack pod(s) still exist in Kubernetes even though ARR now lives in Docker Compose on Debian.", + "kubectl delete namespace arr-stack", + "cluster cleanup: active ARR state is infra/arr-stack, not archive/apps/arr-stack", + ) + ) +if app_control_plane_pods and control_plane_tainted: + count = len(app_control_plane_pods) + namespaces = ", ".join(sorted({namespace for namespace, _, _ in app_control_plane_pods})) + recommendations.append( + ( + "Reschedule remaining app/platform pods off Debian", + f"Debian is already tainted, but {count} pod(s) still run there in: {namespaces}. Existing pods are not evicted by a NoSchedule taint.", + "./jeannie control-plane pods", + "scheduling: restart or drain selected workloads; if they return to Debian, check tolerations, node selectors, affinity, and worker readiness", + ) + ) +elif app_control_plane_pods: recommendations.append( ( "Keep app/data-plane pods off Debian",