Ceph en Proxmox tiene un talento especial: funciona bien hasta el día en que migras algunas VM, arrancas una copia de seguridad y de repente todo se siente como si escribieras en una memoria USB de 2009. Se producen picos de latencia. El iowait sube. Tu configuración “hiperconvergente” se convierte en “hiperpreocupada”.
La solución rara vez es mística. Normalmente es uno de diez cuellos de botella aburridos y medibles: red, tráfico de recuperación, clases de disco mezcladas, metadatos BlueStore mal dimensionados, CPUs insuficientes o una regla CRUSH que te odia en silencio. Vamos a atraparlo en el acto.
Guion de diagnóstico rápido
Quieres respuestas rápidas, no un fin de semana con Grafana y arrepentimientos. Este es el orden que uso cuando alguien dice “Ceph está lento” y hay una cola de producción formándose detrás.
Primero: ¿el clúster está poco saludable o solo lento?
- Verifica la salud, la recuperación y las operaciones lentas. Si hay recuperación/backfill en curso, no estás diagnosticando rendimiento: estás diagnosticando una reconstrucción.
- Confirma que los OSD están up/in y que ninguno esté flapeando.
Segundo: ¿es la red?
- La mayoría de las quejas “Ceph está lento” son en realidad “la red del clúster está congestionada”.
- Busca pérdidas, retransmisiones, comportamiento extraño de offload del NIC, desajuste de MTU y switches sobresuscritos.
Tercero: ¿son los discos/OSD?
- Revisa la latencia de commit/apply de los OSD, operaciones lentas de BlueStore y si DB/WAL están en el medio equivocado.
- Asegúrate de no haber puesto OSD HDD en la misma regla CRUSH que OSD SSD y luego sorprenderte.
Cuarto: ¿es el camino del cliente (hosts Proxmox/VMs)?
- Los nodos Proxmox pueden ser un cuello de botella por CPU, la pila de red del kernel o demasiados clientes RBD.
- El caching mal configurado, el scheduler de IO incorrecto y los trabajos de backup pueden convertir “bien” en “catástrofe”.
Si solo recuerdas una cosa: siempre demuestra si el cuello de botella está en la red, el medio OSD o la recuperación antes de tocar perillas de afinado. Afinar la capa equivocada es como convertir un incidente en una “experiencia de aprendizaje”.
Algunos datos (e historia) que explican el dolor de hoy
Depurar rendimiento es más fácil cuando recuerdas por qué Ceph se comporta como lo hace.
- El objetivo de diseño de Ceph fue fiabilidad a escala, no “máximas IOPS en tres nodos”. Surgió de investigación en UC Santa Cruz y creció hasta ser un sistema de almacenamiento a escala planetaria.
- CRUSH (Controlled Replication Under Scalable Hashing) es la razón por la que Ceph puede colocar datos sin un servidor central de metadatos que decida cada ubicación. Eso es excelente para escala, pero significa que la topología y las clases de dispositivo importan mucho.
- RBD es copy-on-write a nivel bloque y prefiere latencia consistente. Reflejará sin duda micropicos y jitter de red en la latencia “de disco” de las VM.
- BlueStore reemplazó a FileStore para eliminar la sobrecarga del sistema de archivos y mejorar rendimiento, pero introdujo la historia de separación DB/WAL: hecho correctamente es rápido, hecho mal es lento de una manera muy concreta.
- La replicación 3 por defecto de Ceph es un artefacto cultural de operadores que prefieren dormir tranquilos. Pagas por esa seguridad con amplificación de escritura y tráfico de red.
- Los placement groups (PGs) son una palanca de escalado, no una superstición de afinado. Demasiados PGs consumen memoria y CPU; muy pocos concentran carga y ralentizan la recuperación.
- La recuperación y el backfill son estranguladores intencionales. Ceph intenta seguir sirviendo IO durante la reconstrucción, pero igualmente compartes discos y red.
- 10GbE popularizó Ceph en clústeres “asequibles”. Desafortunadamente, también generalizó la sobresuscripción, y la sobresuscripción es cómo obtienes latencia misteriosa.
- Proxmox hizo Ceph accesible con una interfaz amigable—y también facilitó desplegar Ceph sin hacer la tarea poco glamorosa de red y discos.
Una idea para recordar, atribuida a Werner Vogels (mentalidad de fiabilidad/operaciones): todo falla eventualmente, así que diseña y opera como si la falla fuera normal
. La depuración de rendimiento tiene la misma mentalidad: asume que la contención es normal y demuestra de dónde viene.
Las 10 comprobaciones (con comandos, salidas y decisiones)
Estas no son “consejos”. Son comprobaciones con un resultado claro: ejecutas un comando, lees la salida y eliges una acción concreta. Así dejas de adivinar.
Comprobación 1: Salud del clúster, recuperación y ops lentas (la comprobación “¿estamos reconstruyendo?”)
Si el clúster está en recuperación, tu “problema de rendimiento” podría ser comportamiento esperado. Decide si esperar, limitar la recuperación o detener el trabajo que causa churn.
cr0x@server:~$ ceph -s
cluster:
id: 9f1b2d9a-1b2c-4b9b-8d2d-2f7e5f0f2c1a
health: HEALTH_WARN
12 slow ops, oldest one blocked for 34 sec, daemons [osd.3,osd.7] have slow ops
services:
mon: 3 daemons, quorum mon1,mon2,mon3 (age 2h)
mgr: mgr1(active, since 2h)
osd: 12 osds: 12 up (since 2h), 12 in (since 2h)
data:
pools: 4 pools, 256 pgs
objects: 1.2M objects, 4.6 TiB
usage: 13 TiB used, 21 TiB / 34 TiB avail
pgs: 220 active+clean
36 active+clean+scrubbing
io:
client: 220 MiB/s rd, 55 MiB/s wr, 2.1k op/s rd, 900 op/s wr
Qué significa: “slow ops” suele indicar que los OSD no llevan el ritmo (disco) o están bloqueados (red o colas internas). El scrubbing también aparece; no es malo, pero no es gratis.
Decisión: Si las slow ops se correlacionan con ventanas de scrub/recovery, planifica scrub fuera de horas y ajusta la QoS de recuperación (comprobaciones posteriores). Si las slow ops aparecen al azar con IO normal, sigue adelante—esto es un cuello de botella real.
cr0x@server:~$ ceph health detail
HEALTH_WARN 12 slow ops, oldest one blocked for 34 sec, daemons [osd.3,osd.7] have slow ops
[WRN] SLOW_OPS: 12 slow ops, oldest one blocked for 34 sec, daemons [osd.3,osd.7] have slow ops
slow op 1, oldest at osd.3, committed, currently waiting for subops from [osd.7, osd.9]
slow op 2, oldest at osd.7, waiting for BlueStore kv commit
Qué significa: “waiting for subops” huele a replicación/red; “waiting for BlueStore kv commit” huele a DB/WAL de BlueStore o latencia del dispositivo.
Decisión: Divide tu hipótesis: ruta de red vs medio OSD/BlueStore metadata.
Comprobación 2: Demuestra que el problema está en Ceph, no en la VM o el sistema de archivos del host
Los operadores aman culpar a Ceph. A veces con razón. A veces la VM está haciendo escrituras sync de 4k a un sistema de archivos con barreras y estás viendo física en acción.
cr0x@server:~$ pvesm status
Name Type Status Total Used Available %
local dir active 98.00 GiB 22.16 GiB 70.80 GiB 22.61%
local-lvm lvmthin active 870.00 GiB 412.00 GiB 458.00 GiB 47.36%
ceph-rbd rbd active 21.00 TiB 13.10 TiB 7.90 TiB 62.38%
Qué significa: Confirma qué VM están realmente en RBD. He visto tickets “Ceph está lento” donde la VM estaba en local-lvm todo el tiempo. Eso no es un incidente avanzado; es una búsqueda del tesoro.
Decisión: Si solo algunas cargas están en Ceph, compara el comportamiento entre almacenamientos antes de tocar el tuning de Ceph.
cr0x@server:~$ rbd -p ceph-vm ls | head
vm-100-disk-0
vm-101-disk-0
vm-104-disk-0
vm-105-disk-0
Qué significa: Confirma que las imágenes RBD existen y son accesibles. Si este comando es lento, puede indicar lentitud de MON/MGR o problemas de red.
Decisión: Operaciones de metadatos lentas te empujan hacia la red, disco del MON o carga general del clúster.
Comprobación 3: Conceptos básicos de red—latencia, pérdidas, desajuste MTU (el asesino silencioso)
Ceph es un sistema de almacenamiento distribuido. Eso significa que tu red es un bus de almacenamiento. Trátala como tal.
cr0x@server:~$ ip -s link show dev eno2
2: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 3c:ec:ef:12:34:56 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
9876543210 7123456 0 18422 0 112233
TX: bytes packets errors dropped carrier collsns
8765432109 6234567 0 9 0 0
Qué significa: Las pérdidas RX en decenas de miles no son “normales”. Son un síntoma. En enlaces Ceph ocupados, las pérdidas suelen traducirse en retransmisiones, que se convierten en latencia cola, que se convierten en propietarios de VM enfadados.
Decisión: Si las pérdidas aumentan durante incidentes, arregla la red antes de afinar Ceph. Revisa buffers del switch, sobresuscripción, flow control y problemas de NIC/driver.
cr0x@server:~$ ping -c 5 -M do -s 8972 10.10.10.12
PING 10.10.10.12 (10.10.10.12) 8972(9000) bytes of data.
8980 bytes from 10.10.10.12: icmp_seq=1 ttl=64 time=0.321 ms
8980 bytes from 10.10.10.12: icmp_seq=2 ttl=64 time=0.309 ms
8980 bytes from 10.10.10.12: icmp_seq=3 ttl=64 time=0.315 ms
8980 bytes from 10.10.10.12: icmp_seq=4 ttl=64 time=0.311 ms
8980 bytes from 10.10.10.12: icmp_seq=5 ttl=64 time=0.318 ms
--- 10.10.10.12 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
rtt min/avg/max/mdev = 0.309/0.315/0.321/0.004 ms
Qué significa: Los jumbo frames funcionan de forma consistente extremo a extremo, o son una trampa. Esto comprueba la MTU de ruta con “no fragmentar”.
Decisión: Si ves “Frag needed” o pérdida de paquetes, para. Arregla la consistencia MTU en NICs, bonds, bridges y switches. MTU mezclada crea una clase especial de miseria de rendimiento: funciona a medias, lentamente.
cr0x@server:~$ ss -ti dst 10.10.10.12 | head -n 12
ESTAB 0 0 10.10.10.11:6801 10.10.10.12:0
cubic wscale:7,7 rto:204 rtt:0.31/0.02 ato:40 mss:8960 pmtu:9000 rcvmss:8960 advmss:8960
bytes_sent:123456789 bytes_acked:123450000 bytes_received:9876543 segs_out:123456 segs_in:122999
retrans:12/3456 lost:0 sacked:123 fackets:12 reordering:0
Qué significa: Retransmisiones durante un incidente de latencia son un arma humeante. No siempre la causa raíz, pero siempre relevantes.
Decisión: Si las retransmisiones aumentan bajo carga, reduce la sobresuscripción, separa el tráfico del clúster Ceph y verifica buffers de anillo de NIC e interrupciones. No “afines BlueStore” para arreglar pérdida de paquetes.
Broma #1: Los jumbo frames son como dietas: o todos las siguen, o obtienes resultados raros y mucha negación.
Comprobación 4: ¿están separadas la red pública y la de clúster (o al menos no compiten)?
Proxmox facilita ejecutar tráfico público de Ceph y replicación/backfill en la misma interfaz “solo por ahora”. “Solo por ahora” es como queda para siempre.
cr0x@server:~$ ceph config get mon public_network
10.10.10.0/24
cr0x@server:~$ ceph config get mon cluster_network
10.20.20.0/24
Qué significa: Si cluster_network está vacío, replicación y recuperación comparten la misma red que los clientes. Eso puede estar bien en clústeres pequeños, hasta que deja de estarlo.
Decisión: Si tienes NICs/VLAN separadas, configura cluster_network. Si no, considera añadirla antes de perseguir micro-optimizaciones.
Comprobación 5: Sobrecoste de replicación/EC—¿pagas dos veces por durabilidad?
Las quejas de rendimiento a menudo vienen de expectativas desajustadas. Alguien quería “discos VM rápidos”, otro quería “tres copias entre hosts” y nadie calculó la factura de IO.
cr0x@server:~$ ceph osd pool ls detail
pool 1 'ceph-vm' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 128 pgp_num 128 autoscale_mode on
pool 2 'ceph-ct' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 64 pgp_num 64 autoscale_mode on
pool 3 'cephfs_data' erasure size 4+2 crush_rule 3 object_hash rjenkins pg_num 64 pgp_num 64 autoscale_mode on
pool 4 'cephfs_metadata' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 32 pgp_num 32 autoscale_mode on
Qué significa: Un pool replicado con size 3 convierte cada escritura en tres escrituras por la red y los discos. Los pools EC reducen la sobrecarga de capacidad pero cuestan CPU y pueden aumentar la latencia en escrituras pequeñas.
Decisión: Para cargas VM con muchas escrituras aleatorias pequeñas, los pools replicados suelen ser la base sensata. Si usas EC para VMs, hazlo porque lo mediste y aceptas los compromisos.
cr0x@server:~$ ceph tell osd.* perf dump | head -n 20
{
"osd": {
"op_wip": 12,
"op_latency": 0.018,
"op_process_latency": 0.012,
"op_r_latency": 0.006,
"op_w_latency": 0.021,
"subop_latency": 0.019
}
}
Qué significa: Un aumento de subop_latency relativo a op_latency puede indicar que las suboperaciones de replicación son lentas—a menudo red, a veces peers lentos (clases de disco mixtas, OSD ocupados).
Decisión: Si un subconjunto de OSD tiene latencia mucho peor, aíslalos: pueden estar en discos peores, con firmware errado o en hosts sobrecargados.
Comprobación 6: Clases de disco y reglas CRUSH—deja de mezclar SSD y HDD en el mismo camino de rendimiento
Este es uno de los errores más comunes “funcionó en laboratorio”. Algunos OSD HDD se infiltran en la regla de un pool SSD, y ahora cada escritura ocasionalmente cae en el chico lento del grupo.
cr0x@server:~$ ceph osd tree
ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
-1 34.00000 root default
-3 11.33333 host pve1
0 ssd 1.80000 osd.0 up 1.00000 1.00000
1 ssd 1.80000 osd.1 up 1.00000 1.00000
2 hdd 3.06667 osd.2 up 1.00000 1.00000
-5 11.33333 host pve2
3 ssd 1.80000 osd.3 up 1.00000 1.00000
4 ssd 1.80000 osd.4 up 1.00000 1.00000
5 ssd 1.80000 osd.5 up 1.00000 1.00000
Qué significa: Tienes OSD HDD en la misma raíz que SSD. No es automáticamente incorrecto, pero es un riesgo si tu regla de pool no restringe por clase.
Decisión: Asegura que la regla CRUSH del pool seleccione solo SSD (o solo HDD) según la intención. Si quieres tiers mezclados, hazlo explícito con pools y políticas separadas, no con ruleta accidental.
cr0x@server:~$ ceph osd crush rule dump replicated_rule
{
"rule_id": 0,
"rule_name": "replicated_rule",
"type": 1,
"steps": [
{ "op": "take", "item": -1, "item_name": "default" },
{ "op": "chooseleaf_firstn", "num": 0, "type": "host" },
{ "op": "emit" }
]
}
Qué significa: Esta regla no filtra por clase de dispositivo. Así que los HDD pueden ser elegidos como réplicas incluso para pools orientados a SSD.
Decisión: Crea una regla basada en clases y mueve pools sensibles al rendimiento a ella. Sí, es trabajo. Es menos trabajo que explicar fsyncs de 200ms a un equipo de bases de datos.
Comprobación 7: Colocación y dimensionamiento BlueStore DB/WAL—tus “OSD SSD” aún pueden estar hambrientos de metadata
BlueStore usa RocksDB para metadata (el DB) y un WAL. En medios rápidos, la colocación del DB/WAL puede hacer o romper la latencia bajo escrituras pequeñas.
cr0x@server:~$ ceph-bluestore-tool show-label --dev /dev/sdb | head -n 30
{
"osd_uuid": "f3b6b7b3-2a3a-4b7c-9b4c-1f2e3d4c5b6a",
"size": 1920383410176,
"btime": "2025-10-01T11:12:13.000000+0000",
"description": "main",
"whoami": "3"
}
cr0x@server:~$ ceph-volume lvm list | sed -n '1,80p'
====== osd.3 =======
[block] /dev/ceph-2c1a3b4d-.../osd-block-9a8b7c6d-...
devices /dev/sdb
[db] /dev/ceph-2c1a3b4d-.../osd-db-1a2b3c4d-...
devices /dev/nvme0n1
[wal] /dev/ceph-2c1a3b4d-.../osd-wal-5e6f7a8b-...
devices /dev/nvme0n1
Qué significa: Este OSD tiene block en /dev/sdb (probablemente SSD/SATA) con DB/WAL en NVMe, lo cual es generalmente bueno para latencia. Si DB/WAL están en el mismo dispositivo lento que block para OSD HDD, lo notarás.
Decisión: Si tienes OSD HDD, considera colocar DB/WAL en SSD/NVMe. Si tienes OSD SSD pero aún ves alta latencia de commit, confirma que el DB no esté subdimensionado o contendido (varios OSD compartiendo una partición NVMe diminuta).
cr0x@server:~$ ceph daemon osd.3 bluestore perf dump | head -n 40
{
"kv_commits": 124567,
"kv_commit_latency_ms": {
"avgcount": 1024,
"sum": 8345.21,
"avg": 8.15
},
"deferred_write_ops": 0,
"stall": 0
}
Qué significa: Una latencia media de KV commit de ~8ms puede ser aceptable en HDD, sospechosa en “todo NVMe” y catastrófica si sube a decenas/centenas. También se correlaciona con slow ops “waiting for BlueStore kv commit”.
Decisión: Si la latencia de KV commit es alta, investiga la saturación del dispositivo DB, ajustes de caché de escritura y si estás empujando demasiados OSD a un mismo dispositivo DB. Considera reprovisionar con un tamaño e aislamiento de DB adecuados.
Comprobación 8: CPU, memoria y scheduler de OSD—cuando el almacenamiento es rápido, el host se vuelve el cuello de botella
Ceph no son solo discos. Los OSD hacen checksums, compresión (si está activada), networking y tareas administrativas. En clústeres pequeños, un poco de hambre de CPU se convierte en mucha latencia cola.
cr0x@server:~$ ceph tell osd.* dump_historic_ops | head -n 25
{
"ops": [
{
"description": "osd_op(client.1234:5678 1.2e3f4b5c ::ffff:10.10.10.50:0/12345 1) [write 0~4096]",
"duration": 1.238,
"initiated_at": "2025-12-28T10:11:12.123456+0000",
"age": 1.238
}
]
}
Qué significa: Ops que toman >1s no son normales para clústeres basados en SSD saludables con carga moderada. La descripción muestra escrituras de 4k; las escrituras pequeñas sync exponen la latencia inmediatamente.
Decisión: Correlaciona con CPU steal, load average y contención de hilos OSD en el mismo nodo.
cr0x@server:~$ top -b -n 1 | head -n 15
top - 10:22:01 up 12 days, 3:10, 1 user, load average: 18.22, 16.90, 12.40
Tasks: 512 total, 2 running, 510 sleeping, 0 stopped, 0 zombie
%Cpu(s): 28.1 us, 6.4 sy, 0.0 ni, 48.2 id, 15.9 wa, 0.0 hi, 1.4 si, 0.0 st
MiB Mem : 128000.0 total, 2200.0 free, 41200.0 used, 84600.0 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 82200.0 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8123 ceph 20 0 8421376 4.1g 120m S 220.0 3.3 92:12.34 ceph-osd
Qué significa: 15.9% iowait sugiere bloqueos de almacenamiento, pero el load average más el proceso OSD caliente sugieren que el nodo está ocupado. Si es un nodo hiperconvergente ejecutando muchas VMs, la contención de CPU e IO es real.
Decisión: Si OSD y VMs compiten por CPU, fija recursos, reduce densidad de VMs o separa roles. “Solo añadir tuning” no es un plan de capacidad.
cr0x@server:~$ cat /sys/block/sdb/queue/scheduler
mq-deadline none
Qué significa: Para SSD, mq-deadline suele ser un valor razonable por defecto; para HDD, la elección del scheduler importa más. Para NVMe, el scheduler suele importar menos, pero “none” está bien.
Decisión: Si ves latencia patológica en OSD HDD, valida que no estés usando un scheduler que empeore tormentas de seek. No esperes milagros: Ceph en HDD sigue siendo Ceph en HDD.
Comprobación 9: Presión de recovery/backfill/scrub—tu clúster se está comiendo las verduras durante la hora punta
El trabajo en segundo plano de Ceph es bueno. Previene pérdida de datos. También compite por los mismos discos y red que usan tus clientes.
cr0x@server:~$ ceph status | sed -n '1,30p'
cluster:
id: 9f1b2d9a-1b2c-4b9b-8d2d-2f7e5f0f2c1a
health: HEALTH_OK
services:
mon: 3 daemons, quorum mon1,mon2,mon3 (age 2h)
mgr: mgr1(active, since 2h)
osd: 12 osds: 12 up (since 2h), 12 in (since 2h)
data:
pools: 4 pools, 256 pgs
pgs: 256 active+clean
progress:
Recovery event (35s)
[============================..] (remaining: 9s)
Qué significa: Incluso con HEALTH_OK, puede haber recuperación activa. En clústeres pequeños, un evento de recuperación puede dominar el rendimiento durante minutos u horas.
Decisión: Si el IO visible al usuario es más importante que la recuperación rápida en horas de negocio, limita la recuperación durante picos y programa ventanas de mantenimiento para reequilibrados pesados.
cr0x@server:~$ ceph config get osd osd_recovery_max_active
3
cr0x@server:~$ ceph config get osd osd_max_backfills
2
Qué significa: Estos valores determinan cuán agresiva es la recuperación/backfill. Más alto = recuperación más rápida y peor latencia para clientes (habitualmente). Más bajo = más suave para clientes y reconstrucciones más lentas.
Decisión: Si tu clúster es pequeño y el IO de usuarios importa, mantén estos conservadores. Si estás en un escenario de fallo y necesitas redundancia rápido, aumenta temporalmente—luego revierte.
cr0x@server:~$ ceph config set osd osd_recovery_sleep 0.1
Qué significa: Añadir un pequeño sleep en recuperación puede suavizar la latencia de clientes dando oxígeno a los discos.
Decisión: Usa esto cuando veas picos de latencia inducidos por recovery y puedas tolerar una recuperación más lenta. Prueba con cuidado; no “setees y olvides” sin entender tiempos de reconstrucción.
Comprobación 10: Mide lo correcto—RADOS vs RBD, lecturas vs escrituras, sync vs async
Los benchmarks son útiles cuando responden una pregunta específica. “¿Qué tan rápido es Ceph?” no es una pregunta. “¿Es aceptable la latencia de escritura de los OSD?” sí lo es.
cr0x@server:~$ rados bench -p ceph-vm 30 write --no-cleanup
hints = 1
Maintaining 16 concurrent writes of 4194304 bytes for at least 30 seconds.
Total time run: 30.422
Total writes made: 259
Write size: 4194304
Object size: 4194304
Bandwidth (MB/sec): 34.06
Stddev Bandwidth: 6.12
Max bandwidth (MB/sec): 45.01
Min bandwidth (MB/sec): 18.77
Average IOPS: 8
Stddev IOPS: 1
Average Latency(s): 1.932
Max latency(s): 5.221
Min latency(s): 0.412
Qué significa: Escritas de 4MB con ~2s de latencia media es una bandera roja a menos que el clúster esté recuperando intensamente o sea HDD con contención extrema. Esto no es “ámbito de tuning”; es “algo está mal”.
Decisión: Si RADOS bench está mal, el problema es del lado del clúster (red/OSDs/recuperación). Si RADOS bench está bien pero discos VM son lentos, el problema es del lado cliente (configuración RBD, patrón IO de la VM, contención del host).
cr0x@server:~$ rbd perf image iostat --pool ceph-vm --image vm-100-disk-0 --interval 2 --count 5
rbd/image read_ops read_bytes write_ops write_bytes read_latency write_latency
ceph-vm/vm-100-disk-0 120 1.2MiB 340 24.0MiB 7.2ms 41.8ms
ceph-vm/vm-100-disk-0 110 1.1MiB 360 25.5MiB 8.1ms 55.3ms
ceph-vm/vm-100-disk-0 95 980.0KiB 390 28.3MiB 6.9ms 72.1ms
ceph-vm/vm-100-disk-0 130 1.3MiB 310 22.1MiB 7.5ms 38.9ms
ceph-vm/vm-100-disk-0 125 1.2MiB 320 23.0MiB 7.0ms 44.0ms
Qué significa: La latencia de escritura está subiendo mientras la de lectura se mantiene. A menudo apunta a presión de replicación/commit, contención DB/WAL o interferencia de recuperación.
Decisión: Si es una sola imagen/VM: revisa la carga (DB con fsync, journaling). Si son muchas imágenes: revisa latencia de commit de OSD y retransmisiones de red.
Broma #2: Hacer benchmarks sin una pregunta es como probar la resistencia de la cafetera: aprenderás algo, pero no lo que necesitabas.
Tres mini-historias corporativas desde las trincheras de rendimiento
Mini-historia 1: El incidente causado por una suposición errónea (“10GbE es suficiente”)
Tenían un clúster Proxmox ordenado, tres nodos, Ceph replicado size 3, y una pila de switches 10GbE que parecía respetable en las hojas de compra. La suposición era simple: “10GbE es suficiente para nuestra carga”. A menudo lo es—hasta que no lo es.
El primer síntoma no fue una alerta de Ceph. Fue el helpdesk: “Las VM se congelan un segundo durante las copias de seguridad”. Luego se convirtió en “las bases de datos tartamudean”. Los gráficos de latencia parecían un skyline. El dashboard de Ceph se mantuvo mayormente tranquilo, porque la salud no era el problema. Era rendimiento.
Revisamos contadores de interfaz y encontramos RX drops subiendo solo durante dos eventos: backups nocturnos y una ventana semanal de scrub. El tráfico de backup ni siquiera estaba en Ceph—al menos no intencionalmente. Compartía los mismos uplinks bondados y los mismos buffers de switch. El tráfico de replicación de Ceph y el tráfico “backup a NAS” se estaban peleando en un pasillo estrecho.
La suposición errónea fue pensar que el ancho de banda era la única métrica. El verdadero villano fue la contención y los micropicos. El tráfico de replicación de Ceph es entrecortado; el tráfico de backup es sostenido; ponlos juntos y obtienes latencia cola que pone tristes a los clientes RBD.
La solución fue aburrida: separar las redes correctamente (VLANs más QoS en el switch, y finalmente NICs dedicadas), dejar de scrappear durante ventanas de backup y aplicar una política de que el tráfico de clúster nunca comparta el mismo cuello de botella con transferencias masivas. El incidente de rendimiento desapareció. Nadie se impresionó, y así sabes que fue la solución correcta.
Mini-historia 2: La optimización que salió mal (“Aceleremos la recuperación para que termine antes”)
Otra empresa, otro ánimo: odiaban ver “backfill” en la salida de estado de Ceph. Tuvieron un nodo en bucle de reinicio tras un evento de energía, y el clúster se estaba reequilibrando. Alguien decidió “acelerarlo” aumentando la concurrencia de recuperación y backfill.
Por unos minutos pareció genial. Las barras de progreso avanzaban más rápido. Slack se entusiasmó. Luego la latencia de las VM se disparó. Las aplicaciones empezaron a fallar por timeout. El clúster no estaba mal; simplemente estaba demasiado ocupado haciendo lo correcto, demasiado agresivamente.
Lo que pasó: convirtieron la recuperación en una carga prioritaria, sin querer. El backfill golpeó los mismos discos que servían IO de clientes. La red se puso ruidosa. Las colas de OSD se llenaron. Las peticiones cliente no fallaban; simplemente esperaban. Y “esperar” es lo que las bases de datos interpretan como “el disco se está muriendo”.
Revertimos los ajustes, añadimos un pequeño recovery sleep y elegimos una estrategia más matizada: recuperación agresiva solo durante una ventana de incidente definida, y recuperación conservadora en horas laborales. Aún recuperaban la redundancia con rapidez—solo que no a costa de convertir producción en una presentación de diapositivas.
La lección no es “nunca afines la recuperación”. Es “la recuperación es una carga de rendimiento”. Si no la programas, ella te programa a ti.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día (“Reglas CRUSH por clase y disciplina de capacidad”)
Un equipo hizo algo poco glamoroso: mantuvieron simple su diseño de almacenamiento. Pools SSD y HDD separados. Reglas CRUSH separadas por clase de dispositivo. Nada de heroísmos de medios mezclados. Además mantuvieron margen: trataron 70% de utilización como “está llenándose”, no “espacio de sobra”.
Cuando un lote de SSD empezó a mostrar latencia elevada (no fallando, solo raramente más lento), el clúster no implosionó. ¿Por qué? Porque las reglas CRUSH impedían que los OSD HDD fueran réplicas por accidente de pools respaldados por SSD. Las cargas sensibles al rendimiento se quedaron en SSD. Los dispositivos lentos no arrastraron la latencia p99 de todo el pool.
Aun así tuvieron trabajo: marcar OSD sospechosos, reemplazar discos, dejar que la recuperación corriera. Pero el incidente se mantuvo contenido. Sin tickets en cascada de servicios no relacionados. Sin planes de emergencia “mover todo fuera de Ceph”.
Lo que los salvó no fue un sysctl mágico. Fue higiene de diseño. Ese tipo de higiene que parece exceso hasta el día en que convierte una crisis en una tarea de mantenimiento rutinaria.
Errores comunes: síntoma → causa raíz → solución
Esta es la parte donde reconoces tu propio clúster y te sientes ligeramente juzgado. Bien. Los sistemas de producción responden bien al juicio moderado.
1) Síntoma: Picos de latencia de escritura “aleatorios” en muchas VMs
- Causa raíz: Pérdidas/retransmisiones de red, desajuste MTU o sobresuscripción del switch causando latencia cola.
- Solución: Revisa
ip -s link,ss -ti, MTU extremo a extremo. Separa tráfico cluster/público. Reduce sobresuscripción. Evita mezclar tráfico de backup en los mismos enlaces.
2) Síntoma: Lecturas bien, escrituras pésimas
- Causa raíz: Cuello de botella en ruta de replicación/commit: peers OSD lentos, BlueStore KV commits, DB/WAL subdimensionado o recovery interfiriendo.
- Solución: Inspecciona slow ops, rendimiento de BlueStore y ajustes de recuperación. Mueve DB/WAL a dispositivos rápidos; limita recovery en picos; asegúrate que la regla del pool evita discos lentos.
3) Síntoma: “Ceph está lento” solo durante scrub/backfill
- Causa raíz: Trabajo en background compitiendo por el mismo IO y red.
- Solución: Programa ventanas de scrub. Ajusta concurrencia de recovery/backfill y añade
osd_recovery_sleepsi es necesario. Acepta tiempos de recuperación más largos como una elección de negocio.
4) Síntoma: Una VM es terrible; las demás van bien
- Causa raíz: Patrón de carga incompatible (DB sync-heavy, escrituras aleatorias pequeñas, fsync storms), o esa imagen está en un PG/OSD ocupado.
- Solución: Usa
rbd perf image iostat. Revisa dentro de la VM configuraciones de sistema de archivos y aplicación. Considera mover esa carga a un pool con otras configuraciones o medios más rápidos.
5) Síntoma: Rendimiento degradado tras “añadir capacidad”
- Causa raíz: Añadiste discos más lentos a la misma regla CRUSH/pool, o desencadenaste un reequilibrio fuerte durante pico.
- Solución: Reglas CRUSH basadas en clase. Añade capacidad en una ventana controlada. Considera reweights escalonados para reducir el blast radius del reequilibrio.
6) Síntoma: La latencia empeora al cruzar ~70–80% de utilización
- Causa raíz: Fragmentación, menos espacio libre para BlueStore/allocators y comportamientos de colocación/recuperación más costosos al llenarse el clúster.
- Solución: Mantén margen. Planifica capacidad temprano. No operes Ceph al límite a menos que disfrutes migraciones de emergencia.
7) Síntoma: Los comandos Ceph se sienten lentos (status, ls, etc.)
- Causa raíz: Latencia del disco de MON, monitores sobrecargados, problemas de red o carga general del clúster.
- Solución: Revisa IO y red del host MON. Asegura que los MONs corran en medios fiables y no estén hambrientos por VMs en el mismo nodo.
Listas de verificación / plan paso a paso
Plan de triage paso a paso (haz esto en orden)
- Captura el momento: ejecuta
ceph -syceph health detail. Guarda la salida con marca temporal. - Confirma el alcance: qué VMs, qué almacenamiento, qué nodos. Usa
pvesm statusy verifica dónde viven los discos. - Revisa recovery/scrub: si está activo, decide si limitar o esperar.
- Contadores de red:
ip -s linken todas las NIC Ceph, revisa drops y errores. - Sanidad MTU: prueba path MTU con
ping -M doentre todos los nodos en las redes Ceph. - Retransmisiones:
ss -tientre nodos; busca retransmisiones crecientes bajo carga. - Outliers de OSD: identifica OSD con peor latencia via slow ops y perf dumps.
- Clase de disco y CRUSH: verifica que los pools usen reglas y clases correctas; corrige mezclas accidentales.
- DB/WAL de BlueStore: confirma colocación y revisa latencia de KV commit.
- Haz benchmarks responsables: RADOS bench para validar clúster, luego RBD iostat para validar camino cliente.
Lista operativa para mantenerlo rápido (la rutina poco glamorosa)
- Mantén la utilización del clúster cómodamente por debajo de “lleno”. Planifica capacidad como un adulto.
- Separa redes pública y de clúster cuando sea posible, o al menos aísla del tráfico masivo.
- Aplica clases de dispositivo y reglas CRUSH; trata los medios mezclados en un pool como un ítem de revisión de diseño.
- Programa scrub y tareas de mantenimiento pesadas lejos de backups y cargas por lotes.
- Documenta ajustes de recovery/backfill y restablécelos después de incidentes.
- Monitorea distribuciones de latencia (p95/p99), no solo promedios. Los promedios son cómo te sorprenden.
Preguntas frecuentes
1) ¿Por qué Ceph en Proxmox es más lento que un NVMe local?
Porque no es lo mismo. NVMe local es un dispositivo único con accesos en microsegundos. Las escrituras en Ceph son distribuidas, replicadas y reconocidas a través de la red y múltiples OSD. Cambias latencia por disponibilidad y flexibilidad operativa.
2) ¿Realmente necesito una red de clúster separada?
No siempre, pero si tienes latencia impredecible y mezcla de IO cliente más recovery/backups en los mismos enlaces, la separación es una de las mejoras con mayor ROI. Si no puedes añadir NICs, la separación por VLAN más QoS en el switch sigue siendo mejor que “todo en todos lados”.
3) ¿Es obligatoria la replicación size 3?
No. Es un valor por defecto que refleja una postura de riesgo común. Size 2 reduce amplificación de escritura pero aumenta riesgo y reduce tolerancia a fallos. La elección depende de requisitos de negocio, número de nodos y cuánto odias el downtime.
4) ¿Debería usar erasure coding para discos de VM?
Usualmente no para VMs sensibles a latencia y con escrituras pequeñas. EC puede ser excelente para eficiencia de capacidad y objetos grandes, pero añade coste en CPU y puede penalizar escrituras aleatorias pequeñas. Si quieres EC para VMs, mídelo con tu carga real y acepta la complejidad.
5) ¿Qué significa realmente “slow ops”?
Significa que una operación de IO cliente está tardando más de lo esperado dentro del pipeline del OSD—esperando sub-ops, commits, disco o atascada detrás de colas. La salida de detalle suele indicar si es latencia de red/subop o latencia de commit de BlueStore.
6) ¿Unos pocos discos lentos realmente pueden dañar todo el pool?
Sí. La replicación hace que tu latencia de escritura a menudo esté limitada por la réplica más lenta involucrada en la operación. Si tu regla CRUSH permite HDDs en un pool pensado para SSD, has construido un generador aleatorio de latencia p99.
7) ¿Por qué el rendimiento cae durante recovery aunque el clúster esté “HEALTH_OK”?
Porque HEALTH_OK trata seguridad de datos e invariantes del clúster, no el SLO de latencia de tu aplicación. La recuperación es IO y tráfico de red pesado; Ceph puede mantenerse correcto y aun así ser lento.
8) ¿Cuántos OSD por nodo son “demasiados”?
Depende de CPU, RAM, medios y red. Si los procesos OSD tienen hambre de CPU o si los dispositivos DB de BlueStore se comparten demasiado agresivamente, verás latencia de commit y slow ops. La respuesta correcta sale de medir latencia por OSD y contención en el host, no de un número mágico.
9) ¿Debo “simplemente añadir más PGs” para arreglar hotspots?
No, no reflexivamente. El conteo de PGs afecta memoria, overhead de peering y comportamiento de recuperación. Usa autoscaling cuando proceda y ajusta manualmente solo cuando entiendas por qué la distribución es pobre.
10) ¿Cuál es el indicador más rápido de “red vs disco” como cuello de botella?
Mira retransmisiones/pérdidas para la red y latencia de KV commit de BlueStore más retrasos de apply/commit de OSD para disco/metadata. Si ambos están mal, felicidades: tienes un problema real de sistemas distribuidos.
Conclusión: siguientes pasos que mueven la aguja
Si el rendimiento de Ceph-on-Proxmox es lento, no empieces cambiando tunables. Empieza demostrando dónde se pasa el tiempo. Ejecuta el guion de diagnóstico rápido y luego haz las diez comprobaciones con disciplina: contadores de red, MTU, retransmisiones, presión de recovery, clases de disco/reglas CRUSH, colocación DB/WAL de BlueStore y finalmente benchmarks dirigidos.
Tus pasos prácticos siguientes:
- En una hora: captura
ceph -s,ceph health detail, drops de NIC, pruebas MTU y retransmisiones durante el periodo lento. - En un día: verifica que las reglas de pool no mezclen clases de disco; confirma separación red pública/cluster; audita cronogramas de recovery/scrub.
- En una semana: arregla problemas estructurales—DB/WAL en dispositivos adecuados, elimina discos lentos fuera de lugar y corrige sobresuscripción. Afina solo después de que la arquitectura deje de pelear consigo misma.
Ceph puede ser rápido. También puede ser fiable. Pero no será ninguna de las dos si tratas la red como una ocurrencia tardía y el diseño de disco como una sugerencia.