Optimización de Límites del Sistema (ulimit, limits.conf)
Introducción
Los límites de recursos del sistema en Linux controlan cuánto de un recurso dado puede consumir un proceso o usuario. Estos límites son críticos para la estabilidad, seguridad y rendimiento del sistema. Por defecto, las distribuciones Linux establecen límites conservadores que protegen el sistema del agotamiento de recursos pero a menudo restringen el rendimiento de aplicaciones de producción. Comprender y optimizar estos límites es esencial para ejecutar aplicaciones de alto rendimiento, bases de datos, servidores web y otros servicios intensivos en recursos.
Los dos mecanismos principales para gestionar límites de recursos en Linux son el comando ulimit (para límites temporales específicos del shell) y el archivo /etc/security/limits.conf (para límites persistentes específicos de usuario o grupo). La configuración inadecuada de estos límites puede llevar a problemas comunes de producción como "Too many open files", "Cannot fork" o errores "Out of processes" que pueden impactar severamente la disponibilidad de la aplicación.
Esta guía completa explicará los límites de recursos de Linux en profundidad, te mostrará cómo diagnosticar problemas relacionados con límites, demostrará técnicas de configuración adecuadas y proporcionará configuraciones optimizadas para varios casos de uso. Aprenderás cómo eliminar cuellos de botella de recursos y permitir que tus aplicaciones funcionen a su máximo potencial.
Comprendiendo los Límites de Recursos de Linux
¿Qué Son los Límites de Recursos?
Los límites de recursos previenen que usuarios o procesos individuales consuman recursos excesivos del sistema. Sirven dos propósitos:
- Protección del Sistema: Prevenir que procesos descontrolados bloqueen todo el sistema
- Asignación Justa de Recursos: Asegurar que múltiples usuarios o servicios compartan recursos equitativamente
Tipos de Límites
Linux proporciona dos categorías de límites:
- Límites Suaves: Límite actual aplicado por el kernel; puede ser aumentado por el usuario hasta el límite duro
- Límites Duros: Valor máximo que puede establecerse para límites suaves; solo puede ser elevado por root
Límites de Recursos Comunes
| Recurso | Descripción | Problema Común |
|---|---|---|
| nofile | Número de descriptores de archivo abiertos | "Too many open files" |
| nproc | Número de procesos | "Cannot fork" |
| stack | Tamaño de pila en KB | Bloqueos por desbordamiento de pila |
| memlock | Memoria bloqueada en KB | Problemas de rendimiento de base de datos |
| as | Espacio de direcciones (memoria virtual) | Fallos de asignación de memoria |
| cpu | Tiempo de CPU en segundos | Protección contra procesos descontrolados |
| fsize | Tamaño máximo de archivo | Fallos de escritura de archivo |
Verificando Límites Actuales
Usando el Comando ulimit
# Ver todos los límites actuales (suaves)
ulimit -a
# Ver todos los límites duros
ulimit -Ha
# Ver límites específicos
ulimit -n # Archivos abiertos
ulimit -u # Máximo de procesos
ulimit -l # Máxima memoria bloqueada
ulimit -s # Tamaño de pila
Salida de Ejemplo:
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 15738
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 15738
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
Verificando Límites Específicos de Procesos
# Ver límites para un proceso específico
cat /proc/$(pidof nginx)/limits
# Ver límites para shell actual
cat /proc/$$/limits
# Para un PID específico
cat /proc/12345/limits
Salida de Ejemplo:
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 15738 15738 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 15738 15738 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Identificando Problemas Relacionados con Límites
Mensajes de Error Comunes
# Monitorear logs del sistema en busca de errores de límites
tail -f /var/log/syslog | grep -i "too many\|cannot fork\|resource"
journalctl -f | grep -i "too many\|cannot fork"
# Errores comunes:
# "Too many open files"
# "Cannot allocate memory"
# "Cannot fork: Resource temporarily unavailable"
# "Too many processes"
Diagnosticando Problemas de Descriptores de Archivo
# Contar descriptores de archivo abiertos a nivel del sistema
cat /proc/sys/fs/file-nr
# Salida: 2048 0 4096
# ^usado ^libre ^máx
# Encontrar procesos usando más descriptores de archivo
lsof | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
# Contar FDs para un proceso específico
ls -l /proc/$(pidof nginx)/fd | wc -l
# Monitorear uso de FD en tiempo real
watch -n 1 'cat /proc/sys/fs/file-nr'
Diagnosticando Problemas de Límite de Procesos
# Verificar conteo actual de procesos por usuario
ps -eo user= | sort | uniq -c | sort -rn
# Verificar contra límites de usuario
su - username -c "ulimit -u"
# Monitorear fallos de creación de procesos
dmesg | grep -i "fork failed"
Benchmark Antes de la Optimización
Mediciones de Línea Base
# Probar límites de descriptores de archivo
# Crear script de prueba
cat > /tmp/fd-test.sh << 'EOF'
#!/bin/bash
count=0
while true; do
exec {fd}<> <(:)
((count++))
if [ $count -eq 1000 ]; then
echo "Successfully opened $count file descriptors"
fi
done
EOF
chmod +x /tmp/fd-test.sh
./tmp/fd-test.sh
# Con límites por defecto (1024), esto falla rápidamente:
# Error: ./tmp/fd-test.sh: line 4: <(:): Too many open files
Pruebas Específicas de Aplicación
# Prueba de concurrencia de servidor web (Nginx/Apache)
ab -n 10000 -c 5000 http://localhost/
# Resultado con límites por defecto:
# apr_socket_recv: Connection reset by peer (104)
# Completed requests: 3847
# Failed requests: 6153
# Prueba de conexión de base de datos
mysqlslap --concurrency=1000 --iterations=1 --auto-generate-sql
# Resultado con límites por defecto:
# Error: Can't create a new thread
# Connections established: 214/1000
Configuración Temporal de Límites con ulimit
Estableciendo Límites Temporales
# Estos cambios afectan solo la sesión actual del shell
# Aumentar límite de archivos abiertos
ulimit -n 65536
# Aumentar máximo de procesos
ulimit -u 32768
# Aumentar tamaño de pila a 16MB
ulimit -s 16384
# Establecer tamaño ilimitado de volcado de núcleo
ulimit -c unlimited
# Establecer múltiples límites
ulimit -n 65536 -u 32768 -l unlimited
Probando Cambios Temporales
# Establecer límite más alto
ulimit -n 65536
# Verificar
ulimit -n
# Salida: 65536
# Ejecutar tu aplicación y probar
./your-application
# Revertir (o simplemente salir del shell e iniciar uno nuevo)
ulimit -n 1024
Aplicando a Servicios en Ejecución
# Para servicios systemd, los límites deben establecerse en archivo de servicio
# Los cambios temporales de ulimit no afectan demonios ya en ejecución
# Ejemplo: Aumentar temporalmente límites para Nginx
systemctl edit nginx
# Agregar al archivo de override:
[Service]
LimitNOFILE=65536
LimitNPROC=32768
# Recargar y reiniciar
systemctl daemon-reload
systemctl restart nginx
Configuración Persistente con limits.conf
Comprendiendo /etc/security/limits.conf
El archivo de configuración principal para límites de recursos persistentes:
# Ver configuración actual
cat /etc/security/limits.conf
# Formato:
# <domain> <type> <item> <value>
#
# domain: nombre de usuario, @nombre_de_grupo, o *
# type: soft, hard, o -
# item: recurso (nofile, nproc, etc.)
# value: valor límite
Ejemplos de Configuración Básica
# Editar configuración de límites
vim /etc/security/limits.conf
# Agregar al final:
# Aumentar descriptores de archivo para todos los usuarios
* soft nofile 65536
* hard nofile 65536
# Aumentar procesos para todos los usuarios
* soft nproc 32768
* hard nproc 32768
# Establecer volcados de núcleo ilimitados
* soft core unlimited
* hard core unlimited
# Aumentar tamaño de pila
* soft stack 16384
* hard stack 32768
Configuración Específica de Usuario
# Límites para usuario específico
username soft nofile 100000
username hard nofile 100000
username soft nproc 50000
username hard nproc 50000
# Límites para miembros de grupo
@developers soft nofile 65536
@developers hard nofile 65536
# Usuario de base de datos necesita gran memoria bloqueada para rendimiento
mysql soft memlock unlimited
mysql hard memlock unlimited
mysql soft nofile 65536
mysql hard nofile 65536
Usando el Directorio limits.d
Los sistemas modernos soportan /etc/security/limits.d/ para configuración modular:
# Crear archivo de límites específico de aplicación
cat > /etc/security/limits.d/99-webserver.conf << 'EOF'
# Límites de recursos del servidor web
nginx soft nofile 100000
nginx hard nofile 100000
nginx soft nproc 32768
nginx hard nproc 32768
www-data soft nofile 100000
www-data hard nofile 100000
www-data soft nproc 32768
www-data hard nproc 32768
EOF
Aplicando Cambios
# Los cambios surten efecto solo para NUEVAS sesiones
# Las sesiones existentes mantienen sus límites originales
# Probar con nueva sesión
su - username
ulimit -a
# Para servicios, se requiere reinicio
systemctl restart nginx
systemctl restart mysql
# Verificar límites para proceso en ejecución
cat /proc/$(pidof nginx)/limits
Configuración de Límites a Nivel del Sistema
Límites a Nivel de Kernel
# Número máximo de descriptores de archivo a nivel del sistema
sysctl fs.file-max
# Por defecto: típicamente 98304 o similar
# Aumentar límite de descriptores de archivo a nivel del sistema
sysctl -w fs.file-max=2097152
# Hacer persistente
echo "fs.file-max = 2097152" >> /etc/sysctl.conf
# O usar sysctl.d
cat > /etc/sysctl.d/99-limits.conf << 'EOF'
# Límites de recursos a nivel del sistema
fs.file-max = 2097152
fs.inode-max = 2097152
fs.aio-max-nr = 1048576
kernel.pid_max = 4194304
vm.max_map_count = 262144
EOF
sysctl -p /etc/sysctl.d/99-limits.conf
Configuración de PAM
Asegurar que PAM está configurado para aplicar límites:
# Verificar configuración de PAM
grep -r pam_limits /etc/pam.d/
# Debería ver líneas como:
# session required pam_limits.so
# Si falta, agregar a /etc/pam.d/common-session o archivos de servicio específicos:
echo "session required pam_limits.so" >> /etc/pam.d/common-session
Límites de Servicios Systemd
Configurando Límites de Servicios
Los servicios systemd tienen su propio mecanismo de límites:
# Ver límites actuales para servicio
systemctl show nginx | grep -i limit
# Editar archivo de servicio
systemctl edit nginx
# Agregar directivas de límite
[Service]
LimitNOFILE=100000
LimitNPROC=32768
LimitMEMLOCK=infinity
LimitCORE=infinity
# Directivas de límite disponibles:
# LimitCPU, LimitFSIZE, LimitDATA, LimitSTACK, LimitCORE
# LimitRSS, LimitNOFILE, LimitAS, LimitNPROC, LimitMEMLOCK
# LimitLOCKS, LimitSIGPENDING, LimitMSGQUEUE, LimitNICE, LimitRTPRIO
Ejemplo Completo de Configuración de Servicio
# Crear archivo de override para Nginx
mkdir -p /etc/systemd/system/nginx.service.d
cat > /etc/systemd/system/nginx.service.d/limits.conf << 'EOF'
[Service]
# Límites de descriptores de archivo
LimitNOFILE=100000
# Límites de procesos
LimitNPROC=32768
# Volcados de núcleo para depuración
LimitCORE=infinity
# Límites de memoria (si es necesario)
# LimitAS=8G
# LimitRSS=4G
# Tamaño de pila
LimitSTACK=16M
EOF
# Recargar y reiniciar
systemctl daemon-reload
systemctl restart nginx
# Verificar
systemctl show nginx | grep -E "LimitNOFILE|LimitNPROC"
cat /proc/$(pidof nginx)/limits
Configuraciones Optimizadas por Caso de Uso
Servidor Web de Alto Rendimiento (Nginx/Apache)
# /etc/security/limits.d/99-webserver.conf
cat > /etc/security/limits.d/99-webserver.conf << 'EOF'
# Límites de usuario de servidor web
nginx soft nofile 100000
nginx hard nofile 100000
nginx soft nproc 32768
nginx hard nproc 32768
nginx soft memlock unlimited
nginx hard memlock unlimited
www-data soft nofile 100000
www-data hard nofile 100000
www-data soft nproc 32768
www-data hard nproc 32768
EOF
# Configuraciones a nivel del sistema
cat > /etc/sysctl.d/99-webserver.conf << 'EOF'
fs.file-max = 2097152
fs.inode-max = 2097152
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192
EOF
sysctl -p /etc/sysctl.d/99-webserver.conf
# Límites de servicio systemd
cat > /etc/systemd/system/nginx.service.d/limits.conf << 'EOF'
[Service]
LimitNOFILE=100000
LimitNPROC=32768
LimitMEMLOCK=infinity
EOF
systemctl daemon-reload
systemctl restart nginx
Resultados de Rendimiento:
Antes de la optimización:
ab -n 100000 -c 10000 http://localhost/
# Failed requests: 6,234 (Too many open files)
# Requests per second: 8,452
Después de la optimización:
ab -n 100000 -c 10000 http://localhost/
# Failed requests: 0
# Requests per second: 43,127 (mejora 5x)
Servidor de Base de Datos (MySQL/PostgreSQL)
# /etc/security/limits.d/99-database.conf
cat > /etc/security/limits.d/99-database.conf << 'EOF'
# Límites de usuario MySQL
mysql soft nofile 65536
mysql hard nofile 65536
mysql soft nproc 32768
mysql hard nproc 32768
mysql soft memlock unlimited
mysql hard memlock unlimited
mysql soft stack 16384
mysql hard stack 32768
# Límites de usuario PostgreSQL
postgres soft nofile 65536
postgres hard nofile 65536
postgres soft nproc 32768
postgres hard nproc 32768
postgres soft memlock unlimited
postgres hard memlock unlimited
EOF
# Configuraciones de kernel a nivel del sistema
cat > /etc/sysctl.d/99-database.conf << 'EOF'
fs.file-max = 2097152
fs.aio-max-nr = 1048576
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
vm.max_map_count = 262144
EOF
sysctl -p /etc/sysctl.d/99-database.conf
# Servicio systemd de MySQL
cat > /etc/systemd/system/mysql.service.d/limits.conf << 'EOF'
[Service]
LimitNOFILE=65536
LimitNPROC=32768
LimitMEMLOCK=infinity
LimitSTACK=16M
EOF
systemctl daemon-reload
systemctl restart mysql
Resultados de Rendimiento:
Antes de la optimización:
mysqlslap --concurrency=500 --iterations=10 --auto-generate-sql
# Failed connections: 147
# Queries per second: 3,842
Después de la optimización:
mysqlslap --concurrency=500 --iterations=10 --auto-generate-sql
# Failed connections: 0
# Queries per second: 12,634 (mejora 3.3x)
Servidor de Aplicaciones (Node.js, Python, Ruby)
# /etc/security/limits.d/99-appserver.conf
cat > /etc/security/limits.d/99-appserver.conf << 'EOF'
# Límites de servidor de aplicaciones
appuser soft nofile 65536
appuser hard nofile 65536
appuser soft nproc 16384
appuser hard nproc 16384
appuser soft stack 16384
appuser hard stack 32768
# Específico de Node.js
node soft nofile 65536
node hard nofile 65536
node soft nproc 32768
node hard nproc 32768
EOF
# Servicio systemd para aplicación Node.js (ejemplo con PM2)
cat > /etc/systemd/system/nodeapp.service.d/limits.conf << 'EOF'
[Service]
LimitNOFILE=65536
LimitNPROC=16384
LimitSTACK=16M
EOF
systemctl daemon-reload
systemctl restart nodeapp
Host de Contenedores (Docker/Kubernetes)
# /etc/security/limits.d/99-container-host.conf
cat > /etc/security/limits.d/99-container-host.conf << 'EOF'
# Límites de runtime de contenedores
root soft nofile 1048576
root hard nofile 1048576
root soft nproc unlimited
root hard nproc unlimited
root soft memlock unlimited
root hard memlock unlimited
# Todos los usuarios (para procesos de contenedores)
* soft nofile 1048576
* hard nofile 1048576
* soft nproc unlimited
* hard nproc unlimited
EOF
# Configuraciones a nivel del sistema para contenedores
cat > /etc/sysctl.d/99-containers.conf << 'EOF'
fs.file-max = 2097152
fs.inode-max = 2097152
fs.aio-max-nr = 1048576
kernel.pid_max = 4194304
vm.max_map_count = 262144
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl -p /etc/sysctl.d/99-containers.conf
# Configuración de demonio Docker
cat > /etc/docker/daemon.json << 'EOF'
{
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 65536,
"Soft": 65536
},
"nproc": {
"Name": "nproc",
"Hard": 32768,
"Soft": 32768
}
}
}
EOF
systemctl restart docker
Pruebas y Validación
Script Completo de Pruebas
#!/bin/bash
# Guardar como /usr/local/bin/test-limits.sh
echo "=== Suite de Pruebas de Límites de Recursos ==="
echo
# Prueba 1: Límite de descriptores de archivo
echo "Prueba 1: Límite de Descriptores de Archivo"
ulimit -n
echo "Abriendo 50000 descriptores de archivo..."
count=0
for i in {1..50000}; do
exec {fd}<> <(:) 2>/dev/null && ((count++))
done
echo "Abiertos exitosamente: $count descriptores de archivo"
echo
# Prueba 2: Límites de procesos
echo "Prueba 2: Límite de Procesos"
ulimit -u
echo "Conteo actual de procesos:"
ps -u $(whoami) | wc -l
# Prueba 3: Límites de bloqueo de memoria
echo "Prueba 3: Límite de Bloqueo de Memoria"
ulimit -l
echo "Límite de memoria bloqueada: $(ulimit -l) KB"
echo
# Prueba 4: Tamaño de pila
echo "Prueba 4: Tamaño de Pila"
ulimit -s
echo "Tamaño de pila: $(ulimit -s) KB"
echo
# Prueba 5: Verificar límites a nivel del sistema
echo "Prueba 5: Límites a Nivel del Sistema"
echo "Máximo de descriptores de archivo: $(cat /proc/sys/fs/file-max)"
echo "Archivos abiertos actuales: $(cat /proc/sys/fs/file-nr | awk '{print $1}')"
echo "Máximo de procesos: $(cat /proc/sys/kernel/pid_max)"
echo
# Prueba 6: Límites de servicio (si se ejecuta como servicio)
if [ -n "$1" ]; then
echo "Prueba 6: Límites de Servicio para $1"
systemctl show $1 | grep ^Limit
fi
chmod +x /usr/local/bin/test-limits.sh
./usr/local/bin/test-limits.sh nginx
Pruebas de Carga Después de la Optimización
# Prueba de carga de servidor web
echo "Probando servidor web con límites optimizados..."
wrk -t 12 -c 10000 -d 60s --latency http://localhost/
# Antes de la optimización:
# Errors: 4,234 connect errors
# Requests/sec: 8,452
# Latency: 1.2s average
# Después de la optimización:
# Errors: 0
# Requests/sec: 43,127
# Latency: 232ms average
Monitoreando Uso de Límites
#!/bin/bash
# Script de monitoreo continuo de límites
while true; do
clear
echo "=== Monitor de Límites de Recursos ==="
echo "Hora: $(date)"
echo
# Uso de FD a nivel del sistema
echo "Descriptores de Archivo del Sistema:"
cat /proc/sys/fs/file-nr | awk '{printf "Usado: %s | Libre: %s | Máx: %s\n", $1, $2, $3}'
echo
# Uso de FD por proceso (top 5)
echo "Top 5 Procesos por Descriptores de Archivo:"
for pid in $(ps aux | awk '{print $2}' | tail -n +2 | head -5); do
if [ -d /proc/$pid ]; then
cmd=$(ps -p $pid -o comm=)
fds=$(ls /proc/$pid/fd 2>/dev/null | wc -l)
echo "$cmd (PID $pid): $fds FDs"
fi
done
echo
# Conteo de procesos por usuario
echo "Conteo de Procesos por Usuario:"
ps -eo user= | sort | uniq -c | sort -rn | head -5
echo
sleep 5
done
Solución de Problemas Comunes
Problema 1: Error "Too Many Open Files"
# Diagnosticar
dmesg | grep -i "too many open files"
journalctl -xe | grep -i "too many"
# Verificar uso actual vs límites
cat /proc/sys/fs/file-nr
ulimit -n
# Solución 1: Aumentar límites de usuario
cat >> /etc/security/limits.d/99-custom.conf << 'EOF'
* soft nofile 65536
* hard nofile 65536
EOF
# Solución 2: Aumentar límite a nivel del sistema
sysctl -w fs.file-max=2097152
echo "fs.file-max = 2097152" >> /etc/sysctl.conf
# Solución 3: Para servicio systemd
systemctl edit myservice
# Agregar:
# [Service]
# LimitNOFILE=65536
# Reiniciar y verificar
systemctl daemon-reload
systemctl restart myservice
cat /proc/$(pidof myservice)/limits | grep "Max open files"
Problema 2: "Cannot Fork: Resource Temporarily Unavailable"
# Diagnosticar
ulimit -u
ps aux | wc -l
cat /proc/sys/kernel/pid_max
# Verificar conteo de procesos por usuario
ps -eo user= | sort | uniq -c | sort -rn
# Solución 1: Aumentar límite de procesos de usuario
cat >> /etc/security/limits.d/99-custom.conf << 'EOF'
* soft nproc 32768
* hard nproc 32768
EOF
# Solución 2: Aumentar PID máximo del sistema
sysctl -w kernel.pid_max=4194304
echo "kernel.pid_max = 4194304" >> /etc/sysctl.conf
# Solución 3: Para servicio systemd
systemctl edit myservice
# Agregar:
# [Service]
# LimitNPROC=32768
systemctl daemon-reload
systemctl restart myservice
Problema 3: Límites No Aplicados
# Verificar configuración de PAM
grep -r pam_limits /etc/pam.d/
# Debería contener:
# session required pam_limits.so
# Si falta, agregarlo:
echo "session required pam_limits.so" >> /etc/pam.d/common-session
# Verificar que los límites están cargados
ulimit -a
# Para servicios, verificar límites de systemd
systemctl show nginx | grep Limit
# Probar con sesión nueva
su - username
ulimit -a
Problema 4: Límites de Servicio Systemd No Funcionan
# Verificar que existe directorio de override
ls -la /etc/systemd/system/nginx.service.d/
# Verificar sintaxis de archivo de servicio
systemctl cat nginx
# Recargar después de cambios
systemctl daemon-reload
# Verificar que los límites están aplicados
systemctl show nginx | grep Limit
# Verificar límites reales del proceso
cat /proc/$(pidof nginx)/limits
# Si aún no funciona, verificar DefaultLimitNOFILE en system.conf
grep DefaultLimit /etc/systemd/system.conf
grep DefaultLimit /etc/systemd/user.conf
Monitoreo y Alertas
Script de Monitoreo Automatizado
#!/bin/bash
# /usr/local/bin/monitor-limits.sh
LOG_FILE="/var/log/resource-limits.log"
ALERT_EMAIL="[email protected]"
# Umbrales
FD_THRESHOLD=80 # Alertar al 80% de uso
PROC_THRESHOLD=80
# Obtener uso actual
CURRENT_FD=$(cat /proc/sys/fs/file-nr | awk '{print $1}')
MAX_FD=$(cat /proc/sys/fs/file-max)
FD_PERCENT=$(awk "BEGIN {printf \"%.0f\", ($CURRENT_FD/$MAX_FD)*100}")
# Verificar y alertar
if [ $FD_PERCENT -gt $FD_THRESHOLD ]; then
MSG="ADVERTENCIA: Uso de descriptores de archivo al ${FD_PERCENT}% (${CURRENT_FD}/${MAX_FD})"
echo "$(date): $MSG" >> $LOG_FILE
echo "$MSG" | mail -s "Resource Limit Alert" $ALERT_EMAIL
fi
# Registrar estado actual
echo "$(date): Uso de FD: ${FD_PERCENT}%, Procesos: $(ps aux | wc -l)" >> $LOG_FILE
chmod +x /usr/local/bin/monitor-limits.sh
# Agregar a crontab
crontab -e
# */5 * * * * /usr/local/bin/monitor-limits.sh
Mejores Prácticas
1. Comenzar con Valores Conservadores
# No establecer inmediatamente al máximo
# Comenzar con aumentos moderados y probar
# Optimización inicial (segura para la mayoría de sistemas)
* soft nofile 65536
* hard nofile 65536
* soft nproc 16384
* hard nproc 16384
2. Monitorear Antes y Después
# Siempre establecer línea base
# Antes de cambios:
cat /proc/sys/fs/file-nr > /tmp/baseline-fd.txt
ps aux | wc -l > /tmp/baseline-proc.txt
# Después de cambios:
# Comparar y verificar mejora
3. Documentar Todos los Cambios
# Agregar comentarios a archivos de configuración
cat > /etc/security/limits.d/99-custom.conf << 'EOF'
# Optimización de límites de recursos
# Fecha: 2026-01-11
# Autor: Equipo Admin
# Razón: Aplicación web de alto tráfico requiere descriptores de archivo aumentados
# Probado: Manejó exitosamente 10,000 conexiones concurrentes
* soft nofile 65536
* hard nofile 65536
EOF
4. Usar Configuración Modular
# Separar límites por servicio/propósito
/etc/security/limits.d/90-webserver.conf
/etc/security/limits.d/91-database.conf
/etc/security/limits.d/92-application.conf
/etc/security/limits.d/99-general.conf
5. Probar Primero en Staging
# Nunca aplicar directamente a producción
# Probar configuración en entorno de staging
# Monitorear por 24-48 horas antes del despliegue en producción
Conclusión
La configuración adecuada de límites de recursos del sistema es fundamental para ejecutar servidores Linux de alto rendimiento. Las optimizaciones cubiertas en esta guía pueden eliminar cuellos de botella comunes y mejorar dramáticamente el rendimiento de la aplicación:
Mejoras Típicas:
- Capacidad de conexión: aumento de 5-10x
- Estabilidad de aplicación: Elimina errores de agotamiento de recursos
- Rendimiento de base de datos: 2-4x más conexiones concurrentes
- Densidad de contenedores: 50-100% más contenedores por host
Conclusiones Clave:
- Los límites por defecto son demasiado bajos para cargas de trabajo de producción
- Múltiples capas de configuración deben alinearse (ulimit, limits.conf, sysctl, systemd)
- Diferentes aplicaciones requieren diferentes perfiles de límites
- El monitoreo es esencial para detectar y prevenir problemas relacionados con límites
- Probar exhaustivamente antes de desplegar en producción
Jerarquía de Configuración (orden de precedencia):
- Límites de servicio systemd (LimitNOFILE, etc.)
- /etc/security/limits.conf y limits.d/
- Comandos ulimit (temporales)
- Límites de kernel a nivel del sistema (sysctl)
Al implementar estas optimizaciones de límites de recursos de manera sistemática y monitorear su impacto, puedes asegurar que tus aplicaciones funcionen con el máximo rendimiento sin encontrar errores frustrantes relacionados con límites. Recuerda adaptar las configuraciones a tus requisitos específicos de carga de trabajo y monitorear continuamente el uso de recursos para ajustar los límites a medida que tu aplicación escala.


