🎨 Sysprovider Code
Sysprovider LogoWiki
🇪🇸Hosting español para ecommerce

Gestión de Cgroups v2 para Aislamiento de Recursos en Servidores

Actualizado el 1 de abril de 2026

Introducción: Por qué cgroups v2 es el estándar de facto en 2025

El ecosistema de servidores Linux ha evolucionado drásticamente. La virtualización ligera, la orquestación de contenedores y la necesidad de garantizar calidad de servicio (QoS) en entornos multiinquilino han convertido el aislamiento de recursos en una habilidad fundamental para cualquier SysAdmin. Desde la versión 4.5 del kernel Linux, los cgroups v2 (control groups versión 2) se presentan como el reemplazo unificado y coherente de su predecesor, cgroups v1. En 2025, prácticamente todas las distribuciones modernas (RHEL 9+, Ubuntu 22.04+, Debian 12+) lo tienen como backend por defecto para systemd y Docker. Este artículo te guiará a través de su arquitectura, configuración y mejores prácticas para dominar la gestión de recursos en servidores Linux.

¿Qué ventajas ofrece cgroups v2 frente a v1?

Antes de sumergirnos en la configuración, es crucial entender por qué cgroups v2 es superior. Mientras que cgroups v1 permitía montar múltiples jerarquías (una por subsistema: cpu, memory, blkio, etc.), esto generaba problemas de concurrencia y consistencia. cgroups v2 simplifica el modelo a una única jerarquía unificada, donde todos los controladores (subsistemas) cuelgan del mismo árbol.

Diferencias clave

  • Jerarquía única: Todos los procesos pertenecen a un solo árbol de cgroups. Esto elimina conflictos entre controladores.
  • Control por defecto: La mayoría de los controladores están activados sin necesidad de montajes adicionales.
  • No más tareas duplicadas: Un proceso no puede estar en dos cgroups diferentes del mismo tipo.
  • Modo híbrido: Permite coexistir con v1 durante la migración, aunque no es recomendable para entornos nuevos.
  • Presión de memoria (PSI): Integración nativa de métricas de presión de recursos (memory pressure, CPU pressure, IO pressure) a través de /proc/pressure/.

[INFO] A partir de systemd v247, el soporte para cgroups v2 es completo. Distribuciones como Ubuntu 22.04 lo usan por defecto. Verifica tu kernel con: grep cgroup /proc/filesystems.

Estructura y montaje de cgroups v2

En un sistema moderno, cgroups v2 se monta automáticamente en /sys/fs/cgroup. Puedes comprobarlo con:

mount | grep cgroup
# Salida esperada:
# cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime)

La estructura de directorios dentro de /sys/fs/cgroup es plana pero jerárquica. Cada directorio representa un grupo de control. Por ejemplo:

/sys/fs/cgroup/
├── system.slice/       # Grupos creados por systemd
├── user.slice/         # Grupos por sesión de usuario
├── docker/             # Si Docker está configurado con cgroups v2
└── mi_grupo/           # Grupo personalizado

Dentro de cada directorio encontrarás archivos de interfaz como:

  • cpu.max: Límite de CPU (cuota y período).
  • memory.max: Límite de memoria en bytes.
  • io.max: Límite de IOPS o ancho de banda.
  • pids.max: Número máximo de procesos.
  • cgroup.procs: Lista de PIDs asociados al grupo.

Configuración práctica: aislamiento de CPU

Uno de los casos de uso más comunes es limitar el uso de CPU para un proceso o grupo de procesos. Con cgroups v2, esto se logra mediante el archivo cpu.max. Su formato es:

<cuota> <periodo>

Donde cuota es el tiempo de CPU máximo en microsegundos que puede usar el grupo durante un periodo (también en microsegundos). Si se excede, el grupo se estrangula (throttle).

Ejemplo: Limitar un proceso al 50% de un núcleo

# Crear un grupo personalizado
mkdir /sys/fs/cgroup/mi_grupo

# Establecer límite: 50ms de CPU cada 100ms (50% de un núcleo)
echo "50000 100000" > /sys/fs/cgroup/mi_grupo/cpu.max

# Asignar un proceso (PID 1234) al grupo
echo 1234 > /sys/fs/cgroup/mi_grupo/cgroup.procs

[TIP] Para límites de CPU más finos, usa cpu.weight. Este archivo asigna una prioridad relativa (1-10000) entre grupos que compiten por CPU. No es un límite duro, sino un reparto proporcional.

Verificación del estrangulamiento

Puedes monitorear si el grupo está siendo limitado:

