Gestión de memoria en Linux: Swap, OOM Killer y Cgroups

12 min de lectura - 31 de mayo de 2026

hero section cover
Tabla de contenidos
  • Explicación de la gestión de memoria en Linux: swap, OOM killer y cgroups
  • Cómo gestiona Linux las páginas de memoria
  • Configuración del swap
  • El OOM killer
  • Cgroups y límites de memoria
  • Configuración de la memoria según la función del servidor
Compartir

Cómo funcionan juntos Linux swap, el OOM killer y cgroups - con ejemplos de configuración para bases de datos, servidores web y hosts VPS multi-tenant.

Explicación de la gestión de memoria en Linux: swap, OOM killer y cgroups

Linux gestiona la memoria de forma diferente a la mayoría de los sistemas operativos. Un uso elevado de la RAM no siempre es un problema: el kernel utiliza activamente la memoria libre para el almacenamiento en caché con el fin de acelerar las lecturas del disco. Pero cuando se acumula una presión real sobre la memoria, tres mecanismos se encargan de la tarea: swap, el OOM killer y los cgroups. Comprender cómo se comporta cada uno de ellos y cómo configurarlos marca la diferencia entre un servidor que se degrada de forma controlada bajo carga y uno que se bloquea sin previo aviso.

Cómo gestiona Linux las páginas de memoria

Cada proceso se ejecuta en su propio espacio de direcciones virtuales, de hasta 128 TB en sistemas de 64 bits. El núcleo asigna estas direcciones virtuales a la RAM física a través de tablas de páginas, con el búfer de traducción (TLB) almacenando en caché las búsquedas recientes. Una coincidencia en el TLB tarda alrededor de 1 nanosegundo; una falta cuesta entre 20 y 100 nanosegundos, lo que se acumula en cargas de trabajo que consumen mucha memoria, como las bases de datos.

La memoria física se divide en páginas de 4 KB, y el núcleo las clasifica en dos categorías:

  • Páginas respaldadas por archivos: vinculadas a archivos en el disco. El núcleo puede descartar las limpias o vaciar las sucias sin necesidad de swap.
  • Páginas anónimas: memoria de pila y montón sin archivo de respaldo. Estas deben escribirse en el intercambio antes de que el núcleo pueda liberarlas.

En servidores con una gran demanda de memoria, una gran proporción de páginas anónimas implica que el intercambio se activa pronto. Observe el si (swap in) y so (swap out) en vmstat 1 : los valores persistentes distintos de cero son la primera señal de que el sistema está bajo presión.

Para la supervisión, utilice la herramienta adecuada para la tarea:

HerramientaIdeal paraMétrica clave
free -hInstantánea rápida de todo el sistemaavailable columna
vmstat 1Supervisión en tiempo real del intercambio y las E/Ssi, so
htopVista interactiva por procesoBarras de memoria, lista de procesos
smemUso preciso por procesoUSS (tamaño de conjunto único)
/proc/meminfoDetalles a nivel del núcleoMemAvailable, Dirty, Slab

Un error común: fijarse en la free columna en free -h y entrar en pánico. Lo available columna es la que importa. Incluye la memoria que el kernel puede recuperar de la caché bajo demanda. Un servidor que muestre solo 512 MB libres pero 5 GB disponibles no tiene ningún problema.

Cuando la memoria cae por debajo de un umbral, el kswapd demonio del núcleo comienza a recuperar páginas en segundo plano. Si eso no es suficiente, el núcleo pasa a la recuperación directa, bloqueando procesos hasta que se liberen las páginas. De ahí provienen los picos de latencia. Configura una alerta cuando MemAvailable caiga por debajo del 10-15 % de la RAM total para que tengas tiempo de reaccionar.


 

Configuración del swap

El swap es un área del disco —ya sea una partición o un archivo— a la que el kernel traslada las páginas anónimas inactivas cuando se llena la RAM. La diferencia de velocidad es significativa: la RAM DDR4 tiene una latencia de aproximadamente 100 ns, mientras que los SSD NVMe rondan los 100 000 ns y los SSD SATA se acercan a los 500 000 ns. El swap es un búfer de seguridad, no RAM adicional. Un servidor que depende constantemente del swap tiene un problema de memoria que no se solucionará con más swap.

Utilice un archivo de intercambio en lugar de una partición. Es más fácil cambiar su tamaño y no requiere reparticionar.

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Añade el archivo /etc/fstab para que persista tras los reinicios. El chmod 600 paso es obligatorio: cualquier dato paginado fuera de la RAM es legible desde el swap, por lo que el archivo no debe ser legible para todos.

Después de crear el swap, ajuste vm.swappiness. El valor predeterminado de 60 es agresivo. Para la mayoría de las cargas de trabajo de alojamiento, es preferible que el kernel dé prioridad a la RAM y solo utilice el swap como último recurso:

