Saltar a contenido

Kured

Daemon de reinicio de Kubernetes (Kubernetes Reboot Daemon): reinicia los nodos de forma segura cuando el SO lo pide tras instalar parches de seguridad.

Resumen

Kured corre como DaemonSet en los 3 nodos y vigila el sentinel /var/run/reboot-required (generado por unattended-upgrades). Cuando lo detecta dentro de la ventana configurada, hace cordon + drain del nodo, lo reinicia y lo vuelve a uncordon. Un lock en la API serializa los reinicios: nunca se reinician dos nodos a la vez.

Estado

Campo Valor
Estado Operativo
Argo CD Application kured
Namespace kured

Despliegue

Campo Valor
Método Helm chart
Chart / imagen kured@6.1.0 (appVersion 1.23.0)
Origen https://kubereboot.github.io/charts
Config en el repo clusters/luka/apps/kured/application.yaml

Red

Campo Valor
Service — (DaemonSet, no expone nada)
IP —
Puertos —
URL interna —
URL externa —
TLS —

Acceso y usuarios

  • No tiene usuarios ni interfaz. Logs vía kubectl -n kured logs.

Configuración

  • Ventana de reinicio: startTime: 06:00, endTime: 08:00, timeZone: Europe/Madrid (hora local).
  • Comprobación del sentinel: cada 10m (period), acortado para que los 3 nodos puedan reiniciarse serialmente dentro de la ventana de 2 h.
  • Sentinel: /var/run/reboot-required (hostPath montado en /sentinel).
  • Taint previo al drenado: weave.works/kured-node-reboot (PreferNoSchedule) para que Longhorn deje de programar réplicas en el nodo.
  • Lock: sin TTL (serialización estricta; nunca dos nodos a la vez). Si un nodo se queda colgado, el lock weave.works/kured-node-lock se limpia a mano (se ignora en Argo CD para que el selfHeal no lo borre).
  • Drenado: drainGracePeriod: 60, drainTimeout: 10m; forceReboot: false (si el drenado falla, no fuerza el reinicio).
  • Bloqueo por pods: blockingPodSelector: [cnpg.io/instanceRole=primary] — kured no reinicia un nodo que aloje un primario CNPG (el drenaje fallaría por el PDB, ver Notas). Esos nodos se reinician a mano.
  • Disparador (SO): unattended-upgrades instala parches de noble-security y deja el sentinel; Automatic-Reboot: false (el reinicio lo hace Kured). Ver rol Ansible k3s/ansible/roles/unattended-upgrades/.

Almacenamiento

  • — (sin PVC; solo monta el directorio del sentinel en modo read-only).

Dependencias

  • Depende de: unattended-upgrades en el SO (genera el sentinel).
  • Usado por: nadie (servicio de plataforma).

Backup y recuperación

  • — (re-desplegable desde Git; sin estado).

Monitorización

  • Expone la métrica kured_reboot_required{node=...} en :8080/metrics (1 = hay reinicio pendiente).
  • Scrapeado vía PodMonitor kured (clusters/luka/config/servicemonitors/kured.yaml).

Referencias

Notas / TODO

  • ⚠️ Incidencia (sep 2026) — resuelta: failed to create fsnotify watcher: too many open files (EMFILE). El default fs.inotify.max_user_instances=128 se agota (kawhi 143 en uso, kobe 134, kyrie 93) y inotify_init() falla → kured no puede vigilar /var/run/reboot-required. Fix: fs.inotify.max_user_instances=512 y max_user_watches=524288 vía /etc/sysctl.d/90-homelab-inotify.conf (role longhorn-prereqs; valores adoptados tras la incidencia — RKE2 recomienda 8192, aquí 512 es suficiente para el volumen del homelab). Ya aplicado en los 3 nodos y verificado.
  • Notificaciones (Slack/Telegram) pendientes; se añadirán con la observabilidad.
  • Validado (sep 2026): test completo de los 3 nodos — cordon→drain→reboot→ uncordon automático, en serie (lock), sin degradar Longhorn ni CNPG. drainGracePeriod: 60 y drainTimeout: 10m funcionan.
  • Requisito de capacity: el control-plane (kobe) necesita 8 GB. Con 4 GB, al drenar un worker, el churn de pods reasignados + la reconstrucción de réplicas Longhorn saturaba kobe (load 40, memoria agotada) y colgaba el API.
  • Para tests manuales fuera de la ventana: ensanchar startTime/endTime a mano y suspender el autosync de Argo CD (el selfHeal revierte el cambio de ventana en ~1 min).
  • Primarios CNPG no se reinician solos: kured no añade el taint node.kubernetes.io/unschedulable al hacer cordon (solo spec.unschedulable), por lo que CNPG no detecta el drenaje y no hace switchover → su PDB (<cluster>-primary, minAvailable:1) bloquea el drain, y kured evicta mientras tanto pods sin PDB (p. ej. authentik-server) → 502. Fix: blockingPodSelector: [cnpg.io/instanceRole=primary] — kured se salta los nodos con primario CNPG; esos nodos se reinician a mano con switchover previo (docs/runbooks/reboot-nodo-cnpg.md). Ver incidencia 2026-09-24-heimdall-502.