Sysadmin

Cgroups Linux: Limitar CPU y RAM en Procesos (2026)

Cgroups Linux: Limitar CPU y RAM en Procesos (2026)

Encontré swap activa en un servidor con 32 GB de RAM libre. La causa: vm.swappiness=60 sin modificar. Una sola línea en sysctl.conf habría eliminado 200 ms de latencia media en las consultas. Investigando, descubrí que un proceso batch consumía RAM a picos, forzando al kernel a mover páginas al disco y degradando toda la máquina. El 72% de las interrupciones de servicio causadas por recursos agotados parte de un solo proceso fuera de control (SRE Report 2025). Cuando gestionas infraestructuras críticas, como una organización sanitaria pública con miles de endpoints, un servicio descontrolado compromete la disponibilidad que exigen estándares como ISO 27001:2022. La solución no es solo ajustar swappiness, sino aislar el proceso. Los cgroups (Control Groups) de Linux permiten limitar, contabilizar y aislar los recursos de CPU y RAM asignados a procesos. Se configuran con systemd-run para ejecuciones temporales o systemctl set-property para servicios permanentes.

| Objetivo | Comando | Notas |

|—|—|—|

| Limitar CPU al vuelo | systemd-run --scope -p CPUQuota=50% -- cmd | Válido para una sola ejecución |

| Limitar RAM al vuelo | systemd-run --scope -p MemoryMax=512M -- cmd | Previene el OOM killer |

| Límite permanente servicio | systemctl set-property nombre.service CPUQuota=50% | Sobrevive al reboot |

| Verificar límite CPU | cat /sys/fs/cgroup/.../cpu.max | Lee el filesystem virtual |

| Iniciar contenedor limitado | docker run --cpus='0.5' --memory='512m' nginx | Docker crea cgroups automáticamente |

Requisitos Previos / Entorno de Prueba

Para probar los comandos necesitas una distribución Linux moderna con systemd y cgroups v2 activos. Ubuntu 22.04/24.04, Debian 12 o RHEL 9 funcionan perfectamente. Necesitas acceso root o sudo. Verifica la versión con: stat -fc %T /sys/fs/cgroup/. Si devuelve cgroup2fs, estás listo.

Cgroups Linux: Conceptos y Diferencia v1 vs v2

Un cgroup es una feature del kernel Linux que agrupa procesos en jerarquías y asigna límites de recursos. Cada proceso pertenece a un cgroup. Si no defines uno personalizado, termina en el cgroup por defecto del sistema, donde no tiene límites. Puedes impedir que un script ocupe el 100% de la CPU o que una base de datos con un memory leak consuma toda la RAM hasta que salte el OOM killer.

La versión 1 usaba una jerarquía separada para cada recurso. Un cgroup para la CPU, otro para la memoria, otro para I/O. Generaba confusión y conflictos. La versión 2 unifica todo en una sola jerarquía. Hoy systemd gestiona los cgroups v2 de forma nativa en todas las distribuciones principales. Cuando inicias un servicio con systemd, creas un cgroup. El 89% de las infraestructuras usa contenedores en producción, y cada uno se basa en cgroups v2 para aislar recursos (CNCF Survey 2025).

Limitar CPU y RAM con systemd

Para limitar un comando único sin crear archivos de configuración, usa systemd-run. Ejecuto un script pesado y le concedo solo el 50% de un core.

systemd-run --scope -p CPUQuota=50% -p MemoryMax=512M -- ./script_pesado.sh

El parámetro CPUQuota=50% significa que el proceso puede usar como máximo el 50% de un core CPU. Si tienes 4 cores y escribes CPUQuota=200%, el proceso puede usar 2.

En el mismo comando he especificado MemoryMax=512M. Este es un límite absoluto. Si el proceso intenta asignar el megabyte 513, el kernel lo bloquea. El OOM killer entra en acción y termina el proceso. Usa MemoryHigh=512M si prefieres ralentizar el proceso en lugar de matarlo, aplicando presión sobre la memoria.

Para un servicio que funciona siempre, aplica los límites directamente a la unidad systemd. systemd-run funciona para ejecuciones ad hoc.