Función del servidorvm.swappinessvm.vfs_cache_pressure
Servidor web general10–2050
Base de datos (MySQL/PostgreSQL)1–550
Predeterminado (la mayoría de las distribuciones)60100

Para el tamaño del swap: 1–2 GB es suficiente para un VPS de 2 GB que gestione picos de tráfico ocasionales. En sistemas con 8 GB o más, un swap fijo de 2–4 GB suele ser suficiente. El objetivo es proporcionar al kernel una válvula de escape para las páginas inactivas, no ampliar la memoria total direccionable.

En servidores con memoria RAM limitada pero con CPU abundante, zram crea un área de swap comprimida en la memoria, evitando por completo la E/S de disco. Vale la pena considerarlo en hosts VPS multitenant donde NVMe se comparte entre los tenants. Hay que estar atento a la contienda de E/S si el swap reside en el mismo dispositivo que los archivos de la base de datos: el intercambio intensivo y las escrituras de disco de alto rendimiento no coexisten bien.

El OOM killer

Cuando el kernel agota la RAM y el espacio de intercambio y no puede recuperar suficiente memoria por otros medios, interviene el OOM killer. Este evalúa los procesos utilizando la oom_badness() función:

points = (rss_anon + rss_file + rss_shmem + swapents + pgtables_pages) + (oom_score_adj × totalpages / 1000)

El proceso con la puntuación más alta se elimina. La fórmula favorece a los procesos que consumen mucha memoria, y el kernel evita eliminar varios procesos en rápida sucesión comprobando si un proceso ya se ha terminado en los últimos 5 segundos.

En los registros aparecen dos tipos de eventos OOM:

  • OOM global: todo el sistema se ha quedado sin RAM y sin espacio de intercambio. Los registros comienzan con Out of memory:
  • OOM de Cgroup: un contenedor o servicio ha alcanzado su memory.max límite. Los registros comienzan con Memory cgroup out of memory:

Para revisar eventos OOM anteriores:

dmesg -T | grep -i "out of memory"
journalctl -k --grep="oom"

Presta atención al order campo en los registros de OOM. Un valor superior a 0 sugiere fragmentación de la memoria en lugar de agotamiento total: el kernel no pudo encontrar suficientes páginas contiguas incluso con memoria libre disponible.

Puedes influir en los procesos a los que se dirige el OOM killer ajustando /proc/<pid>/oom_score_adj. El rango va de -1000 (nunca matar) a +1000 (matar primero). Para los servicios gestionados por systemd, configúrelo de forma permanente en el archivo de unidad:

[Service]
OOMScoreAdjust=-1000

Parámetros sysctl adicionales para ajustar el comportamiento de OOM:

ParámetroValorEfecto
vm.overcommit_memory0Modo heurístico de sobreasignación predeterminado
vm.overcommit_memory2Modo estricto; impide que las asignaciones superen RAM × overcommit_ratio + swap
vm.panic_on_oom1Reinicia en lugar de matar un proceso
vm.oom_kill_allocating_task1Elimina el proceso que ha provocado el OOM en lugar del mayor consumidor

Para una supervisión proactiva, consulte /proc/pressure/memory (Información de estancamiento por presión, disponible desde el kernel 4.20). Observe el some avg10 valor: por debajo del 5 % es normal; si se mantiene por encima del 20 %, es probable que se produzca un evento OOM. Un allocstall contador en /proc/vmstat es otra señal temprana: cuenta los bloqueos de recuperación directa, que a menudo preceden a las terminaciones por OOM. Herramientas como systemd-oomd o earlyoom pueden actuar en función de los umbrales de PSI antes de que se active el OOM killer del kernel.

Cgroups y límites de memoria

Los grupos de control (cgroups) permiten organizar los procesos en grupos y aplicar límites estrictos de recursos. Introducidos en Linux 2.6.24, son la base de los entornos de ejecución de contenedores, incluidos Docker, Podman, Kubernetes y LXC. El kernel realiza un seguimiento del uso de memoria por cgroup, incluyendo la memoria anónima, las páginas respaldadas por archivos y los objetos del kernel. Si un cgroup alcanza su límite, el kernel recupera memoria dentro de ese grupo o activa una terminación OOM (falta de memoria) en el ámbito del cgroup.

Los cgroups v1 y v2 difieren principalmente en su estructura. La v1 monta cada controlador (memoria, CPU, E/S) por separado bajo /sys/fs/cgroup/<controller>/, lo que da lugar a un seguimiento inconsistente de los recursos. V2 utiliza una jerarquía unificada en /sys/fs/cgroup/. Kubernetes cambió a v2 como predeterminado en la versión 1.25 y dejó de admitir v1 en la 1.31.

Para comprobar qué versión utiliza tu sistema:

stat -fc %T /sys/fs/cgroup/

cgroup2fs significa v2; tmpfs normalmente significa v1.