cat /sys/fs/cgroup/mi_grupo/cpu.stat
# Contiene campos como nr_throttled (veces que se estranguló) y throttled_usec (tiempo total estrangulado)

Aislamiento de memoria: límites duros y blandos

La gestión de memoria en cgroups v2 es directa. El archivo memory.max establece un límite duro. Si un proceso intenta asignar más memoria de la permitida, el kernel lo mata (OOM killer) o lo bloquea dependiendo de la configuración.

Ejemplo: Limitar memoria a 256 MB

mkdir /sys/fs/cgroup/grupo_mem
echo 268435456 > /sys/fs/cgroup/grupo_mem/memory.max   # 256 MB en bytes
echo 1234 > /sys/fs/cgroup/grupo_mem/cgroup.procs

Para límites blandos, usa memory.high. El proceso no será matado, pero se estrangulará su asignación bajo presión de memoria.

Control de swap

Por defecto, cgroups v2 permite swap hasta el límite de memoria. Para deshabilitarlo:

echo 0 > /sys/fs/cgroup/grupo_mem/memory.swap.max

[WARNING] Deshabilitar swap en un grupo puede causar OOM si la memoria física se agota. Úsalo solo cuando sepas que el proceso tiene un perfil de memoria predecible.

Aislamiento de E/S (IO) con cgroups v2

El controlador io permite limitar el ancho de banda de lectura/escritura y las IOPS para dispositivos de bloque específicos. El archivo clave es io.max.

Formato de io.max

<major>:<minor> <tipo>=<límite>

Donde tipo puede ser rbps (bytes de lectura por segundo), wbps (bytes de escritura), riops (IOPS de lectura) o wiops (IOPS de escritura).

Ejemplo: Limitar E/S a 10 MB/s de lectura y 5 MB/s de escritura

# Identificar el dispositivo (ej. /dev/sda: major 8, minor 0)
ls -l /dev/sda

# Crear grupo y establecer límites
mkdir /sys/fs/cgroup/grupo_io
echo "8:0 rbps=10485760 wbps=5242880" > /sys/fs/cgroup/grupo_io/io.max
echo 1234 > /sys/fs/cgroup/grupo_io/cgroup.procs

Para un control más fino, usa io.weight (similar a CPU weight) para priorizar el acceso a E/S entre grupos.

Integración con systemd: gestión declarativa de recursos

systemd es el gestor de servicios e init más extendido en Linux. Desde la versión 247, systemd gestiona cgroups v2 de forma nativa. Puedes definir límites directamente en los archivos de unidad (.service, .slice, .scope).

Ejemplo: Servicio con límites de CPU y memoria

Crea un archivo /etc/systemd/system/mi-servicio.service:

[Unit]
Description=Servicio con límites de recursos

[Service]
ExecStart=/usr/bin/mi_aplicacion
CPUQuota=50%                # Equivale a cpu.max
MemoryMax=512M              # memory.max
MemoryHigh=384M             # memory.high
TasksMax=100                # pids.max
IOReadBandwidthMax=/dev/sda 10M   # io.max rbps
IOWriteBandwidthMax=/dev/sda 5M   # io.max wbps

[Install]
WantedBy=multi-user.target

Luego recarga systemd y arranca el servicio:

systemctl daemon-reload
systemctl start mi-servicio.service

[INFO] systemd también permite crear slices jerárquicos (por ejemplo, system.slice, user.slice) para agrupar servicios y usuarios, facilitando la gestión de recursos a nivel de sistema.

Monitorización avanzada con PSI (Pressure Stall Information)

Una de las joyas de cgroups v2 es la integración de PSI. Estos archivos en /proc/pressure/ (y dentro de cada cgroup) muestran métricas de presión de recursos en tres categorías: cpu, memory, io. Son esenciales para detectar cuellos de botella antes de que ocurra una falla.

Ejemplo de lectura de PSI

cat /proc/pressure/memory
# Salida:
# some avg10=0.00 avg60=0.00 avg300=0.00 total=0
# full avg10=0.00 avg60=0.00 avg300=0.00 total=0
  • some: Porcentaje de tiempo en que al menos un proceso está esperando por el recurso.
  • full: Porcentaje de tiempo en que todos los procesos están detenidos por falta del recurso.

Puedes monitorear estos valores con herramientas como prometheus + node_exporter o scripts personalizados.

Script simple para alertar sobre presión de memoria