systemctl set-property nombre.service CPUQuota=50%
systemctl set-property nombre.service MemoryMax=512M

Estos comandos crean archivos de configuración en /etc/systemd/system.control/nombre.service.d/. Los límites sobreviven al reboot y se aplican inmediatamente sin reiniciar el servicio.

Con cgroups v2 y systemd, la gestión manual con cgcreate no es recomendable porque systemd no conocería su existencia. Si necesitas un slice personalizado para agrupar varios servicios, crea un archivo /etc/systemd/system/mioslice.slice:

[Unit]
Description=Mi Slice Personalizado

[Slice]
CPUQuota=200%
MemoryMax=2G

Luego asigna los servicios a este slice con systemctl set-property nombre.service Slice=mioslice.slice.

Verificar Límites y el Caso Docker

El kernel expone el estado de los cgroups a través de un filesystem virtual. Para comprobar la CPU asignada a un servicio:

cat /sys/fs/cgroup/system.slice/nombre.service/cpu.max

El output muestra dos valores: la quota y el periodo. 50000 100000 significa 50% de CPU. max 100000 significa sin límite. Para la RAM comprueba memory.max.

Docker usa cgroups bajo el capó. Cuando inicias un contenedor con límites de recursos, Docker traduce los flags en parámetros cgroup v2.

docker run --cpus='0.5' --memory='512m' nginx

Este comando crea un cgroup, coloca el proceso del contenedor y aplica los límites. --cpus='0.5' configura CPUQuota=50%. --memory='512m' configura MemoryMax=512M. Si rastreas el PID del contenedor en /proc/PID/cgroup, verás la ruta bajo /sys/fs/cgroup/system.slice/docker-.scope/.

Errores Comunes y Resolución de Problemas

El límite no se aplica: Comprueba que estás en cgroups v2. Si estás en v1, las rutas y comandos cambian. Verifica con stat -fc %T /sys/fs/cgroup/.

Proceso terminado inesperadamente: Si configuras MemoryMax demasiado bajo, el OOM killer termina el proceso. Revisa los logs del kernel con dmesg para confirmarlo. Usa MemoryHigh para un umbral suave.

Imposible modificar la propiedad: Si systemctl set-property devuelve error, el servicio podría estar ejecutándose en un modo que no soporta cambios en runtime. Detén el servicio, configura la propiedad y reinícialo.

Cómo ver los procesos de un cgroup: Usa systemd-cgls para visualizar el árbol de cgroups y los procesos asociados. Para un cgroup específico, lee el archivo cgroup.procs en la ruta del cgroup, como cat /sys/fs/cgroup/system.slice/nombre.service/cgroup.procs.

CPUQuota vs CPUShares: CPUShares define un peso relativo entre procesos que compiten por la CPU. CPUQuota define un límite absoluto. Con CPUQuota=50%, el proceso nunca superará el 50% de un core, aunque la CPU esté al 10% de uso global.

Impacto en performance: Los límites de cgroups afectan el rendimiento solo si el proceso intenta superar el límite asignado. Un proceso que usa el 30% de CPU con un límite del 50% no sufre ralentizaciones. Si intenta usar el 60%, el kernel lo limita a la quota asignada.

Conclusiones con Puntos Clave Operativos

Controlar los recursos no es opcional en producción. Un solo proceso sin límites puede degradar todo el sistema. Aplica estos tres pasos: identifica los procesos críticos o potencialmente inestables, usa systemctl set-property para limitar su CPU y RAM, monitoriza los límites leyendo el filesystem virtual. Docker lo hace por defecto para cada contenedor. Haz lo mismo con tus servicios bare metal.

Lee también: Lynis Audit Linux: Guía Práctica de Hardening 2026

Referencia externa: cgroups(7) – Linux man page

Comparte este artículo:

Escrito por

Rosario Giordano

Rosario Giordano es administrador de sistemas y consultor de TI especializado en c iberseguridad y cloud, con más de 20 años de experiencia en la gestión de infraestructuras Linux empresariales. Sus áreas de especialización incluyen el hardening de SSH, plataformas Kubernetes , bases de datos PostgreSQL, virtualización con VMware/Proxmox y el cumplimiento de los marcos de seguridad NIS2 e ISO 27001.