Actualizar el clúster deja de ser un acontecimiento cuando lo haces cada mes

El calendario de soporte fija tu programación lo planifiques o no. Las APIs obsoletas, los drenajes bloqueados y los complementos que van por detrás del plano de control son las tres cosas que convierten una actualización en un incidente.

Hay dos culturas de actualización. En la primera, el clúster se actualiza cada pocas semanas, nadie lo menciona y el registro de cambios es una línea en un pull request. En la segunda, el clúster va cuatro versiones por detrás, la actualización es un proyecto con nombre propio y ventana de mantenimiento, tres personas están nerviosas y se pospone otra vez porque hay un lanzamiento el mes que viene.

La segunda cultura no es más prudente. Es la consecuencia del primer aplazamiento, y el riesgo se acumula. Kubernetes publica unas tres veces al año con alrededor de catorce meses de soporte de parches por versión menor, y los proveedores gestionados superponen sus propias ventanas, con soporte ampliado disponible a cambio de dinero y, al final, una actualización forzada. Quedarse atrás significa que acabas actualizando según el calendario del proveedor, durante lo que sea que esté pasando esa semana.

Por qué ir atrasado sale más caro que ir al día

Saltarse versiones no está soportado en el plano de control: actualizas de una en una versión menor, así que ir cuatro por detrás son cuatro actualizaciones seguidas, cada una con su validación.

Cada versión trae además sus propias obsolescencias, y cuanto más recorrido haces en un solo proyecto más te encuentras a la vez. Una actualización de una versión suele tener una lista corta de cambios sobre la que puedes razonar. Una de cuatro versiones es una tarea de investigación.

Mientras tanto el entorno sigue moviéndose. Se escriben manifiestos nuevos contra la API vieja, se acumulan más complementos, y la distancia entre tu versión y la que supone tu herramienta crece. Las tarifas de soporte ampliado son el coste visible y la parte más pequeña.

Encuentra las APIs obsoletas antes de que las encuentre la actualización

Es el paso de preparación con más valor, y es mecánico.

Las versiones de API eliminadas son la rotura clásica: un manifiesto que se aplica bien hoy falla después de actualizar porque la versión que nombra ya no existe. Las cargas que ya están corriendo no se ven afectadas hasta que algo las vuelve a aplicar, y por eso el fallo suele aparecer días después en un pipeline y no durante la ventana de actualización.

Mira en tres sitios, porque guardan cosas distintas:

  • Los objetos vivos del clúster, a través de las métricas de obsolescencia que expone el servidor de API y de su registro de auditoría, que juntos te dicen qué se sigue pidiendo y quién lo pide.
  • Tus manifiestos y charts en git, incluidos los de entornos que despliegas poco.
  • Charts y operadores de terceros, que son la fuente más común de sorpresas.

Las herramientas que comparan tus manifiestos con una versión objetivo cazan casi todo en una sola ejecución. Haz esta comprobación en integración continua contra la siguiente versión, de forma permanente, para que la lista nunca sea una sorpresa.

Lee además las notas de versión del propio proveedor, no solo las del proyecto. Los proveedores gestionados cambian valores por defecto, contenidos de la imagen de nodo y versiones de complementos de formas que las notas del proyecto no mencionan.

El drenaje es donde las actualizaciones se atascan de verdad

Actualizar el plano de control suele ser tranquilo. Reemplazar los nodos es donde se para.

Drenar un nodo desaloja pods y espera. Espera para siempre si no se puede satisfacer un presupuesto de interrupción de pods, y los presupuestos mal configurados son extremadamente comunes:

  • Un presupuesto cuyo mínimo disponible es igual al número de réplicas, que no permite ninguna interrupción y bloquea el drenaje de forma permanente.
  • Un presupuesto sobre un despliegue de una sola réplica, que es una contradicción que la API acepta.
  • Un StatefulSet donde el desalojo se bloquea por un volumen que no puede desasociarse porque el pod no ha terminado limpiamente.

Y luego están los pods que nada va a desalojar: pods sueltos sin controlador, que no se vuelven a crear nunca, y trabajos de larga duración que el drenaje esperará educadamente. Los dos necesitan una decisión antes de la actualización, no durante.

Pon un tiempo de espera al drenaje y ten claro qué harás cuando se alcance. Prueba el drenaje en un nodo de producción en horario laboral, bastante antes de la actualización, porque esa única prueba encuentra casi todo esto.

Diferencia de versiones, complementos y orden de operaciones

