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.