Mr.PlanB Logo
    Volver al blog
    Ceph
    Almacenamiento
    API
    Recuperación ante desastres
    Proxmox
    Debugging

    Cómo una mala llamada API tumbó un clúster Ceph entero

    9 de noviembre de 2025
    10 min de lectura

    Todo empezó con un único comando, una simple petición curl pensada para obtener unas pocas estadísticas inofensivas. En lugar de eso, puso de rodillas a un clúster Ceph entero.

    El administrador de un homelab, probando la API RESTful de Ceph, envió lo que debió ser una llamada rutinaria:

    curl -k -X POST "https://USERNAME:API_KEY@HOSTNAME:PORT/request?wait=1" -d '{"prefix": "df", "detail": 1}'
    

    Esa línea no parece peligrosa. Es el tipo de comando que cualquiera que gestione Ceph ha usado o probado alguna vez: un vistazo rápido a las estadísticas de los pools, algo que normalmente obtendrías con ceph df detail. Esta vez, sin embargo, ese pequeño parámetro, "detail": 1, provocó algo mucho peor que un simple error de sintaxis. En cuestión de segundos, los servicios de monitorización (ceph-mon) cayeron en todo el clúster.

    Cada VM conectada al sistema se congeló. El panel de Proxmox se tiñó de rojo, los demonios de almacenamiento dejaron de responder y el clúster central de una infraestructura autoalojada quedó completamente muerto, todo por una única petición API malformada.

    El día en que murieron los monitores

    Al principio parecía un tropiezo menor. El administrador, conocido como packetsar, vio que los monitores de Ceph arrojaban errores. En lugar de recuperarse, cayeron y no paraban de reiniciarse en bucle. Los registros se llenaron con un mensaje inquietantemente específico:

    ceph-mon[278661]: terminate called after throwing an instance of 'ceph::common::bad_cmd_get'
    ceph-mon[278661]: what():  bad or missing field 'detail'
    

    Cualquiera que haya lidiado con Ceph sabe que cuando fallan los monitores (MON), tienes un problema grave. Los MON mantienen el mapa del clúster: saben qué OSD guardan qué datos, dónde residen los pools y quiénes forman el quórum. Cuando caen, el clúster pierde prácticamente la memoria.

    Y esto fue mucho más allá de la caída de un único nodo. El problema se propagó en cascada por todos los monitores. Cada uno leyó la petición envenenada desde una base de datos compartida y cayó por el mismo precipicio. Cada intento de reinicio no hizo más que repetir el fallo.

    "Reinicios de servidor, reinicios de servicio, nada funcionaba", escribió packetsar. "El clúster de Ceph y Proxmox está totalmente caído y las VM se han detenido en este punto".

    La píldora venenosa autoinfligida

    Lo más extraño es que el comando no debió ser tan dañino. La API de Ceph debería validar la entrada y gestionar con elegancia el JSON malformado o los campos desconocidos. En su lugar, el parámetro "detail": 1 se interpretó de una forma que provocó una excepción fatal dentro del proceso ceph-mon.

    Básicamente, Ceph ingirió la petición errónea, se atragantó con ella y la guardó, reproduciendo el mismo comando no válido cada vez que los monitores intentaban arrancar. Fue un bucle de caídas continuo: el clúster recordaba el comando erróneo y volvía a consumirlo una y otra vez.

    "Parece que esa petición se guardó en una base de datos ceph-mon compartida e hizo caer a todos los servicios de monitorización", escribió el admin.

    Así, un comando defectuoso se convirtió en corrupción persistente. El estado envenenado vivía dentro del almacén del monitor, lo que significaba que ni siquiera un reinicio limpio lograba eliminarlo.

    Un comentario lo resumió a la perfección:

    "¿Otro ejemplo más de mala validación de entradas? No olvides registrar esto como bug en Ceph".

    La lección es simple y contundente: cuando construyes sistemas distribuidos, validar las entradas no es opcional, porque un solo campo sin comprobar puede derribarlo todo.

    "Puedes envenenar todo el clúster con una sola llamada REST"

    Así lo describió packetsar más adelante en el hilo. Suena exagerado hasta que recuerdas la arquitectura de Ceph.

    Ceph se fundamenta en el consenso. Los monitores replican datos para mantener el quórum, y cuando uno recibe un estado defectuoso, lo propaga a los demás asumiendo que es válido. Por tanto, si un comando malformado llega a la base de datos de los monitores, se copia fielmente en todos los nodos. El sistema confía en sus pares, lo que constituye su gran fortaleza y, en este caso, su mayor debilidad.

    Cuando alguien preguntó si el mismo comando funcionaba bien mediante la CLI, el admin confirmó que ceph df detail se ejecutaba perfectamente desde la línea de comandos. Fue la capa de la API REST la que no validó correctamente los datos. Esa distinción importa porque sitúa el problema en el envoltorio de la API de Ceph y no en su lógica central, y ese wrapper es una capa pensada para que la automatización sea más segura y sencilla. Aquí se convirtió en un punto único de fallo.

    Reconstruir desde las cenizas

    Una vez asimilada la gravedad del desastre, packetsar tuvo que averiguar cómo resucitar un clúster Ceph muerto cuando los monitores ni siquiera arrancaban.

    No existe un botón mágico para deshacer cambios en la base de datos de los monitores de Ceph, así que packetsar tuvo que recurrir al método tradicional y reconstruirla manualmente a partir de los OSD (Object Storage Daemons). Es un procedimiento descrito en lo más profundo de la documentación de Ceph, reservado habitualmente para escenarios de corrupción extrema.

    Este es el proceso de recuperación, simplificado:

    1. Apagar todos los OSD en cada host para detener escrituras adicionales.
    2. Elegir un host para empezar y reconstruir una base de datos de monitorización nueva usando los datos de sus OSD locales.
    3. Sincronizar mediante rsync ese nuevo store.db con los demás hosts, uno por uno, reconstruyendo y combinando sobre la marcha.
    4. Cuando la base de datos esté completa, reemplazar el archivo store.db de producción en todos los monitores con el nuevo.
    5. Levantar los MON de nuevo y dejar que alcancen el quórum.
    6. Finalmente, reconstruir los demonios gestores (mgr) uno a uno y volver a configurar ajustes como el módulo de la API REST.

    No es algo que se haga a la ligera. Es un trabajo lento y tenso, sobre todo cuando tu clúster de almacenamiento sostiene toda tu infraestructura de virtualización. Pero funcionó.

    "Pude volver a poner las VM en línea aproximadamente 1 hora después de empezar a trabajar con calma en el proceso de reconstrucción", escribió.

    Es una capacidad de recuperación notable, y demuestra hasta qué punto se pueden entender y reparar los sistemas de código abierto cuando tienes control total y paciencia.

    Lecciones del desastre

    Nadie debería interpretar esto como una invitación a dejar de experimentar con su clúster, ya que trastear es la mejor forma de aprender. Pero los sistemas distribuidos, especialmente soluciones como Ceph, exigen un respeto particular.

    De este tropiezo se desprenden varias conclusiones clave.

    1. Las API no siempre son más seguras

    Tendemos a pensar que las API eliminan riesgos y que usar llamadas estructuradas en lugar de comandos directos hace que la automatización sea más segura. Este incidente demuestra que puede ocurrir lo contrario si la API no valida las entradas como es debido. Una entrada incorrecta a través de una API jamás debería derribar el servicio que expone. Eso es desarrollo básico 101.

    2. La persistencia es un arma de doble filo

    El diseño de Ceph le otorga una gran resiliencia, manteniendo la coherencia de los datos entre nodos incluso ante caídas. Esa misma persistencia lo vuelve implacable. Si almacena un estado erróneo, ese mal estado se convierte en verdad absoluta hasta que se purga a mano.

    3. Probar en producción no es probar

    Resulta tentador probar "solo un detalle" en tu clúster en producción, sobre todo si lo has hecho 100 veces antes. Pero un lab autoalojado no es lo mismo que un entorno aislado de pruebas, y un solo comando mal formado puede transformar un experimento de tarde en una sesión de recuperación a las 4 a.m.

    4. La documentación es supervivencia

    La documentación salvó a este clúster, y la suerte tuvo poco que ver. Poca gente sabe que se puede reconstruir el almacén de monitores desde los OSD. El proceso está enterrado en los documentos de bajo nivel de Ceph, ese material que solo leen los administradores desesperados, y fue justo lo que devolvió la vida al clúster.

    El peligro de los fallos silenciosos

    Esta no fue la primera historia de desastre con Ceph, y no será la última. Otros usuarios intervinieron con experiencias inquietantemente similares: clústeres que se negaban a arrancar tras cortes de luz, monitores dañados sin posibilidad de reparación o configuraciones fantasma que persistían sin desaparecer.

    Un usuario escribió:

    "Logré romper Ceph por un corte de energía inesperado... nunca volvió a levantar y nada de lo que probé funcionó. Incluso empezando de cero reaparecían restos antiguos. Descarté Ceph y me pasé a ZFS con replicación".

    ZFS no es almacenamiento distribuido; cambia escalabilidad por sencillez y fiabilidad, lo cual resulta muy revelador. Cuando la vía de recuperación de un sistema es más dura que una migración completa, conviene interpretarlo como una señal de advertencia.

    Ceph es potente pero exigente. Ofrece una flexibilidad enorme, aunando almacenamiento de objetos, bloques y archivos en una sola plataforma, pero asume que gestionarás ese poder con responsabilidad.

    "La vergüenza pública podría ser la mejor medicina"

    Un comentarista bromeó diciendo que si el fallo era reproducible, "los desarrolladores de Ceph deberían avergonzarse". Y, sinceramente, tiene parte de razón.

    Esto va más allá de un caso límite rebuscado. Una llamada REST autenticada nunca debería poder tirar los servicios esenciales. Ya sea en un homelab o en un centro de datos, esa clase de fragilidad mina la confianza en la plataforma.

    El software de código abierto prospera gracias a la transparencia. Los fallos ocurren, pero incidentes como este evidencian la necesidad de mejores pruebas en la validación de entradas de API, sobre todo en comandos con privilegios administrativos.

    Consecuencias y reflexión

    La historia tiene un final feliz: el clúster revivió, las VM volvieron a estar en línea y el administrador aprendió más sobre las entrañas de Ceph en pocas horas que la mayoría en meses.

    También dejó huella. "Parece una locura que puedas envenenar todo el clúster con una sola llamada REST", comentó. Y no le falta razón.

    Los sistemas distribuidos están diseñados para ser resilientes, pero resiliencia no significa invulnerabilidad. A veces significa capacidad de recuperación. Este caso distó de ser ideal, pero muestra con claridad que puedes salir adelante cuando todo se tuerce.

    El panorama general

    Hay aquí una reflexión más amplia sobre la fragilidad de la automatización en la infraestructura moderna. Apilamos capas sobre capas: API sobre demonios y demonios sobre bases de datos, todo para simplificar la gestión. Cada capa introduce también nueva complejidad y nuevas formas de fallar.

    En entornos nativos de la nube, ese riesgo se multiplica. Cada servicio se comunica con otro mediante API, y cada comando, script de despliegue o tarea automatizada tiene el potencial de provocar una cascada.

    Cuando una plataforma como Ceph, uno de los sistemas de almacenamiento de código abierto más respetados del mundo, puede caer por un único campo JSON malformado, es un recordatorio de que la complejidad siempre tiene un coste.

    Epílogo: una línea para dominarlos a todos

    En algún lugar del historial del terminal descansa ese fatídico comando. Es pequeño e inocente, una línea de texto que cabe en un tuit.

    Detrás queda una historia sobre confianza, fragilidad y resiliencia en sistemas distribuidos: cómo hasta el software más sofisticado puede desmoronarse por un fallo diminuto y cómo, con el conocimiento adecuado, persistencia y documentación, puede volver a la vida. A veces, la diferencia entre una pérdida total de datos y la recuperación consiste simplemente en saber qué archivo sincronizar a continuación con rsync.