El plano de control va primero. Los nodos van después y pueden ir más antiguos que el plano de control dentro de la ventana de diferencia soportada, nunca más nuevos. Tu cliente de línea de comandos y tu herramienta de integración continua tienen su propio rango soportado, y un pipeline con un cliente dos versiones por detrás fallará de formas que parecen problemas del clúster.

Los complementos son la parte que los equipos olvidan, y la parte que se rompe. El complemento de red, los controladores de almacenamiento, el controlador de entrada o de pasarela, la gestión de certificados, la de DNS externo, el servidor de métricas, el autoescalador, la malla de servicios, los webhooks de admisión y cualquier operador tienen cada uno su matriz de compatibilidad. Algunos hay que actualizarlos antes que el plano de control, otros después.

Escribe la matriz una vez, como una tabla de componente contra versiones soportadas de Kubernetes, y guárdala en el repositorio junto a la definición del clúster. Convierte un ejercicio de investigación en una lista de comprobación.

Los webhooks de admisión merecen una precaución especial. Un webhook que falla cerrado y es incompatible con la versión nueva bloquea todos los despliegues del clúster, incluido el despliegue que lo arreglaría. Revisa la política de fallo y la caducidad del certificado de todos los webhooks antes de empezar.

Los grupos de nodos azul y verde ganan al reemplazo en el sitio

Para el plano de datos, el patrón que minimiza el riesgo no es un reemplazo progresivo en el sitio. Es crear un grupo de nodos nuevo con la versión nueva junto al antiguo, acordonar el antiguo, drenarlo poco a poco y mirar.

La ventaja es que revertir es trivial. Si las cargas se portan mal con la imagen de nodo nueva, desacordonas el grupo antiguo y drenas de vuelta. Con el reemplazo en el sitio, los nodos antiguos ya no están y revertir significa otro ciclo completo.

Te cuesta el precio de ejecutar los dos grupos unas horas, que es un precio pequeño por tener salida. Mueve primero una carga no crítica y déjala reposar, en vez de drenarlo todo en secuencia al primer intento.

El ritmo que vuelve esto aburrido

Actualiza los clústeres de no producción de forma programada y automática, y deja que corran la versión nueva una semana o dos antes de que le toque a producción. Ese desfase caza problemas reales sin nada en juego.

Después actualiza producción cada mes o al menos cada trimestre, en horario laboral, como trabajo normal y no como un acontecimiento. No tiene que hacerlo siempre la misma persona; para eso está escrita la lista de comprobación.

Dos hábitos de apoyo hacen que esto aguante. Mantén la definición del clúster en código para que subir de versión sea una diferencia revisable, con los patrones de estado y pipeline de Terraform en AWS. Y trata la actualización como un cambio más, con la misma validación y la misma expectativa de reversión, que es exactamente el encuadre de llevar AKS a producción y OKE en producción.

Lo que se olvida

  • Copias de etcd antes de actualizar el plano de control. Los proveedores gestionados las hacen, pero verifícalo y conoce el camino de restauración.
  • Los cambios de imagen de nodo traen cambios de núcleo y de tiempo de ejecución. Una carga que depende de una función concreta del núcleo o de un comportamiento antiguo del tiempo de ejecución puede romperse sin que intervenga ninguna API de Kubernetes.
  • Los recursos personalizados de alcance de clúster son compartidos. Actualizar un controlador puede cambiar definiciones de las que depende otro, lo que es agudo en un clúster compartido.
  • Cuota para el grupo de nodos nuevo. Una actualización azul y verde necesita margen, y topar con una cuota de instancias a mitad de actualización es un mal momento para descubrirlo.
  • Puertas de funcionalidad y APIs en beta. Todo lo que activaste estando en beta puede promocionarse con cambios, o eliminarse.

Qué hacer esta semana

Ejecuta una comprobación de APIs obsoletas contra la siguiente versión menor, sobre tu clúster de producción y sobre tus manifiestos en git. Lleva diez minutos y produce una lista concreta. Si esa lista está vacía, programa la actualización para un martes por la mañana y deja de tratarla como un proyecto. Metemos esta comprobación en el pipeline durante la fase de plataforma de un proyecto cloud.

ConsultorIA

¿Quieres esto en tu nube?

El diagnóstico de diez días en solo lectura es gratuito, y con Skyline puedes ver tu entorno en un mapa antes de escribirnos.

Artículos relacionados

Módulos que la gente reutiliza en vez de copiar

Los dos fracasos son un módulo que envuelve un recurso y no aporta nada, y un módulo que lo hace todo y que nadie se atreve a cambiar. Una interfaz mínima, valores por defecto seguros y un versionado honesto son lo que los separa.