#!/bin/bash
# Alerta si la presión de memoria supera el 10% en los últimos 10 segundos
pressure=$(awk '/some avg10/{print $2}' /proc/pressure/memory | cut -d= -f2)
if (( $(echo "$pressure > 10.0" | bc -l) )); then
    echo "ALERTA: Presión de memoria alta: $pressure%"
fi

Casos de uso reales en SysAdmin 2025

1. Contenedores Docker con cgroups v2

Docker desde la versión 20.10 usa cgroups v2 por defecto si el kernel lo soporta. Puedes limitar recursos al crear contenedores:

docker run -d --name web_limited \
  --cpus="0.5" \
  --memory="256m" \
  --memory-swap="256m" \
  --device-read-bps=/dev/sda:10mb \
  nginx:latest

Esto crea automáticamente cgroups en /sys/fs/cgroup/docker/.

2. Entornos multiinquilino con slices de systemd

Para aislar usuarios en un servidor compartido, usa user.slice. systemd asigna automáticamente cada sesión de usuario a su propio cgroup. Puedes limitar recursos globalmente para todos los usuarios editando /etc/systemd/system/user-.slice.d/50-limits.conf:

[Slice]
CPUQuota=200%        # Todos los usuarios juntos no pueden usar más de 2 núcleos
MemoryMax=4G
TasksMax=500

3. Priorización de servicios críticos

En un servidor web con base de datos, puedes dar más peso a MySQL que a Apache:

# Asignar mayor peso de CPU a MySQL
echo 10000 > /sys/fs/cgroup/system.slice/mysql.service/cpu.weight
# Apache con menor peso
echo 1000 > /sys/fs/cgroup/system.slice/httpd.service/cpu.weight

Herramientas y comandos esenciales para el SysAdmin

Comando/HerramientaPropósito
systemd-cglsMuestra el árbol de cgroups de systemd
systemd-cgtopMonitoriza el uso de recursos por cgroup en tiempo real
cgcreate / cgset (libcgroup)Alternativa para crear cgroups sin systemd
cat /sys/fs/cgroup/<grupo>/cpu.statEstadísticas detalladas de CPU
cat /proc/pressure/*Métricas PSI globales
podman statsSimilar a Docker stats, pero usa cgroups v2 nativamente

Solución de problemas comunes

Error: "Permission denied" al escribir en archivos de cgroups

Asegúrate de ejecutar los comandos como root o con sudo. Además, verifica que el controlador no esté deshabilitado en el kernel:

cat /boot/config-$(uname -r) | grep CGROUP
# Debe tener CONFIG_CGROUPS=y y CONFIG_CGROUP_CPUACCT=y etc.

El límite de CPU no se aplica correctamente

Revisa que cpu.max esté bien formateado. Por ejemplo, para 2 núcleos completos:

echo "200000 100000" > cpu.max   # 200ms cada 100ms = 2 núcleos

Los límites de IO no tienen efecto

Verifica que el dispositivo de bloque esté correctamente identificado. Usa lsblk para obtener major:minor.

[WARNING] cgroups v2 no soporta todos los controladores de v1 (por ejemplo, net_prio y net_cls). Si necesitas clasificación de tráfico de red, usa tc o iptables junto con cgroups v2.

Conclusión y mejores prácticas para 2025

La gestión de cgroups v2 se ha vuelto indispensable para cualquier SysAdmin que busque garantizar estabilidad y rendimiento en servidores Linux. Con la adopción masiva de contenedores y microservicios, dominar el aislamiento de recursos ya no es opcional.

Recomendaciones finales:

  1. Migra completamente a cgroups v2: Si aún usas v1, planifica la migración. La mayoría de distribuciones ya no soportan v1 en nuevos lanzamientos.
  2. Usa systemd para la gestión declarativa: Es más mantenible y seguro que manipular archivos directamente.
  3. Monitorea PSI: Implementa alertas tempranas de presión de recursos para evitar fallos catastróficos.
  4. Documenta tus límites: En entornos con muchos servicios, mantener un registro de los límites aplicados es crucial para el troubleshooting.
  5. Prueba en entornos de staging: Antes de aplicar límites agresivos en producción, simula cargas de trabajo para ajustar valores.

El dominio de cgroups v2 te permitirá exprimir al máximo el hardware de tus servidores, garantizando que cada proceso tenga los recursos que necesita sin robarle a sus vecinos. En un mundo donde la eficiencia es clave, esta habilidad te diferenciará como SysAdmin de alto nivel.

¿Necesitas ayuda?Son dos de nuestros técnicos, Agustín y Mikel, y están disponibles para resolver cualquier problema.

Hablar con ellos ahora
Agustín y Mikel