Seleccione su idioma

Después de un corte eléctrico, varios clústeres de OpenShift volvieron a arrancar. Los nodos estaban encendidos, pero parte de la plataforma no conseguía levantar. Lo más desconcertante: algunas imágenes figuraban en el inventario local y, sin embargo, el runtime aseguraba que no existían.

Hay incidencias que empiezan con un síntoma y terminan enseñándote que el problema estaba dos capas más abajo. Esta fue una de ellas.

Al restablecerse la alimentación tras un apagón, varios clústeres tuvieron que recuperarse prácticamente al mismo tiempo. Una parte de los nodos volvió a estar disponible, pero los pods esenciales no arrancaban. A primera vista parecía un desastre de red. En realidad, el rastro más útil estaba en el almacenamiento local de imágenes de los nodos.

¿Buscas los comandos de recuperación? He reunido el diagnóstico, la reparación del almacenamiento de CRI-O y las comprobaciones posteriores en la guía técnica paso a paso.

El síntoma: un clúster que arrancaba a medias

Encontramos pods bloqueados en ContainerCreating y otros en ImagePullBackOff, CreateContainerError o CrashLoopBackOff. Algunos componentes de red no lograban iniciar y, sin ellos, el resto de la plataforma empezó a fallar en cascada.

Los mensajes de Multus hablaban de esperas agotadas al configurar la red del pod. OVN-Kubernetes no estaba funcionando con normalidad. La creación de sandboxes fallaba. El plano de control y los servicios expuestos parecían sufrir problemas de conectividad, aunque los síntomas no encajaban del todo con una avería convencional de red.

Esto es importante: cuando el CNI no está disponible, un fallo al crear un pod puede parecer un problema de red incluso si la causa original impide que arranque el propio componente de red.

La pista: «image not known»

Al revisar kubelet y CRI-O apareció una familia de errores mucho más precisa:

image not known
could not stat ... overlay/.../diff: no such file or directory

El inventario que mostraba crictl images incluía algunas imágenes que el runtime luego no podía utilizar. En comprobaciones adicionales, crictl inspecti y podman image inspect no siempre daban una imagen coherente del estado local. Esa diferencia, por sí sola, no demuestra corrupción —las herramientas pueden consultar contextos de almacenamiento distintos—, pero junto con los errores de CRI-O y las capas ausentes señaló claramente dónde investigar.

La distinción decisiva fue entre un registro de imágenes y el almacén de imágenes del nodo. Un registry publica y distribuye imágenes. CRI-O, mediante containers/storage, necesita mantener sus propias referencias, metadatos y capas para crear contenedores. Una imagen puede haber existido y conservar entradas en un catálogo, pero no ser utilizable si faltan datos a los que esas entradas apuntan.

Las comprobaciones de integridad de CRI-O encontraron numerosas inconsistencias en imágenes, capas y contenedores en al menos uno de los nodos afectados. Era una evidencia mucho más concreta que la primera impresión de «el registry está roto».

El efecto dominó

La secuencia que observamos fue aproximadamente esta:

  1. Los nodos arrancaron después de una interrupción no ordenada.
  2. Parte de su almacenamiento local de imágenes presentaba referencias o capas inconsistentes.
  3. CRI-O no podía crear determinados contenedores, incluidos componentes necesarios para la red.
  4. Sin esos componentes, fallaba la creación de nuevos sandboxes y se acumulaban errores de pods y operadores.
  5. El plano de control, la entrada de tráfico y distintas aplicaciones parecían afectados simultáneamente.

Además, muchos nodos intentaban recuperar imágenes a la vez. Vimos descargas lentas, tiempos de espera TLS y límites de peticiones al descargar imágenes. Eso prolongó la recuperación y añadió ruido a los registros, pero no explicaba los errores iniciales de capas locales.

Cómo recuperamos los nodos

No hubo una orden mágica que sirviera para todos. La recuperación fue gradual y orientada por la evidencia de cada nodo.

  1. Separar los síntomas. Revisamos el estado de nodos, pods y operadores, junto con los registros de kubelet y CRI-O. Era necesario distinguir el fallo de creación de contenedores de sus consecuencias en la red.
  2. Contrastar las imágenes. Utilizamos crictl images, crictl inspecti y comprobaciones con Podman, además de los mensajes de error asociados a las capas ausentes.
  3. Verificar la integridad. En los nodos que lo requerían, crio check permitió comprobar el almacenamiento. En uno de ellos fue necesario ejecutar una reparación controlada con crio check --repair --force; la comprobación posterior terminó sin errores.
  4. Recuperar imágenes concretas. Cuando una imagen requerida no era utilizable, la volvimos a descargar con crictl pull, identificándola por el digest previsto. Así evitamos depender de una etiqueta que pudiera señalar otra versión.
  5. Reincorporar progresivamente. Tras comprobar el runtime, los componentes de red y los pods esenciales, fuimos devolviendo los nodos a servicio y verificando el estado de los operadores.

Precaución: crio check --repair --force modifica el almacenamiento y no debe ejecutarse indiscriminadamente con cargas en funcionamiento. Antes de una reparación hay que consultar la documentación de la versión instalada y preparar una ventana de mantenimiento adecuada; detener CRI-O cuando corresponda puede afectar a los contenedores del nodo. En nodos de control, el procedimiento exige especial cuidado para mantener el quórum y la disponibilidad.

No fue necesario borrar por completo el almacén de contenedores, aplicar una limpieza masiva ni reinstalar los clústeres. La reparación selectiva y la recuperación de imágenes fueron suficientes para superar el problema principal.

Las comprobaciones que cerraron la incidencia

Una imagen descargada correctamente no equivale a un nodo recuperado. Validamos que los componentes de red volvían a ejecutar sus contenedores, que podían crearse sandboxes, que los servicios del plano de control respondían y que los operadores y las aplicaciones regresaban a estados saludables.

Durante la recuperación aparecieron también problemas secundarios, incluidos errores temporales de TLS y condiciones de operadores que no tenían la misma causa. No los usamos como prueba de que el apagón hubiera corrompido todos los subsistemas: cada síntoma necesitaba su propia comprobación.

Lo que me llevo de aquella noche

  • La red puede ser la víctima, no el origen. Si el runtime no puede arrancar el CNI, los errores de red serán generalizados.
  • El inventario no garantiza integridad. Una referencia de imagen visible no asegura que sus capas puedan utilizarse.
  • Un apagón afecta a las dependencias, no solo a los servicios. Recuperar primero los componentes fundamentales reduce mucho el ruido posterior.
  • Reparar con precisión es mejor que arrasar. Antes de borrar el almacenamiento hay que disponer de evidencias, conocer el alcance y preservar lo recuperable.
  • La recuperación simultánea también consume capacidad externa. Conviene prever disponibilidad de imágenes y evitar una avalancha de descargas en frío.

No pudimos demostrar qué operación concreta dejó inconsistentes las referencias persistidas durante el apagón. Sí pudimos determinar dónde estaba el fallo operativo y restablecer la plataforma sin reconstruirla desde cero. Y esa diferencia entre síntoma, evidencia y causa probable es quizá la lección más útil.

Referencias