Reinicio controlado de un nodo con CNPG y Longhorn¶
Cómo reiniciar un nodo k3s de forma segura cuando hospeda primarios de
CloudNativePG o volúmenes de Longhorn. Es el procedimiento que kured no
puede hacer solo: un kubectl drain directo se bloquea con los PDB de los
primarios CNPG y del instance-manager de Longhorn (ver incidencia
2026-09-24-heimdall-502).
Cuándo usarlo: el sentinel
/var/run/reboot-requiredestá presente (kernel pendiente de reiniciar) y kured no consigue drenar el nodo. También como mantenimiento planificado.
Precondiciones¶
kubectlapuntando al cluster (k3s/ansible/.kubeconfig).- Plugin
kubectl-cnpginstalado (brew install kubectl-cnpg). - SSH al nodo (
ubuntu@<ip>, clave inyectada por cloud-init).
Procedimiento (nodo a nodo, en serie)¶
-
Identificar los primarios CNPG en el nodo:
kubectl get cluster -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,PRIMARY:.status.currentPrimary' kubectl get pods -A -l cnpg.io/instanceRole=primary -o wide # primarios y su columna NODE -
Switchover de cada primario que esté en el nodo hacia su réplica (en otro nodo):
kubectl cnpg promote <cluster> <instancia-replica> -n <namespace> kubectl cnpg status <cluster> -n <namespace> # esperar "Cluster in healthy state" y nuevo Primary -
Cordon (desactiva programación; CNPG y Longhorn reaccionan):
kubectl cordon <nodo> -
Drain (ahora los primarios ya no están en el nodo):
Elkubectl drain <nodo> --ignore-daemonsets --delete-emptydir-data --grace-period=60 --timeout=10m --forceinstance-managerde Longhorn puede tardar en evictarse (evacua réplicas antes); los volúmenes quedan temporalmentedegradedhasta el reboot. Verificar que termina connode/<nodo> drainedantes de seguir; si falla (error when evicting ... disruption budget), hay un primario u otro PDB sin resolver en el nodo: no rebotar. -
Reboot:
ssh ubuntu@<ip> 'sudo -n systemctl reboot' -
Esperar a que vuelva (control-plane: ~3–5 min hasta que el API server responde). Verificar que el nodo vuelve
Ready(kubectl get nodes) y el nuevo kernel / sentinel:kubectl get nodes # esperar STATUS=Ready ssh ubuntu@<ip> 'uname -r; cat /var/run/reboot-required 2>/dev/null && echo PRESENT || echo ABSENT' -
Uncordon (solo con el nodo
Ready) y verificar recuperación:kubectl uncordon <nodo> kubectl get nodes kubectl get cluster -A # "Cluster in healthy state" kubectl get pods -A | grep -vE "Running|Completed" # sin crashloops
Nota: justo tras el reboot, el API server puede devolver
http: Handler timeouty el operador de CNPG entrar enCrashLoopBackOffmientras Longhorn reconstruye réplicas (alta carga). Es transitorio; se recupera solo en unos minutos.
Por qué kured no lo hace solo¶
kured hace cordon + drain sin el switchover previo de CNPG. El PDB del
primario CNPG (<cluster>-primary, minAvailable: 1) y el PDB por nodo del
instance-manager de Longhorn bloquean la evicción → kured reintenta hasta el
drainTimeout y falla, evictando mientras tanto pods sin PDB (p. ej.
authentik-server), que es lo que provoca los 502.
La causa de fondo es que kured no añade el taint node.kubernetes.io/unschedulable
al hacer cordon (solo spec.unschedulable), y CNPG detecta el drenaje por
taint (DRAIN_TAINTS). Fix aplicado: kured lleva
blockingPodSelector: [cnpg.io/instanceRole=primary], así que se salta los
nodos con primario CNPG y solo reinicia los demás. Este runbook es el
procedimiento para reiniciar el nodo con primario cuando toque (p. ej. tras un
unattended-upgrades). Ver la incidencia referenciada arriba.