CaracterísticaCgroup v1Cgroup v2
JerarquíaMúltiple, por controladorÚnica, unificada
Límite de memoria rígidomemory.limit_in_bytesmemory.max
Límite de memoria flexiblememory.soft_limit_in_bytesmemory.high (limitaciones)
Seguimiento del usomemory.usage_in_bytesmemory.current
Métricas de presiónLimitadoPSI integrado

Los controles de memoria clave en cgroup v2:

ParámetroTipoDescripción
memory.maxLímite estrictoSi se supera este valor, se activa el OOM killer
memory.highLímite flexibleLimita la asignación y activa la recuperación antes de alcanzar el límite duro
memory.lowProtección blandaLa memoria por debajo de este umbral se recupera en último lugar
memory.minProtección estrictaLa memoria por debajo de este nivel nunca se recupera
memory.swap.maxLímite de intercambioEstablecer en 0 para desactivar el intercambio para este cgroup
memory.oom.groupBooleanoSi está habilitado, OOM mata todos los procesos del cgroup a la vez

Una regla práctica: ajústelo memory.high entre un 10 % y un 20 % por debajo memory.max para dar al kernel margen para recuperar memoria antes de alcanzar el límite máximo. Al dimensionar memory.max, añada un 20-30 % por encima del uso máximo de la aplicación para tener en cuenta la caché de páginas, que cuenta para el total de memoria del cgroup.

Gestiona los cgroups a través de systemd en lugar de escribir directamente en el sistema de archivos del cgroup. Utiliza directivas de archivos de unidad como MemoryMax=, MemoryHigh=, y MemoryMin= para límites persistentes. Para pruebas rápidas:

systemd-run --scope -p MemoryMax=512M <command>

Para los grupos de trabajadores de servidores web, configurar memory.oom.group=1 garantiza una terminación limpia si un trabajador excede su límite, sin dejar procesos huérfanos. Para los motores de base de datos, memory.min protege el grupo de búferes para que no sea recuperado bajo presión en todo el sistema.

Configuración de la memoria según la función del servidor

La configuración adecuada de la memoria depende de la función del servidor. Aplicar la misma configuración a una base de datos y a un servidor web PHP perjudicará a uno de ellos.

Función del servidorvm.swappinessEstrategia OOMPolítica de Cgroup
Base de datos1–5Proteger (OOMScoreAdjust=-900)Utilizar memory.min para proteger el grupo de búferes
Servidor web/de aplicaciones10–20PredeterminadoLímite por grupo de trabajadores a través de memory.max
Trabajador en segundo plano60Eliminable (OOMScoreAdjust=+200)Limitación a través de memory.high
VPS multitenant60 (con zram)PredeterminadoAislamiento duro por inquilino mediante memory.max

Para MySQL y PostgreSQL, asigne entre el 50 % y el 70 % de la RAM disponible a innodb_buffer_pool_size, desactive las páginas enormes transparentes para reducir los picos de latencia y proteja el proceso con OOMScoreAdjust=-900 en el archivo de unidad de systemd.

Para PHP-FPM, dimensiona los grupos de trabajadores en función del uso real de memoria. Cada trabajador suele utilizar entre 30 y 100 MB. Divide la RAM asignada por el tamaño medio de los trabajadores para obtener un pm.max_children . Utilice memory.max en cgroups para limitar el grupo.

Para cargas de trabajo con gran volumen de escritura, establezca vm.dirty_ratio en torno al 10 % y vm.dirty_background_ratio al 3 %. Esto vacía las páginas sucias con mayor frecuencia, evitando grandes atascos de E/S.

Haga que el ajuste del kernel sea persistente guardando los parámetros en /etc/sysctl.d/90-memory.conf. Los ajustes aplicados en tiempo de ejecución se pierden al reiniciar el sistema.

Para ver un resumen de los valores recomendados por función:

ParámetroServidor web/de aplicacionesServidor de bases de datos
vm.swappiness10–201–5
vm.vfs_cache_pressure5050
vm.dirty_ratio15 %10 %
vm.min_free_kbytes6553665536
Protección OOMPredeterminadoOOMScoreAdjust=-1000

Si está ejecutando cargas de trabajo de alta densidad y necesita un servidor con el margen suficiente para aplicar estas políticas correctamente, vale la pena echar un vistazo a los servidores dedicados de FDC.

Blog

Destacados de la semana

Más artículos
Gestión de memoria en Linux: Swap, OOM Killer y Cgroups

Gestión de memoria en Linux: Swap, OOM Killer y Cgroups

Cómo funcionan juntos Linux swap, el OOM killer y cgroups - con ejemplos de configuración para bases de datos, servidores web y hosts VPS multi-tenant.

12 min de lectura - 31 de mayo de 2026

Guía de instalación de Prometheus y node_exporter

15 min de lectura - 29 de mayo de 2026

Más artículos