Linux Namespaces y Cgroups: Guía de Fundamentos de Tecnología de Contenedores
Introducción
Los namespaces de Linux y los grupos de control (cgroups) representan las tecnologías fundamentales del kernel que habilitan la contenedorización, el aislamiento de recursos y la computación multi-inquilino que impulsan la infraestructura moderna en la nube. Aunque Docker, Kubernetes y otras plataformas de contenedores proporcionan abstracciones fáciles de usar, comprender los mecanismos subyacentes de namespaces y cgroups distingue a los usuarios de plataformas de los ingenieros de infraestructura capaces de construir soluciones de aislamiento personalizadas, resolver problemas complejos de contenedores y arquitectar sistemas multi-inquilino seguros.
Los namespaces proporcionan aislamiento de procesos creando vistas separadas de los recursos del sistema—los procesos en diferentes namespaces no pueden ver ni interactuar con los recursos de los demás, permitiendo que las aplicaciones se ejecuten con pilas de red independientes, jerarquías de sistemas de archivos, árboles de procesos y mapeos de usuario/grupo. Este aislamiento forma el límite de seguridad entre contenedores, previniendo la escalada de privilegios y la interferencia de recursos.
Los Cgroups (grupos de control) habilitan la contabilidad, limitación y priorización de recursos—controlando cuánta CPU, memoria, E/S de disco y ancho de banda de red pueden consumir los procesos. Combinados con namespaces, los cgroups proporcionan el marco completo de aislamiento y gestión de recursos del que depende la contenedorización.
Las principales empresas tecnológicas, incluyendo Google (que originó los cgroups), Facebook, Netflix y Amazon, aprovechan extensivamente los namespaces y cgroups más allá de la simple contenedorización—implementando arquitecturas multi-inquilino personalizadas, entornos de sandbox seguros, aislamiento de recursos para infraestructura compartida y mecanismos sofisticados de calidad de servicio.
Esta guía completa explora implementaciones de namespaces y cgroups de nivel empresarial, cubriendo conceptos arquitectónicos, aplicaciones prácticas, configuraciones avanzadas, optimización de rendimiento, consideraciones de seguridad y metodologías de resolución de problemas esenciales para construir plataformas de contenedores de producción y sistemas con gestión de recursos.
Teoría y Conceptos Fundamentales
Arquitectura de Namespaces de Linux
Linux proporciona siete tipos de namespaces, cada uno aislando recursos específicos del sistema:
PID Namespace (ID de Proceso): Aísla el espacio de números de ID de proceso. Los procesos en diferentes namespaces PID pueden tener PIDs idénticos. Permite que el proceso init del contenedor sea PID 1 dentro de su namespace mientras tiene un PID diferente en el namespace del host. Esencial para el aislamiento del árbol de procesos y prevenir señales de proceso entre contenedores.
Network Namespace (NET): Aísla la pila de red incluyendo interfaces, tablas de enrutamiento, reglas de firewall y sockets. Cada namespace de red tiene una interfaz loopback independiente, direcciones IP, configuración de enrutamiento y reglas de iptables. Permite que los contenedores tengan configuraciones de red aisladas sin afectar al host u otros contenedores.
Mount Namespace (MNT): Aísla los puntos de montaje del sistema de archivos. Los procesos en diferentes namespaces de montaje ven jerarquías de sistemas de archivos diferentes. Permite que los contenedores tengan sistemas de archivos raíz independientes sin requerir chroot. Soporta escenarios complejos como volúmenes compartidos entre contenedores específicos mientras mantiene el aislamiento general.
UTS Namespace (Unix Timesharing System): Aísla el nombre de host y el nombre de dominio. Permite que cada contenedor tenga un nombre de host único sin afectar al host u otros contenedores. Útil para sistemas distribuidos donde la identificación por nombre de host es importante.
IPC Namespace (Comunicación Inter-Proceso): Aísla los recursos IPC de System V (colas de mensajes, semáforos, segmentos de memoria compartida). Previene que los procesos en diferentes contenedores interfieran con los mecanismos IPC de los demás.
User Namespace (USER): Mapea IDs de usuario y grupo entre el namespace y el host. Permite que el usuario root dentro del contenedor sea un usuario sin privilegios en el sistema host. Crítico para la seguridad—permite que los contenedores ejecuten procesos como root internamente mientras previenen la escalada de privilegios en el host. El namespace más complejo con implicaciones de seguridad.
Cgroup Namespace: Virtualiza la vista de /proc/self/cgroup y el directorio raíz de cgroup. Previene que los procesos vean o modifiquen cgroups padres. Mejora la seguridad del contenedor limitando la visibilidad de la jerarquía de cgroups.
Arquitectura de Cgroups
Los Cgroups organizan procesos en grupos jerárquicos con controles de recursos:
Cgroup v1 (Legacy): Múltiples jerarquías independientes, una por controlador de recursos (cpu, memory, blkio, etc.). Gestión compleja pero flexible. Todavía ampliamente usado en sistemas de producción.
Cgroup v2 (Unificado): Jerarquía unificada única con todos los controladores. Gestión simplificada y rendimiento mejorado. Por defecto en distribuciones modernas pero adopción en curso.
Controladores de Recursos:
Controlador CPU: Limita el tiempo de CPU disponible para los procesos. Implementa:
- CPU shares: Asignación proporcional de CPU (por defecto 1024 shares)
- CPU quotas: Límites duros en tiempo de CPU (microsegundos por período)
- CPU sets: Fijar procesos a núcleos de CPU específicos
Controlador Memory: Limita el uso de memoria incluyendo RAM y swap. Características:
- Límites de memoria (duros y suaves)
- Control de OOM (Out of Memory) y notificación
- Monitoreo de presión de memoria
- Contabilidad y límites de swap
Controlador Block I/O: Controla el ancho de banda de E/S de disco y IOPS. Soporta:
- Peso de E/S (asignación proporcional)
- Límites de E/S (IOPS y ancho de banda)
- Controles específicos de dispositivo
Controlador Network: Limita el ancho de banda de red y tasas de paquetes. Menos maduro que otros controladores.
Controlador PIDs: Limita el número de procesos/hilos creados. Previene fork bombs y agotamiento de recursos.
Pila de Tecnología de Contenedores
Comprendiendo cómo se apilan las tecnologías:
┌─────────────────────────────────┐
│ Orquestación de Contenedores │ Kubernetes, Docker Swarm
│ (Kubernetes, Swarm) │
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ Runtime de Contenedores │ Docker, containerd, CRI-O
│ (Docker, containerd) │
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ Runtime de Bajo Nivel │ runc, crun
│ (runc, crun) │
└─────────────────────────────────┘
↓
┌─────────────────────────────────┐
│ Características del Kernel │ Namespaces, Cgroups
│ (Namespaces, Cgroups) │
└─────────────────────────────────┘
Todas las plataformas de contenedores finalmente usan namespaces y cgroups, independientemente del nivel de abstracción.
Requisitos Previos
Requisitos de Hardware
Especificaciones Mínimas del Sistema:
- 2 núcleos de CPU (4+ recomendados para pruebas)
- 4GB de RAM mínimo (8GB+ para escenarios complejos)
- 20GB de espacio libre en disco
- Kernel de Linux 3.10+ (4.x+ recomendado para soporte completo de características)
Verificación de Soporte de Namespaces:
# Verificar soporte de namespaces
ls /proc/self/ns/
# Debería mostrar: cgroup, ipc, mnt, net, pid, user, uts
# Verificar versión de cgroup
stat -fc %T /sys/fs/cgroup
# cgroup2fs = cgroup v2
# tmpfs = cgroup v1
Requisitos de Software
Herramientas Requeridas:
# RHEL/Rocky
dnf install -y util-linux iproute bridge-utils nsenter unshare
# Ubuntu/Debian
apt install -y util-linux iproute2 bridge-utils
# Instalar herramientas de cgroup
dnf install -y libcgroup libcgroup-tools # RHEL/Rocky
apt install -y cgroup-tools # Ubuntu/Debian
Configuración del Kernel
Verificar características requeridas del kernel:
# Verificar soporte de namespaces
grep -E "CONFIG_.*_NS" /boot/config-$(uname -r)
# Verificar soporte de cgroups
grep -E "CONFIG_CGROUP" /boot/config-$(uname -r)
# Opciones requeridas (deberían ser =y):
# CONFIG_NAMESPACES=y
# CONFIG_UTS_NS=y
# CONFIG_IPC_NS=y
# CONFIG_PID_NS=y
# CONFIG_NET_NS=y
# CONFIG_CGROUPS=y
# CONFIG_MEMCG=y
# CONFIG_CGROUP_SCHED=y
Habilitar namespaces de usuario (si están deshabilitados):
# Verificar si está habilitado
sysctl kernel.unprivileged_userns_clone
# Habilitar (RHEL/Rocky/Debian)
echo "kernel.unprivileged_userns_clone=1" >> /etc/sysctl.d/99-userns.conf
sysctl -p /etc/sysctl.d/99-userns.conf
Configuración Avanzada
Exploración de PID Namespace
Creando PID Namespace Aislado:
# Crear PID namespace con nuevo árbol de procesos
unshare --pid --fork --mount-proc bash
# Dentro del nuevo namespace
ps aux
# Muestra solo los procesos en este namespace
# El proceso es PID 1 en el namespace
echo $$
# Salir del namespace
exit
Creación Programática de PID Namespace:
// pid_namespace_demo.c
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
static int child_func(void *arg) {
printf("PID hijo en namespace: %d\n", getpid());
printf("PID padre del hijo: %d\n", getppid());
sleep(5);
return 0;
}
#define STACK_SIZE (1024 * 1024)
static char child_stack[STACK_SIZE];
int main() {
printf("PID padre: %d\n", getpid());
pid_t child_pid = clone(child_func,
child_stack + STACK_SIZE,
CLONE_NEWPID | SIGCHLD,
NULL);
printf("PID hijo en namespace padre: %d\n", child_pid);
waitpid(child_pid, NULL, 0);
return 0;
}
Compilar y ejecutar:
gcc -o pid_ns_demo pid_namespace_demo.c
./pid_ns_demo
Configuración de Network Namespace
Crear Pila de Red Aislada:
# Crear network namespace
ip netns add isolated_net
# Listar namespaces
ip netns list
# Ejecutar comando en namespace
ip netns exec isolated_net ip addr
# Muestra solo interfaz loopback
# Crear par veth conectando namespaces
ip link add veth0 type veth peer name veth1
# Mover un extremo al namespace
ip link set veth1 netns isolated_net
# Configurar lado del host
ip addr add 192.168.100.1/24 dev veth0
ip link set veth0 up
# Configurar lado del namespace
ip netns exec isolated_net ip addr add 192.168.100.2/24 dev veth1
ip netns exec isolated_net ip link set veth1 up
ip netns exec isolated_net ip link set lo up
# Probar conectividad
ip netns exec isolated_net ping -c 3 192.168.100.1
# Agregar ruta por defecto en namespace
ip netns exec isolated_net ip route add default via 192.168.100.1
# Habilitar NAT para conectividad del namespace
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
Network Namespace con Bridge:
# Crear bridge
ip link add br0 type bridge
ip link set br0 up
ip addr add 192.168.200.1/24 dev br0
# Crear múltiples namespaces conectados al bridge
for i in {1..3}; do
# Crear namespace
ip netns add container${i}
# Crear par veth
ip link add veth${i}-host type veth peer name veth${i}-cont
# Adjuntar lado del host al bridge
ip link set veth${i}-host master br0
ip link set veth${i}-host up
# Mover lado del contenedor al namespace
ip link set veth${i}-cont netns container${i}
# Configurar namespace
ip netns exec container${i} ip link set lo up
ip netns exec container${i} ip link set veth${i}-cont up
ip netns exec container${i} ip addr add 192.168.200.${i}1/24 dev veth${i}-cont
ip netns exec container${i} ip route add default via 192.168.200.1
done
# Probar conectividad entre namespaces
ip netns exec container1 ping -c 3 192.168.200.21
ip netns exec container2 ping -c 3 192.168.200.31
Configuración de Mount Namespace
Jerarquía de Sistema de Archivos Aislada:
# Crear mount namespace con /tmp aislado
unshare --mount bash
# Los cambios solo afectan a este namespace
mount -t tmpfs tmpfs /tmp
df -h /tmp
# En otra terminal, /tmp permanece sin cambios
df -h /tmp
Sistema de Archivos Raíz Estilo Contenedor:
#!/bin/bash
# container_rootfs.sh - Crear contenedor con rootfs aislado
ROOTFS="/var/lib/containers/rootfs"
# Preparar rootfs mínimo (simplificado)
mkdir -p ${ROOTFS}/{bin,lib,lib64,proc,sys,dev,etc,root}
# Copiar binarios esenciales
cp /bin/bash /bin/ls /bin/cat ${ROOTFS}/bin/
# Copiar bibliotecas requeridas
ldd /bin/bash | grep -o '/lib[^ ]*' | xargs -I {} cp {} ${ROOTFS}/lib64/
ldd /bin/ls | grep -o '/lib[^ ]*' | xargs -I {} cp {} ${ROOTFS}/lib64/
# Crear contenedor con mount namespace aislado
unshare --mount --fork bash -c "
mount --bind ${ROOTFS} ${ROOTFS}
mount --make-private ${ROOTFS}
cd ${ROOTFS}
mkdir -p old_root
pivot_root . old_root
umount -l old_root
rmdir old_root
mount -t proc proc /proc
mount -t sysfs sys /sys
exec /bin/bash
"
User Namespace para Contenedores sin Privilegios
Mapear UID/GID en Namespace:
# Crear mapeo de user namespace
unshare --user --map-root-user bash
# Dentro del namespace, el proceso aparece como root
id
# uid=0(root) gid=0(root) groups=0(root)
# Pero fuera del namespace, ejecutándose como usuario original
# Verificar desde otra terminal:
# ps aux | grep bash
Mapeo Personalizado de UID/GID:
# Ejemplo de mapeo avanzado
unshare --user bash
# En otra terminal, encontrar PID
PID=$(pgrep -f "unshare --user")
# Crear mapeo personalizado
# Mapear UID 0-999 del namespace a UID 100000-100999 del host
echo "0 100000 1000" > /proc/${PID}/uid_map
echo "0 100000 1000" > /proc/${PID}/gid_map
# Requerido para escribir en los mapas
echo "deny" > /proc/${PID}/setgroups
Configuración de Cgroups v2
Habilitar Cgroup v2 (si no es por defecto):
# Verificar versión actual
mount | grep cgroup
# Habilitar cgroup v2 vía línea de comandos del kernel
# Editar /etc/default/grub
GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=1"
# Actualizar grub
grub2-mkconfig -o /boot/grub2/grub.cfg
reboot
Crear Jerarquía de Cgroup:
# Jerarquía unificada de Cgroup v2
CGROUP_ROOT="/sys/fs/cgroup"
# Crear cgroup para aplicación de prueba
mkdir ${CGROUP_ROOT}/test_app
# Habilitar controladores
echo "+cpu +memory +io +pids" > ${CGROUP_ROOT}/cgroup.subtree_control
echo "+cpu +memory +io +pids" > ${CGROUP_ROOT}/test_app/cgroup.subtree_control
# Establecer límites de recursos
echo "50000 100000" > ${CGROUP_ROOT}/test_app/cpu.max # 50ms por 100ms (50% CPU)
echo "512M" > ${CGROUP_ROOT}/test_app/memory.max
echo "100" > ${CGROUP_ROOT}/test_app/pids.max
# Agregar proceso al cgroup
echo $$ > ${CGROUP_ROOT}/test_app/cgroup.procs
# Verificar colocación
cat /proc/self/cgroup
# Probar límite de CPU
dd if=/dev/zero of=/dev/null & # Debería usar solo ~50% CPU
Configuración de Cgroups v1
Control de CPU:
# Crear cgroup de CPU
mkdir /sys/fs/cgroup/cpu/limited_cpu
# Establecer CPU shares (asignación proporcional)
echo 512 > /sys/fs/cgroup/cpu/limited_cpu/cpu.shares # 50% del valor por defecto 1024
# Establecer cuota de CPU (límite duro)
echo 50000 > /sys/fs/cgroup/cpu/limited_cpu/cpu.cfs_quota_us # 50ms
echo 100000 > /sys/fs/cgroup/cpu/limited_cpu/cpu.cfs_period_us # por 100ms
# Agregar proceso
echo $$ > /sys/fs/cgroup/cpu/limited_cpu/tasks
Control de Memoria:
# Crear cgroup de memoria
mkdir /sys/fs/cgroup/memory/limited_mem
# Establecer límite de memoria
echo 512M > /sys/fs/cgroup/memory/limited_mem/memory.limit_in_bytes
# Establecer límite de swap
echo 256M > /sys/fs/cgroup/memory/limited_mem/memory.memsw.limit_in_bytes
# Habilitar notificación OOM
echo 1 > /sys/fs/cgroup/memory/limited_mem/memory.oom_control
# Agregar proceso
echo $$ > /sys/fs/cgroup/memory/limited_mem/tasks
# Monitorear uso de memoria
watch cat /sys/fs/cgroup/memory/limited_mem/memory.usage_in_bytes
Control de E/S de Bloque:
# Crear cgroup de blkio
mkdir /sys/fs/cgroup/blkio/limited_io
# Establecer peso de E/S (100-1000, por defecto 500)
echo 250 > /sys/fs/cgroup/blkio/limited_io/blkio.weight
# Establecer límite de ancho de banda de lectura específico del dispositivo (bytes/seg)
# Formato: major:minor bytes_por_segundo
echo "8:0 10485760" > /sys/fs/cgroup/blkio/limited_io/blkio.throttle.read_bps_device # 10MB/s
# Establecer límite de IOPS de escritura
echo "8:0 100" > /sys/fs/cgroup/blkio/limited_io/blkio.throttle.write_iops_device
# Agregar proceso
echo $$ > /sys/fs/cgroup/blkio/limited_io/tasks
Integración con Systemd
Crear Servicio Systemd con Límites de Recursos:
# /etc/systemd/system/resource-limited.service
[Unit]
Description=Aplicación con Recursos Limitados
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/my-application
# Límites de CPU
CPUQuota=50%
CPUWeight=500
# Límites de memoria
MemoryMax=512M
MemoryHigh=400M
# Límites de tareas
TasksMax=100
# Límites de E/S
IOWeight=500
IOReadBandwidthMax=/dev/sda 10M
IOWriteBandwidthMax=/dev/sda 5M
[Install]
WantedBy=multi-user.target
Activar servicio:
systemctl daemon-reload
systemctl start resource-limited.service
# Monitorear uso de recursos
systemctl status resource-limited.service
Optimización de Rendimiento
Fijación de CPU y Conciencia NUMA
Fijar Proceso a CPUs Específicas:
# Crear cgroup de cpuset
mkdir /sys/fs/cgroup/cpuset/dedicated_cpus
# Asignar CPUs 4-7
echo "4-7" > /sys/fs/cgroup/cpuset/dedicated_cpus/cpuset.cpus
# Asignar nodos de memoria (NUMA)
echo "0" > /sys/fs/cgroup/cpuset/dedicated_cpus/cpuset.mems
# Hacer exclusivo (prevenir otros procesos)
echo 1 > /sys/fs/cgroup/cpuset/dedicated_cpus/cpuset.cpu_exclusive
# Agregar proceso
echo $PID > /sys/fs/cgroup/cpuset/dedicated_cpus/tasks
# Verificar
taskset -cp $PID
Asignación de Memoria Consciente de NUMA:
# Crear cgroup de memoria con política NUMA
mkdir /sys/fs/cgroup/memory/numa_aware
# Vincular a nodo NUMA específico
numactl --membind=0 --cpunodebind=0 my-application
# O usar controlador de memoria de cgroup
echo 0 > /sys/fs/cgroup/memory/numa_aware/memory.numa_stat
Monitoreo de Rendimiento de Cgroup
Monitorear Uso de CPU:
# Cgroup v2
watch cat /sys/fs/cgroup/test_app/cpu.stat
# Cgroup v1
watch cat /sys/fs/cgroup/cpu/test_app/cpuacct.usage
Monitorear Uso de Memoria y Presión:
# Cgroup v2 - Información de presión de memoria
cat /sys/fs/cgroup/test_app/memory.pressure
# some avg10=0.00 avg60=0.00 avg300=0.00 total=0
# full avg10=0.00 avg60=0.00 avg300=0.00 total=0
# Uso de memoria actual
cat /sys/fs/cgroup/test_app/memory.current
# Eventos de memoria (OOM kills, etc.)
cat /sys/fs/cgroup/test_app/memory.events
Monitorear Rendimiento de E/S:
# Cgroup v2
cat /sys/fs/cgroup/test_app/io.stat
# Cgroup v1
cat /sys/fs/cgroup/blkio/test_app/blkio.throttle.io_service_bytes
Optimización del Tiempo de Inicio de Contenedores
Creación Perezosa de Namespaces:
# Crear namespaces solo cuando sea necesario
# Usar nsenter para unirse a namespaces existentes en lugar de crear nuevos
# Compartir namespaces entre contenedores relacionados
unshare --pid --fork bash # Namespace padre
nsenter --target $PARENT_PID --pid bash # Unirse al namespace PID padre
Estrategias de Optimización de Memoria
Límite de Memoria vs Reserva:
# Cgroup v2
echo "1G" > /sys/fs/cgroup/app/memory.max # Límite duro
echo "512M" > /sys/fs/cgroup/app/memory.high # Límite suave (throttling)
echo "256M" > /sys/fs/cgroup/app/memory.low # Memoria protegida
# Cgroup v1
echo 1073741824 > /sys/fs/cgroup/memory/app/memory.limit_in_bytes
echo 536870912 > /sys/fs/cgroup/memory/app/memory.soft_limit_in_bytes
Monitoreo y Observabilidad
Inspección de Namespaces
Listar Namespaces Activos:
# Listar network namespaces
ip netns list
# Listar todos los tipos de namespace para un proceso
ls -la /proc/$PID/ns/
# Comparar namespaces entre procesos
for ns in /proc/self/ns/*; do
echo "$ns: $(readlink $ns)"
done
Encontrar Procesos en Namespace:
#!/bin/bash
# find_ns_processes.sh - Encontrar todos los procesos en un namespace
NS_TYPE=$1 # pid, net, mnt, etc.
TARGET_NS=$2
for pid in /proc/[0-9]*; do
pid=$(basename $pid)
current_ns=$(readlink /proc/$pid/ns/$NS_TYPE 2>/dev/null)
if [ "$current_ns" == "$TARGET_NS" ]; then
echo "PID $pid: $(cat /proc/$pid/cmdline | tr '\0' ' ')"
fi
done
Herramientas de Monitoreo de Cgroup
Systemd-cgtop (monitoreo en tiempo real de cgroup):
# Monitorear uso de recursos de cgroup
systemd-cgtop
# Columnas ordenables: Path, Tasks, %CPU, Memory, I/O
Script de Monitoreo Personalizado:
#!/bin/bash
# cgroup_monitor.sh - Monitorear métricas de cgroup
CGROUP_PATH="/sys/fs/cgroup/test_app"
while true; do
clear
echo "=== Monitoreo de Cgroup: $(date) ==="
# CPU
echo -e "\n--- CPU ---"
cat ${CGROUP_PATH}/cpu.stat
# Memoria
echo -e "\n--- Memoria ---"
echo -n "Actual: "
cat ${CGROUP_PATH}/memory.current
echo -n "Máximo: "
cat ${CGROUP_PATH}/memory.max
# Presión de memoria
echo -e "\n--- Presión de Memoria ---"
cat ${CGROUP_PATH}/memory.pressure
# E/S
echo -e "\n--- E/S ---"
cat ${CGROUP_PATH}/io.stat
# PIDs
echo -e "\n--- PIDs ---"
echo -n "Actual: "
cat ${CGROUP_PATH}/pids.current
echo -n "Máximo: "
cat ${CGROUP_PATH}/pids.max
sleep 2
done
Integración con Prometheus
Exportar métricas de cgroup:
# Instalar cAdvisor para métricas de contenedores
docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--volume=/dev/disk/:/dev/disk:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
gcr.io/cadvisor/cadvisor:latest
# Métricas disponibles en http://localhost:8080/metrics
Resolución de Problemas
Problemas con Namespaces
No se Puede Crear Namespace:
Síntoma: "Operation not permitted" al crear namespace.
Diagnóstico:
# Verificar soporte del kernel
cat /boot/config-$(uname -r) | grep NAMESPACES
# Verificar creación de namespace sin privilegios
sysctl kernel.unprivileged_userns_clone
Resolución:
# Habilitar user namespaces sin privilegios
echo "kernel.unprivileged_userns_clone=1" >> /etc/sysctl.d/99-userns.conf
sysctl -p /etc/sysctl.d/99-userns.conf
# O ejecutar con sudo/root
sudo unshare --user --map-root-user bash
Problemas de Conectividad en Network Namespace:
Síntoma: El namespace no puede alcanzar la red externa.
Diagnóstico:
# Verificar enrutamiento del namespace
ip netns exec myns ip route
# Verificar reglas NAT
iptables -t nat -L POSTROUTING -n -v
# Verificar reenvío de IP
cat /proc/sys/net/ipv4/ip_forward
Resolución:
# Habilitar reenvío de IP
echo 1 > /proc/sys/net/ipv4/ip_forward
# Agregar regla NAT
iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -j MASQUERADE
# Agregar ruta por defecto en namespace
ip netns exec myns ip route add default via 192.168.100.1
Problemas con Cgroups
Proceso Terminado por OOM:
Síntoma: Proceso terminado con mensaje "Out of memory".
Diagnóstico:
# Verificar límite de memoria del cgroup
cat /sys/fs/cgroup/app/memory.max
# Verificar uso real
cat /sys/fs/cgroup/app/memory.current
# Verificar eventos OOM
cat /sys/fs/cgroup/app/memory.events | grep oom
Resolución:
# Incrementar límite de memoria
echo "2G" > /sys/fs/cgroup/app/memory.max
# Deshabilitar OOM killer (usar con precaución)
echo 1 > /sys/fs/cgroup/memory/app/memory.oom_control
# Habilitar swap para cgroup
echo "1G" > /sys/fs/cgroup/app/memory.swap.max
Problemas de Throttling de CPU:
Síntoma: Aplicación lenta a pesar de bajo uso de CPU del sistema.
Diagnóstico:
# Verificar cuota de CPU
cat /sys/fs/cgroup/app/cpu.max
# Verificar estadísticas de throttling
cat /sys/fs/cgroup/app/cpu.stat | grep throttled
Resolución:
# Incrementar cuota de CPU
echo "200000 100000" > /sys/fs/cgroup/app/cpu.max # 200% (2 núcleos)
# Eliminar límite de cuota
echo "max 100000" > /sys/fs/cgroup/app/cpu.max
# Incrementar peso/shares de CPU
echo 2048 > /sys/fs/cgroup/app/cpu.weight
No se Puede Escribir en Archivos de Cgroup:
Síntoma: Permiso denegado al modificar parámetros de cgroup.
Diagnóstico:
# Verificar propiedad del cgroup
ls -ld /sys/fs/cgroup/app
# Verificar delegación
cat /sys/fs/cgroup/cgroup.subtree_control
Resolución:
# Habilitar controladores
echo "+cpu +memory +io" > /sys/fs/cgroup/cgroup.subtree_control
# Cambiar propiedad (si se usa delegación)
chown -R user:group /sys/fs/cgroup/app
Conclusión
Los namespaces y cgroups de Linux proporcionan las tecnologías fundamentales del kernel que habilitan la contenedorización, el aislamiento de recursos y la computación multi-inquilino esenciales para la infraestructura moderna en la nube. Comprender estos mecanismos más allá de las abstracciones de plataformas de contenedores permite a los ingenieros construir soluciones de aislamiento personalizadas, resolver problemas complejos de contenedores, optimizar la asignación de recursos y arquitectar sistemas multi-inquilino seguros.
Los namespaces entregan aislamiento de procesos a través de múltiples dimensiones—árboles de procesos, pilas de red, jerarquías de sistemas de archivos, mecanismos IPC y mapeos de usuario/grupo—creando límites de seguridad que previenen la escalada de privilegios y la interferencia de recursos. Los Cgroups complementan este aislamiento con capacidades de contabilidad, limitación y priorización de recursos que controlan el consumo de CPU, memoria, E/S y procesos.
El despliegue exitoso de tecnologías de namespaces y cgroups requiere comprender la arquitectura del kernel, el comportamiento de los controladores de recursos, las implicaciones de rendimiento y las consideraciones de seguridad. Las organizaciones deben implementar monitoreo completo del uso de recursos, límites de cgroups, conectividad de namespaces y rendimiento de aplicaciones para validar la efectividad de la configuración.
A medida que la contenedorización evoluciona hacia requisitos de aislamiento cada vez más sofisticados—multi-tenencia segura, controles de recursos granulares y escenarios de red complejos—el dominio de los mecanismos subyacentes de namespaces y cgroups se vuelve esencial para los ingenieros de infraestructura que construyen plataformas de próxima generación más allá de los runtimes de contenedores estándar.


