diff --git a/README.md b/README.md index bb8208d..0db3974 100644 --- a/README.md +++ b/README.md @@ -237,6 +237,11 @@ running the full pipeline: ./jeannie fix-debian-docker-root ``` +When `./jeannie up` sees an existing tracked kubeadm control plane but +the Kubernetes API is down, it starts the saved runtime before applying cluster +changes. Use `./jeannie rebuild-cluster` only when you intentionally +want to destroy and recreate the cluster. + ## Validation Useful checks after a rebuild: diff --git a/README.md.tmpl b/README.md.tmpl index 68d89b6..9e1c92a 100644 --- a/README.md.tmpl +++ b/README.md.tmpl @@ -237,6 +237,11 @@ running the full pipeline: ./{{ main_script }} fix-debian-docker-root ``` +When `./{{ main_script }} up` sees an existing tracked kubeadm control plane but +the Kubernetes API is down, it starts the saved runtime before applying cluster +changes. Use `./{{ main_script }} rebuild-cluster` only when you intentionally +want to destroy and recreate the cluster. + ## Validation Useful checks after a rebuild: diff --git a/jeannie b/jeannie index 26ce046..3b4949b 100755 --- a/jeannie +++ b/jeannie @@ -3789,6 +3789,7 @@ up() { if [[ -z "${LAB_CLUSTER_VAR_FILE:-}" ]]; then prepare_cluster_worker_var_file true fi + ensure_existing_cluster_started_for_up run_tofu_stack "bootstrap/cluster" doctor_versions_report run_tofu_stack "bootstrap/platform" @@ -4006,6 +4007,45 @@ start_cluster() { echo "Kubernetes runtime start requested. Use 'kubectl get nodes -o wide' to watch readiness." } +kubernetes_api_reachable() { + kubectl --kubeconfig "${KUBECONFIG_PATH}" get --raw=/readyz >/dev/null 2>&1 +} + +cluster_control_plane_tracked() { + tofu_state_has_resource "bootstrap/cluster" "null_resource.kubeadm_control_plane" +} + +wait_for_kubernetes_api() { + local timeout_seconds="${1:-180}" + local elapsed=0 + + until kubernetes_api_reachable; do + if ((elapsed >= timeout_seconds)); then + echo "Kubernetes API did not become reachable after ${timeout_seconds}s." >&2 + return 1 + fi + sleep 5 + elapsed=$((elapsed + 5)) + done +} + +ensure_existing_cluster_started_for_up() { + if ! cluster_control_plane_tracked; then + echo "No tracked kubeadm control plane found; bootstrap/cluster will create one." + return 0 + fi + + if kubernetes_api_reachable; then + echo "Existing Kubernetes control plane is reachable." + return 0 + fi + + echo "Existing Kubernetes control plane is tracked but API is down; starting cluster runtime..." + start_cluster + wait_for_kubernetes_api "${LAB_CLUSTER_START_WAIT_SECONDS:-180}" + echo "Existing Kubernetes control plane is reachable after start." +} + status_section() { printf '\n== %s ==\n' "$1" }