Repair node version drift in pipeline
This commit is contained in:
parent
f1a9b1fcdb
commit
d94ae2619b
|
|
@ -159,7 +159,21 @@ jobs:
|
||||||
action_command="${HOMELAB_ACTION_COMMAND:-auto}"
|
action_command="${HOMELAB_ACTION_COMMAND:-auto}"
|
||||||
if [[ "${action_command}" == "auto" ]]; then
|
if [[ "${action_command}" == "auto" ]]; then
|
||||||
if [[ -s "${kubeconfig_probe}" ]]; then
|
if [[ -s "${kubeconfig_probe}" ]]; then
|
||||||
action_command="apps"
|
set +e
|
||||||
|
version_report="$("${deploy_dir}/lab.sh" doctor-versions 2>&1)"
|
||||||
|
version_status=$?
|
||||||
|
set -e
|
||||||
|
printf '%s\n' "${version_report}"
|
||||||
|
|
||||||
|
if ((version_status == 0)); then
|
||||||
|
action_command="apps"
|
||||||
|
elif printf '%s\n' "${version_report}" | grep -Eq 'Kubernetes kubelet minors are mixed|At least one kubelet does not match'; then
|
||||||
|
echo "Kubernetes node version drift detected; switching automatic deploy to rebuild-cluster."
|
||||||
|
action_command="rebuild-cluster"
|
||||||
|
else
|
||||||
|
echo "Version guard failed without Kubernetes minor drift; refusing automatic app deploy." >&2
|
||||||
|
exit "${version_status}"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
action_command="rebuild-cluster"
|
action_command="rebuild-cluster"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
14
README.md
14
README.md
|
|
@ -112,9 +112,11 @@ Check node versions from the Debian host:
|
||||||
|
|
||||||
The check prints the API server, kubelet versions, kubelet minors, and containerd
|
The check prints the API server, kubelet versions, kubelet minors, and containerd
|
||||||
runtimes. It exits nonzero when kubelet minors differ from the API server minor
|
runtimes. It exits nonzero when kubelet minors differ from the API server minor
|
||||||
or when containerd major versions are mixed. For Pimox workers, prefer rebuilding
|
or when containerd major versions are mixed. The Gitea Actions auto path runs
|
||||||
from the corrected golden template and rejoining the worker over ad hoc live
|
this check before app deploys; kubelet minor drift switches the job to
|
||||||
package upgrades.
|
`./lab.sh rebuild-cluster` so the Pimox template and worker VMs are replaced
|
||||||
|
from the pinned image. For Pimox workers, prefer rebuilding from the corrected
|
||||||
|
golden template and rejoining the worker over ad hoc live package upgrades.
|
||||||
|
|
||||||
## Deploying
|
## Deploying
|
||||||
|
|
||||||
|
|
@ -575,8 +577,10 @@ The workflow only blocks automatic deploy for Raspberry Pi Gitea service
|
||||||
changes: files under `infra/gitea/`, or edits inside the `deploy_gitea`,
|
changes: files under `infra/gitea/`, or edits inside the `deploy_gitea`,
|
||||||
`install_gitea_backup_timer`, `backup_gitea`, or `drill_gitea_restore`
|
`install_gitea_backup_timer`, `backup_gitea`, or `drill_gitea_restore`
|
||||||
functions in `lab.sh`. Other changes use `HOMELAB_ACTION_COMMAND=auto` by
|
functions in `lab.sh`. Other changes use `HOMELAB_ACTION_COMMAND=auto` by
|
||||||
default: Actions runs `./lab.sh apps` when the Debian runner already has a
|
default: Actions runs `./lab.sh doctor-versions` when the Debian runner already
|
||||||
cluster kubeconfig, or `./lab.sh rebuild-cluster` when it does not.
|
has a cluster kubeconfig. If node versions are aligned it runs `./lab.sh apps`;
|
||||||
|
if kubelet minor drift is detected it runs `./lab.sh rebuild-cluster`; if no
|
||||||
|
kubeconfig exists it also runs `./lab.sh rebuild-cluster`.
|
||||||
|
|
||||||
Set `HOMELAB_ACTION_COMMAND=apps` or `HOMELAB_ACTION_COMMAND=rebuild-cluster`
|
Set `HOMELAB_ACTION_COMMAND=apps` or `HOMELAB_ACTION_COMMAND=rebuild-cluster`
|
||||||
on the runner to force one path.
|
on the runner to force one path.
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ resource "null_resource" "kubeadm_control_plane" {
|
||||||
kubeconfig_owner = var.kubeconfig_owner
|
kubeconfig_owner = var.kubeconfig_owner
|
||||||
registry_endpoint = var.registry_endpoint
|
registry_endpoint = var.registry_endpoint
|
||||||
registry_config_version = "8"
|
registry_config_version = "8"
|
||||||
|
containerd_runtime = "docker-containerd-io"
|
||||||
cni_plugins_version = "2"
|
cni_plugins_version = "2"
|
||||||
node_dns_servers = join(" ", var.node_dns_servers)
|
node_dns_servers = join(" ", var.node_dns_servers)
|
||||||
persistent_volume_dirs = join(",", var.persistent_volume_dirs)
|
persistent_volume_dirs = join(",", var.persistent_volume_dirs)
|
||||||
|
|
@ -44,6 +45,31 @@ install_missing_packages() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
install_containerd_runtime() {
|
||||||
|
codename="$(. /etc/os-release && printf '%s' "$${VERSION_CODENAME:-trixie}")"
|
||||||
|
arch="$(dpkg --print-architecture)"
|
||||||
|
|
||||||
|
sudo install -d -m 0755 /etc/apt/keyrings
|
||||||
|
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<DOCKER_SOURCES
|
||||||
|
Types: deb
|
||||||
|
URIs: https://download.docker.com/linux/debian
|
||||||
|
Suites: $${codename}
|
||||||
|
Components: stable
|
||||||
|
Architectures: $${arch}
|
||||||
|
Signed-By: /etc/apt/keyrings/docker.asc
|
||||||
|
DOCKER_SOURCES
|
||||||
|
|
||||||
|
if dpkg -s containerd >/dev/null 2>&1 && ! dpkg -s containerd.io >/dev/null 2>&1; then
|
||||||
|
sudo apt-get remove -y containerd runc || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y --no-install-recommends containerd.io
|
||||||
|
sudo apt-mark hold containerd.io
|
||||||
|
}
|
||||||
|
|
||||||
configure_node_dns() {
|
configure_node_dns() {
|
||||||
dns_servers="${self.triggers.node_dns_servers}"
|
dns_servers="${self.triggers.node_dns_servers}"
|
||||||
if [ -z "$dns_servers" ]; then
|
if [ -z "$dns_servers" ]; then
|
||||||
|
|
@ -269,7 +295,8 @@ REGISTRY_EOT
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_node_dns
|
configure_node_dns
|
||||||
install_missing_packages containernetworking-plugins open-iscsi nfs-common
|
install_missing_packages ca-certificates curl gpg apt-transport-https containernetworking-plugins open-iscsi nfs-common
|
||||||
|
install_containerd_runtime
|
||||||
install_cni_plugins
|
install_cni_plugins
|
||||||
sudo systemctl enable --now iscsid
|
sudo systemctl enable --now iscsid
|
||||||
sudo systemctl enable kubelet || true
|
sudo systemctl enable kubelet || true
|
||||||
|
|
@ -364,6 +391,7 @@ resource "null_resource" "kubeadm_worker" {
|
||||||
ssh_key_path = each.value.ssh_key_path
|
ssh_key_path = each.value.ssh_key_path
|
||||||
registry_endpoint = var.registry_endpoint
|
registry_endpoint = var.registry_endpoint
|
||||||
registry_config_version = "8"
|
registry_config_version = "8"
|
||||||
|
containerd_runtime = "docker-containerd-io"
|
||||||
cni_plugins_version = "2"
|
cni_plugins_version = "2"
|
||||||
node_dns_servers = join(" ", var.node_dns_servers)
|
node_dns_servers = join(" ", var.node_dns_servers)
|
||||||
persistent_volume_dirs = join(",", var.persistent_volume_dirs)
|
persistent_volume_dirs = join(",", var.persistent_volume_dirs)
|
||||||
|
|
@ -404,6 +432,31 @@ install_missing_packages() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
install_containerd_runtime() {
|
||||||
|
codename="$(. /etc/os-release && printf '%s' "$${VERSION_CODENAME:-trixie}")"
|
||||||
|
arch="$(dpkg --print-architecture)"
|
||||||
|
|
||||||
|
sudo install -d -m 0755 /etc/apt/keyrings
|
||||||
|
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<DOCKER_SOURCES
|
||||||
|
Types: deb
|
||||||
|
URIs: https://download.docker.com/linux/debian
|
||||||
|
Suites: $${codename}
|
||||||
|
Components: stable
|
||||||
|
Architectures: $${arch}
|
||||||
|
Signed-By: /etc/apt/keyrings/docker.asc
|
||||||
|
DOCKER_SOURCES
|
||||||
|
|
||||||
|
if dpkg -s containerd >/dev/null 2>&1 && ! dpkg -s containerd.io >/dev/null 2>&1; then
|
||||||
|
sudo apt-get remove -y containerd runc || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y --no-install-recommends containerd.io
|
||||||
|
sudo apt-mark hold containerd.io
|
||||||
|
}
|
||||||
|
|
||||||
configure_node_dns() {
|
configure_node_dns() {
|
||||||
dns_servers="${self.triggers.node_dns_servers}"
|
dns_servers="${self.triggers.node_dns_servers}"
|
||||||
if [ -z "$dns_servers" ]; then
|
if [ -z "$dns_servers" ]; then
|
||||||
|
|
@ -629,7 +682,8 @@ REGISTRY_EOT
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_node_dns
|
configure_node_dns
|
||||||
install_missing_packages containernetworking-plugins open-iscsi nfs-common
|
install_missing_packages ca-certificates curl gpg apt-transport-https containernetworking-plugins open-iscsi nfs-common
|
||||||
|
install_containerd_runtime
|
||||||
install_cni_plugins
|
install_cni_plugins
|
||||||
sudo systemctl enable --now iscsid
|
sudo systemctl enable --now iscsid
|
||||||
sudo systemctl enable kubelet || true
|
sudo systemctl enable kubelet || true
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ to edit Orange Pi host networking.
|
||||||
- a preseed file for unattended Debian install
|
- a preseed file for unattended Debian install
|
||||||
- guest prep scripts that install Kubernetes tools, containerd, qemu guest agent, cloud-init, OpenEBS dependencies, cgroup prerequisites, swap disablement, and the local registry trust path
|
- guest prep scripts that install Kubernetes tools, containerd, qemu guest agent, cloud-init, OpenEBS dependencies, cgroup prerequisites, swap disablement, and the local registry trust path
|
||||||
- Kubernetes tools from the pinned minor in `TF_VAR_kubernetes_minor_version`, defaulting to `v1.36`
|
- Kubernetes tools from the pinned minor in `TF_VAR_kubernetes_minor_version`, defaulting to `v1.36`
|
||||||
|
- `containerd.io` from Docker's Debian repository so worker runtimes use the
|
||||||
|
same package source as the Debian control-plane host
|
||||||
- kernel boot options for cgroup support through `TF_VAR_kernel_cgroup_boot_options`
|
- kernel boot options for cgroup support through `TF_VAR_kernel_cgroup_boot_options`
|
||||||
- a template sealing script at `/usr/local/sbin/homelab-prepare-template.sh` inside the installed VM that verifies cgroup boot state before sealing
|
- a template sealing script at `/usr/local/sbin/homelab-prepare-template.sh` inside the installed VM that verifies cgroup boot state before sealing
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ locals {
|
||||||
"apt-transport-https",
|
"apt-transport-https",
|
||||||
"qemu-guest-agent",
|
"qemu-guest-agent",
|
||||||
"cloud-init",
|
"cloud-init",
|
||||||
"containerd",
|
|
||||||
"open-iscsi",
|
"open-iscsi",
|
||||||
"nfs-common",
|
"nfs-common",
|
||||||
"iptables",
|
"iptables",
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,31 @@ install_kubernetes_tools() {
|
||||||
apt-mark hold kubelet kubeadm kubectl
|
apt-mark hold kubelet kubeadm kubectl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
install_containerd_runtime() {
|
||||||
|
codename="$(. /etc/os-release && printf '%s' "$VERSION_CODENAME")"
|
||||||
|
arch="$(dpkg --print-architecture)"
|
||||||
|
|
||||||
|
install -d -m 0755 /etc/apt/keyrings
|
||||||
|
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
cat >/etc/apt/sources.list.d/docker.sources <<DOCKER_SOURCES
|
||||||
|
Types: deb
|
||||||
|
URIs: https://download.docker.com/linux/debian
|
||||||
|
Suites: $codename
|
||||||
|
Components: stable
|
||||||
|
Architectures: $arch
|
||||||
|
Signed-By: /etc/apt/keyrings/docker.asc
|
||||||
|
DOCKER_SOURCES
|
||||||
|
|
||||||
|
if dpkg -s containerd >/dev/null 2>&1 && ! dpkg -s containerd.io >/dev/null 2>&1; then
|
||||||
|
apt-get remove -y containerd runc || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y --no-install-recommends containerd.io
|
||||||
|
apt-mark hold containerd.io
|
||||||
|
}
|
||||||
|
|
||||||
configure_containerd() {
|
configure_containerd() {
|
||||||
mkdir -p /etc/containerd /etc/containerd/certs.d/${registry_endpoint}
|
mkdir -p /etc/containerd /etc/containerd/certs.d/${registry_endpoint}
|
||||||
containerd config default >/etc/containerd/config.toml
|
containerd config default >/etc/containerd/config.toml
|
||||||
|
|
@ -170,5 +195,6 @@ configure_dns
|
||||||
configure_kubernetes_prereqs
|
configure_kubernetes_prereqs
|
||||||
configure_kernel_boot_options
|
configure_kernel_boot_options
|
||||||
install_kubernetes_tools
|
install_kubernetes_tools
|
||||||
|
install_containerd_runtime
|
||||||
configure_containerd
|
configure_containerd
|
||||||
enable_services
|
enable_services
|
||||||
|
|
|
||||||
17
lab.sh
17
lab.sh
|
|
@ -309,7 +309,7 @@ move_prometheus_stack_workers() {
|
||||||
kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get pods -o wide
|
kubectl --kubeconfig "${KUBECONFIG_PATH}" -n "${namespace}" get pods -o wide
|
||||||
}
|
}
|
||||||
|
|
||||||
doctor_versions() {
|
doctor_versions_report() {
|
||||||
local api_version
|
local api_version
|
||||||
local api_minor
|
local api_minor
|
||||||
local containerd_major_count
|
local containerd_major_count
|
||||||
|
|
@ -332,7 +332,7 @@ doctor_versions() {
|
||||||
|
|
||||||
if [[ -z "${node_rows}" ]]; then
|
if [[ -z "${node_rows}" ]]; then
|
||||||
echo "No Kubernetes nodes found." >&2
|
echo "No Kubernetes nodes found." >&2
|
||||||
exit 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf 'API server: %s\n\n' "${api_version}"
|
printf 'API server: %s\n\n' "${api_version}"
|
||||||
|
|
@ -384,7 +384,12 @@ doctor_versions() {
|
||||||
echo "Node Kubernetes and containerd versions are aligned."
|
echo "Node Kubernetes and containerd versions are aligned."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit "${status}"
|
return "${status}"
|
||||||
|
}
|
||||||
|
|
||||||
|
doctor_versions() {
|
||||||
|
doctor_versions_report
|
||||||
|
exit "$?"
|
||||||
}
|
}
|
||||||
|
|
||||||
truthy() {
|
truthy() {
|
||||||
|
|
@ -3053,6 +3058,7 @@ up() {
|
||||||
prepare_cluster_worker_var_file true
|
prepare_cluster_worker_var_file true
|
||||||
fi
|
fi
|
||||||
run_tofu_stack "bootstrap/cluster"
|
run_tofu_stack "bootstrap/cluster"
|
||||||
|
doctor_versions_report
|
||||||
run_tofu_stack "bootstrap/platform"
|
run_tofu_stack "bootstrap/platform"
|
||||||
apps
|
apps
|
||||||
run_tofu_stack "bootstrap/edge"
|
run_tofu_stack "bootstrap/edge"
|
||||||
|
|
@ -3064,6 +3070,10 @@ rebuild_cluster() {
|
||||||
require_debian_server "rebuild-cluster"
|
require_debian_server "rebuild-cluster"
|
||||||
|
|
||||||
export WORKER_SSH_TARGETS="${WORKER_SSH_TARGETS:-}"
|
export WORKER_SSH_TARGETS="${WORKER_SSH_TARGETS:-}"
|
||||||
|
export LAB_INCLUDE_RASPBERRY_WORKER="${LAB_INCLUDE_RASPBERRY_WORKER:-true}"
|
||||||
|
export LAB_PIMOX_TEMPLATE_REPLACE_EXISTING="${LAB_PIMOX_TEMPLATE_REPLACE_EXISTING:-true}"
|
||||||
|
export LAB_PIMOX_WORKER_COUNT="${LAB_PIMOX_WORKER_COUNT:-2}"
|
||||||
|
export LAB_PIMOX_WORKER_REPLACE_EXISTING="${LAB_PIMOX_WORKER_REPLACE_EXISTING:-true}"
|
||||||
|
|
||||||
echo "Rebuilding the Kubernetes cluster without touching external Raspberry Pi Gitea..."
|
echo "Rebuilding the Kubernetes cluster without touching external Raspberry Pi Gitea..."
|
||||||
|
|
||||||
|
|
@ -3074,6 +3084,7 @@ rebuild_cluster() {
|
||||||
prepare_cluster_worker_var_file true
|
prepare_cluster_worker_var_file true
|
||||||
fi
|
fi
|
||||||
run_tofu_stack "bootstrap/cluster"
|
run_tofu_stack "bootstrap/cluster"
|
||||||
|
doctor_versions_report
|
||||||
run_tofu_stack "bootstrap/platform"
|
run_tofu_stack "bootstrap/platform"
|
||||||
apps
|
apps
|
||||||
run_tofu_stack "bootstrap/edge"
|
run_tofu_stack "bootstrap/edge"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue