Volver al blog
31 de agosto de 2026Sergei Solod8 min de lectura

Mi VPS de REGXA mostró un 94 % de CPU steal incluso sin tráfico

Al investigar graves problemas de rendimiento en un VPS KVM de REGXA encontré un 92–94 % de CPU steal, solicitudes a localhost que tardaban segundos, colas de conexiones crecientes y respuestas HTTP 504 de más de dos minutos. Tras retirar todo el tráfico de producción, el CPU steal subió al 94,17 %, y REGXA terminó atribuyéndolo a contención de recursos en su infraestructura compartida.

REGXAVPSLinuxCPU stealvirtualización

No escribo esto como una reseña negativa de REGXA ni para decirle a nadie si debería o no comprarles un VPS. Es simplemente uno de mis días como desarrollador.

Migré una carga normal a un VPS KVM con 2 vCPU, 2 GB de RAM y 60 GB NVMe. Nginx funcionaba. El backend funcionaba. Pero la máquina se comportaba como si estuviera completamente saturada: las solicitudes se acumulaban, TLS se volvía lento, las conexiones permanecían abiertas y algunas peticiones acababan devolviendo HTTP 504 después de más de dos minutos.

La contabilidad de CPU cambió la investigación

Mi primera hipótesis era obvia: algo dentro del VPS estaba consumiendo el procesador. Entonces ejecuté mpstat.

Average CPU steal: 92.58%
CPU 0 steal: 90.62%
CPU 1 steal: 94.57%
CPU user: 4.02%
CPU system: 1.47%
CPU iowait: 0.41%
CPU idle: 0.53%

Las muestras individuales mostraban repetidamente alrededor de un 89–98 % de steal. La presión de CPU también era extrema:

CPU PSI some avg10: 79.47
CPU PSI some avg60: 75.32
CPU PSI some avg300: 76.31
Load average: 5.85 / 5.75 / 5.73

Era una máquina con solo dos vCPU. Linux tenía procesos ejecutables esperando CPU. La cifra importante no era el uso normal de CPU de la aplicación, sino %steal.

Un uso alto de CPU y CPU steal son problemas distintos

Si mi aplicación estuviera consumiendo realmente el procesador, esperaría valores altos de user o system. En cambio, el VPS se parecía aproximadamente a esto:

user: 4%
system: 1%
steal: 93%

CPU steal es el tiempo durante el cual una CPU virtual está lista para ejecutarse, pero el hipervisor no la programa. Por eso, cuando digo que al VPS se le estaba quitando tiempo de CPU, lo digo en ese sentido técnico de virtualización. No puedo demostrar que REGXA reasignara deliberadamente a otro cliente unos núcleos físicos que fueran exclusivamente míos, ni puedo deducir intención a partir de las métricas del invitado. Lo que sí puedo demostrar es que la máquina tenía trabajo listo y repetidamente no recibía tiempo de planificación de CPU.

Eliminé todo el tráfico de producción

Seguía existiendo una objeción razonable: quizá mi propia carga provocaba el problema. Así que eliminé esa variable. Moví la carga activa a otra máquina, dejé de enviar tráfico de producción al VPS, esperé a que se vaciaran las colas y repetí la medición.

Average CPU steal: 94.17%
CPU 0 steal: 95.56%
CPU 1 steal: 92.83%
CPU user: 1.95%
CPU system: 0.59%
CPU iowait: 0.59%
CPU idle: 2.18%

El resultado empeoró. Las muestras de vmstat seguían mostrando entre un 91 y un 98 % de steal, y hasta 15 procesos ejecutables esperaban CPU. La combinación clave era:

user: 1.95%
system: 0.59%
steal: 94.17%

Mis aplicaciones casi no hacían nada, pero la VM seguía perdiendo prácticamente todo su tiempo de planificación. La carga normal de producción dejó de ser una explicación creíble.

Hasta localhost se volvió absurdamente lento

También probé HTTPS a través de 127.0.0.1, eliminando de la prueba el DNS público, mi ISP, la distancia geográfica y la ruta de red externa.

Con tráfico, cuatro de diez intentos HTTPS a localhost fallaron durante el handshake TLS. Los que sí terminaron tardaron 29,30, 22,77, 12,25, 11,87, 11,12 y 9,40 segundos. Algunos handshakes TLS por sí solos duraron alrededor de nueve segundos.

Después de retirar el tráfico de producción, localhost mejoró, pero siguió siendo inestable: 0,061, 0,745, 0,830, 0,873, 1,010, 1,117, 1,121, 2,188 y 3,355 segundos. La misma operación local podía tardar unos 61 ms una vez y más de 3,3 segundos en el siguiente intento.

El resto del stack mostraba las consecuencias

En un momento llegué a observar aproximadamente 450 conexiones establecidas, 122 conexiones huérfanas, 110 FIN-WAIT-1 y 33 CLOSE-WAIT. La cola de escucha del backend local llegó a unas 14–15 conexiones, y la de HTTPS a unas 40.

Nginx registró respuestas HTTP 504 después de 142,857, 138,902, 135,064, 129,819 y 128,657 segundos. Otras peticiones permanecieron abiertas durante unos 67–130 segundos. También vi timeouts de conexión segura de unos 35–41 segundos, timeouts de red hacia la base de datos y operaciones TLS retrasadas.

Por separado, esos síntomas podían parecer problemas distintos de Nginx, base de datos, red o backend. Pero aumentar los timeouts no crea tiempo de CPU que el hipervisor no está programando.

Ni la RAM ni el disco explicaban el problema

El VPS todavía tenía aproximadamente 1,0–1,1 GiB de RAM disponible, casi nada de swap utilizado, ningún evento OOM y ninguna actividad del OOM killer. El sistema de archivos estaba solo alrededor del 20 % ocupado, con unos 44 GB libres. El I/O wait se mantuvo por debajo del 1 % durante las mediciones importantes de CPU.

No faltaba memoria, el disco no estaba lleno y mis aplicaciones no estaban consumiendo la CPU desaparecida. La métrica dominante seguía siendo %steal.

Un VPS KVM sano se veía completamente distinto

Ejecuté el mismo tipo de diagnóstico en otro VPS KVM que estaba atendiendo tráfico normal:

Average CPU steal: 0.02%
CPU idle: 87.86%
CPU PSI avg10: 0.29
CPU PSI avg60: 0.63
CPU PSI avg300: 0.49
Load average: 0.47 / 0.33 / 0.14

Sus diez solicitudes HTTPS locales tardaron aproximadamente entre 37 y 69 ms. Más tarde medí otro VPS de producción realmente ocupado y observé 61,71 % de CPU user, 5,08 % de CPU system, 24,09 % idle y solo 0,13 % de steal.

Esa es ahora la distinción importante para mí. Un VPS puede estar ocupado porque mi software realmente usa el procesador. Eso es muy diferente de que el invitado pase más del 90 % del tiempo de CPU medido esperando al hipervisor.

REGXA terminó confirmando la contención en la infraestructura

Desde dentro de la VM podía medir al sistema invitado, pero no podía ver el host físico, la configuración del scheduler, las cuotas de CPU ni las máquinas virtuales vecinas. REGXA sí podía.

Finalmente, soporte me dijo que el VPS estaba alojado sobre shared CPU infrastructure, que los recursos de CPU se compartían entre varias máquinas virtuales y que el rendimiento podía variar según la carga del nodo físico. También indicaron que la infraestructura de Frankfurt estaba experimentando una demanda especialmente alta y atribuyeron explícitamente mi elevado CPU steal a resource contention on the underlying infrastructure.

También dijeron que no podían modificar las cuotas ni las políticas de planificación de CPU ni dedicar recursos adicionales a ese VPS compartido sobre la infraestructura actual. La solución técnica propuesta fue trasladar el VPS a una ubicación con menor utilización.

Eso resultaba difícil de conciliar con el lenguaje que yo había visto sobre núcleos de CPU dedicados y recursos garantizados. No puedo ver la configuración exacta del host, así que no puedo afirmar si el mecanismo inmediato fue CPU overcommitment, cuotas, pesos del scheduler, throttling o una combinación. Tampoco puedo demostrar intención. No hace falta: Linux mostró de forma sostenida un 92–94 % de steal y la propia REGXA atribuyó ese valor elevado a la contención en su infraestructura compartida.

Conseguir el reembolso exigió otra ronda de insistencia

Una vez claro el problema de infraestructura, no quería seguir trasladando el VPS y probando otros nodos. Quería cancelar el servicio y recuperar mi dinero.

Al principio me ofrecieron únicamente una cantidad parcial, y el reembolso propuesto iba al saldo de mi cuenta REGXA en lugar de volver a la tarjeta que había utilizado para pagar. Para mí, saldo interno del proveedor no equivale a un reembolso cuando quiero abandonar el servicio.

Así que seguí respondiendo y pidiendo que se devolviera el 100 % del pago al método de pago original. Finalmente REGXA aceptó y devolvió el importe completo al método de pago original, describiendo el reembolso íntegro como una excepción.

Aprecio que finalmente devolvieran todo. Pero tener que seguir insistiendo por la resolución económica después de que soporte ya hubiera reconocido la contención de infraestructura también forma parte de mi experiencia.

La lección que me quedó

El error más fácil habría sido seguir optimizando mi aplicación. Podría haber cambiado Nginx, aumentado los timeouts, reducido la concurrencia, añadido reintentos, investigado MongoDB o reescrito código del backend. Algunas cosas quizá habrían cambiado síntomas concretos. Ninguna habría respondido a la pregunta importante: ¿por qué el CPU steal superaba el 90 %?

Ya no me basta con comprobar que SSH funciona, Nginx arranca y un endpoint de salud devuelve 200. En un VPS nuevo también miro %user, %system, %iowait, %idle, %steal, CPU PSI, la cola de ejecución y la latencia de localhost.

Y cuando algo parece sospechoso, retiro la carga y vuelvo a medir. En este caso eso produjo el resultado más claro de todo el incidente:

CPU user: 1.95%
CPU system: 0.59%
CPU steal: 94.17%

No afirmo que todos los VPS de REGXA se comporten así. Probé un VPS y documenté lo que ocurrió en él. Pero en esa máquina la evidencia fue excepcionalmente clara: mis aplicaciones apenas consumían CPU mientras Linux indicaba que la gran mayoría del tiempo de CPU virtual se perdía esperando la planificación del hipervisor. Más tarde, REGXA atribuyó exactamente ese comportamiento a la contención de recursos en su infraestructura compartida.

Por eso lo documento. No como una puntuación ni como una recomendación, sino simplemente como uno de mis días como desarrollador y como una métrica que nunca volveré a ignorar en un VPS.