Consigna y contexto aplicable
En un host Linux que utiliza cgroup v2, el contenedor A tiene estas restricciones de ejercicio:
| Restricción | Valor concreto de cgroup v2 |
|---|---|
| Memoria | memory.max = 536870912 bytes, o 512 MiB |
| CPU | cpu.max = 50000 100000, o hasta 50 ms cada 100 ms |
| Conteo de tareas | pids.max = 128 |
Dentro del contenedor, la aplicación se ve a sí misma como el PID 1, un hostname de contenedor, su propia tabla de montajes y sus propias interfaces de red. Explique cómo un runtime crea ese entorno, de dónde proviene realmente el aislamiento y cómo se manifiestan las fallas por límites. Luego, aborde el límite de seguridad del kernel compartido y demuestre la configuración mediante el estado observable del kernel en lugar de basarse únicamente en un docker run exitoso.
Esta pregunta aplica a roles de Linux, plataforma, SRE, DevOps, infraestructura, cloud, seguridad y backend. Los valores son restricciones de entrevista, no valores predeterminados recomendados. "Contenedor" se refiere a un contenedor de procesos al estilo OCI de Linux; los productos de contenedores respaldados por VM añaden una capa de aislamiento diferente.
Qué está evaluando el entrevistador
La primera prueba consiste en determinar si el candidato puede sustituir la frase "VM ligera" por un modelo de procesos preciso. Un contenedor Linux es un árbol de procesos en el host. Los namespaces modifican los recursos globales que esos procesos pueden ver: PIDs, montajes, objetos de red, objetos IPC, identidad del host, IDs de usuario, rutas de cgroup y, opcionalmente, relojes. Un sistema de archivos raíz y una vista de montaje privada suministran la imagen de userspace. Ninguno de ellos crea un segundo kernel.
La segunda prueba consiste en separar la visibilidad del control de recursos. Los namespaces responden a la pregunta "¿qué instancia puede observar o modificar este proceso?". Los cgroups responden a "¿cuánto puede consumir este grupo y cómo se contabiliza?". Un PID namespace no limita el número de tareas. Un límite de PID de cgroup no oculta los procesos del host. Un mount namespace cambia la vista de montajes, mientras que el rootfs suministra los archivos. chroot por sí solo no es ni un contenedor completo ni un límite de seguridad.
La tercera prueba consiste en deducir el comportamiento a partir de archivos exactos de cgroup v2. memory.max es un límite de memoria estricto que puede provocar una terminación OOM local en el cgroup tras fallar la recuperación de memoria (reclaim). cpu.max es un control de ancho de banda: tras consumir 50 ms en un período de 100 ms, el trabajo ejecutable se ralentiza (throttled) hasta que haya cuota disponible; no se termina. pids.max rechaza una llamada infractora a fork() o clone() con EAGAIN. El candidato debe nombrar los contadores de eventos que distinguen estos resultados.
La cuarta prueba es el criterio de seguridad. Los contenedores comparten el kernel del host, por lo que los namespaces y cgroups no equivalen a un límite de VM. El mapeo de User-ID, un conjunto reducido de capabilities, no_new_privs, seccomp, un LSM como AppArmor o SELinux, montajes de solo lectura o enmascarados y dispositivos limitados reducen la superficie de ataque. Un contenedor privilegiado, el PID o network namespace del host, el socket de Docker o un montaje amplio del host pueden eliminar deliberadamente límites importantes.
Por último, el entrevistador busca un plan de verificación. La respuesta debe comparar las identidades de inodos de namespaces, los mapeos UID/GID, la pertenencia a cgroups y los archivos de controladores, las capabilities del proceso, el estado de seccomp, la propagación de montajes, las interfaces de red y los contadores de fallas desde ambos lados del límite.
Preguntas para aclarar antes de responder
- ¿Qué runtime y modo de contenedor están dentro del alcance? Se asume un runtime OCI en Linux. El modo rootless, el remapeo de user namespaces, el modo privilegiado y los sandboxes respaldados por VM cambian el límite de confianza.
- ¿"0.5 CPU" significa cuota o peso relativo? Aquí significa un tope de ancho de banda de 50,000 microsegundos por cada período de 100,000 microsegundos.
cpu.weightsolo cambia la proporción relativa durante la contención. - ¿Qué incluyen los 512 MiB? cgroup v2 contabiliza los principales consumidores, como la memoria anónima, el page cache, las estructuras del kernel y los buffers de sockets, pero no todos los recursos del host están controlados por este único archivo.
- ¿128 se refiere a procesos o tareas del kernel? El controlador pids utiliza IDs de tareas del kernel, por lo que los hilos (threads) también consumen el presupuesto. Ese detalle importa en runtimes con alta concurrencia de hilos.
- ¿El swap está habilitado y limitado por separado?
memory.maxymemory.swap.maxson controles diferentes. La consigna fija únicamente el límite de memoria, por lo que la política de swap debe inspeccionarse en lugar de asumirse. - ¿Qué namespaces están configurados realmente? La configuración de OCI puede crear un namespace, unirse a un namespace existente mediante una ruta u omitir el tipo y heredar el namespace del runtime. Omitir uno constituye un cambio real en los límites.
- ¿Cuál es el modelo de amenazas? Las cargas de trabajo hostiles multi-tenant pueden requerir un límite de VM o microVM además del aislamiento de procesos. Una carga de trabajo interna confiable puede admitir un balance diferente.
Estructura de respuesta de 30 segundos
"Un contenedor Linux es un árbol de procesos del host iniciado sobre un rootfs, ubicado en namespaces y un cgroup seleccionados; el kernel del host sigue siendo compartido. Los namespaces aíslan las vistas, mientras que los cgroups contabilizan y limitan el consumo. Aquí, memory.max=536870912 puede provocar un OOM del cgroup tras un reclaim fallido, cpu.max=50000 100000 limita por throttling el trabajo de fair-class después de 50 ms por cada 100 ms, y pids.max=128 rechaza un fork o clone infractor con EAGAIN.
Añadiría mapeo de UID cuando sea apropiado, capabilities mínimas, no_new_privs, seccomp, una política de AppArmor o SELinux, montajes seguros y dispositivos restringidos. Verificaría las identidades de namespaces, los mapas de UID, los montajes, las interfaces, los archivos de cgroup efectivos, las capabilities y el estado de seguridad desde ambos lados; luego ejecutaría pruebas acotadas y exigiría evidencia coincidente en memory.events, cpu.stat y pids.events."
Análisis detallado paso a paso
Paso 1: Comenzar con el modelo de procesos del host
El runtime recibe un bundle OCI que contiene un sistema de archivos raíz y una configuración. Una secuencia de configuración representativa es:
- validar el bundle, el ejecutable, los montajes, las opciones de namespaces, las credenciales y las configuraciones de recursos;
- crear o seleccionar el subárbol de cgroup y escribir los valores del controlador;
- crear nuevos namespaces o unirse a los namespaces existentes configurados;
- establecer mapeos UID/GID si se utiliza un user namespace;
- hacer que la propagación de montajes sea segura, montar el rootfs y los sistemas de archivos especiales, y cambiar la raíz del proceso;
- crear o mover dispositivos de red y configurar rutas cuando se utiliza un nuevo network namespace;
- establecer credenciales, capabilities,
no_new_privs, seccomp y etiquetas o perfiles LSM; - asociar el proceso al cgroup y ejecutar
execcon la aplicación configurada.
El orden exacto y los procesos auxiliares varían según el runtime. Lo que no varía es el estado observable del kernel: la aplicación sigue siendo un proceso programado en el host con membresías de namespaces, credenciales, montajes, filtros y una ruta de cgroup. Si el runtime falla inesperadamente tras una configuración parcial, la limpieza debe eliminar montajes, interfaces, anclajes de namespaces (namespace pins) y cgroups; la palabra "contenedor" no es un objeto del kernel que realice la limpieza automáticamente.
Paso 2: Asignar una responsabilidad a cada namespace
Los namespaces principales son complementarios:
| Namespace | Vista aislada | Límite importante |
|---|---|---|
| PID | Espacio numérico de Process ID y visibilidad | La misma tarea tiene un PID interno y un PID de host; el PID 1 del contenedor debe recolectar procesos hijos huérfanos (reap) y manejar señales correctamente |
| Mount | Puntos de montaje y propagación | Cambia la tabla de montajes, no el kernel subyacente ni automáticamente el almacenamiento de respaldo |
| Network | Interfaces, rutas, puertos, sockets y pila de red | La conectividad se reintroduce deliberadamente con un par veth, bridge, enrutamiento u otro controlador de red |
| UTS | Hostname y nombre de dominio NIS | Es una presentación de identidad, no autenticación |
| IPC | System V IPC y colas de mensajes POSIX | Los archivos o sockets compartidos deliberadamente mediante montajes aún pueden conectar cargas de trabajo |
| User | Mapeos UID/GID y capabilities dentro del alcance del namespace | El UID 0 interno puede mapearse a un UID no privilegiado en el host |
| Cgroup | Vista de la jerarquía de cgroups | La aplicación de recursos proviene de los controladores, no de la vista del cgroup namespace |
| Time | Desplazamientos de reloj de arranque y monotónico | No proporciona hardware de reloj de tiempo real independiente y arbitrario |
Un tipo de namespace omitido de la lista de namespaces de OCI se hereda del runtime. --pid=host, usar la red del host o unirse al namespace de otro contenedor pueden ser decisiones intencionales, pero la respuesta debe señalar la pérdida de aislamiento en lugar de seguir describiendo un contenedor totalmente privado.
El límite del sistema de archivos requiere tanto un mount namespace como un rootfs. Un modo de propagación privado o esclavo evita que los eventos de montaje del contenedor se transmitan inesperadamente al host. Los montajes de solo lectura, las rutas enmascaradas, un /dev mínimo y los bind mounts explícitos restringen el acceso. Un bind mount con permisos de escritura de la raíz del host o del socket del motor de contenedores crea una vía directa de alto impacto, independientemente del hostname privado del proceso.
Paso 3: Deducir los tres resultados de los límites de recursos
Memoria. memory.max=536870912 es el límite estricto principal para el cgroup y sus descendientes. A medida que el uso se acerca al límite, el kernel intenta recuperar memoria (reclaim). Si el uso alcanza el límite y no se puede reducir, el cgroup entra en el manejo de OOM; en el modo predeterminado, el OOM killer puede seleccionar una tarea en ese cgroup, y memory.oom.group=1 puede solicitar el tratamiento como una única carga de trabajo indivisible. Puede ocurrir una lectura breve por encima del límite. Verifique memory.current, memory.peak y los campos max, oom, oom_kill y oom_group_kill en memory.events. No diagnostique cada SIGKILL como un OOM de cgroup sin esos contadores y evidencia del kernel o del runtime.
CPU. cpu.max=50000 100000 significa que las tareas de fair-class en el grupo pueden consumir hasta 50,000 microsegundos durante cada período de 100,000 microsegundos: un ancho de banda promedio de 0.5 CPU. Múltiples hilos pueden consumir la cuota de forma concurrente y agotarla antes de que finalice el período. Las tareas ejecutables sufren entonces throttling hasta que haya cuota disponible; no se terminan. Inspeccione usage_usec, nr_periods, nr_throttled y throttled_usec en cpu.stat. Por lo tanto, un pico de latencia cerca del límite de un período puede deberse al throttling de cuota incluso cuando la CPU del host esté disponible.
Tareas. pids.max=128 es un límite jerárquico estricto sobre las tareas del kernel. Los hilos cuentan. Una vez que una nueva tarea violaría la política, fork() o clone() falla con EAGAIN; las tareas existentes continúan ejecutándose. Inspeccione pids.current, pids.peak y el conteo de max en pids.events. Mover tareas existentes o reducir el límite configurado puede producir temporalmente pids.current > pids.max; la creación se sigue bloqueando para evitar violar la política.
Los cgroups padre también restringen a los hijos. Un hijo no puede obtener capacidad de CPU, memoria o tareas que sus ancestros no permitan. Por el contrario, estas tres configuraciones no limitan automáticamente todos los recursos: el espacio de almacenamiento, las operaciones de E/S, los descriptores de archivo, el ancho de banda de red, los dispositivos y los objetos globales del kernel requieren sus propios controles y límites operativos.
Paso 4: Aplicar capas de controles de seguridad alrededor del kernel compartido
Los user namespaces permiten que un proceso sea el UID 0 internamente mientras se mapea a un UID normal sin privilegios en el exterior. Esto reduce el impacto de un escape de namespace o de un acceso erróneo a archivos del host, pero los mapeos y la propiedad del sistema de archivos deben diseñarse en conjunto. Sin un user namespace, root en el contenedor sigue siendo el UID 0 del host, incluso si sus capabilities y los objetos a los que puede acceder están restringidos.
Las capabilities dividen los privilegios tradicionales de root. Comience desde el conjunto mínimo en lugar de otorgar todas las capabilities. Quitar una capability solo es útil si el proceso no puede recuperarla mediante capabilities de archivo, ejecución con set-user-ID u otra vía; un conjunto acotado y no_new_privs hacen que esa intención sea auditable.
Seccomp filtra llamadas al sistema y puede permitir, denegar, atrapar (trap), matar, registrar o notificar según la llamada y sus argumentos. Reduce la superficie de ataque alcanzable del kernel, pero no interpreta la autorización a nivel de aplicación. Un LSM como AppArmor o SELinux aplica políticas a operaciones sobre archivos, procesos, sockets y otros objetos. Los sistemas de archivos de solo lectura, las rutas de /proc enmascaradas y un conjunto mínimo de dispositivos añaden restricciones independientes.
Estas son capas, no sustitutos. Los cgroups abordan principalmente la contabilidad y la denegación de servicio por recursos; no evitan que un contenedor lea los datos de otro. Los namespaces aíslan principalmente las vistas; no corrigen vulnerabilidades en el kernel compartido. Para tenants adversarios, el riesgo de exploits del kernel o los requisitos de cumplimiento normativo pueden justificar un límite mediante VM, microVM o un kernel en sandbox.
Paso 5: Verificar el estado del kernel desde ambos lados
Desde el host, identifique primero el proceso init del contenedor y la ruta del cgroup. Un esquema de inspección genérico es:
pid=<host-pid-of-container-init>
cg=/sys/fs/cgroup/<container-cgroup>
readlink /proc/$pid/ns/{pid,mnt,net,uts,ipc,user,cgroup}
cat /proc/$pid/uid_map
cat /proc/$pid/gid_map
cat /proc/$pid/cgroup
cat "$cg/memory.current" "$cg/memory.max" "$cg/memory.events"
cat "$cg/cpu.max" "$cg/cpu.stat"
cat "$cg/pids.current" "$cg/pids.max" "$cg/pids.events"
grep -E '^(CapPrm|CapEff|CapBnd|NoNewPrivs|Seccomp):' /proc/$pid/statusCompare las identidades de dispositivo/inodo de los enlaces simbólicos de namespaces con el host y con otro contenedor. Identidades diferentes demuestran instancias de namespace diferentes; no demuestran por sí solas montajes seguros, rutas o políticas adecuadas. Inspeccione la tabla y propagación de montajes reales, los enlaces y rutas de red, el conjunto de capabilities efectivas, el modo de seccomp, la etiqueta LSM y los nodos de dispositivos.
Dentro del contenedor, registre /proc/1/status, /proc/self/cgroup, mount, hostname, los procesos visibles, interfaces, rutas, UID/GID y enlaces de namespaces. Utilice nsenter desde un host autorizado únicamente para diagnóstico; entrar en namespaces es un acceso privilegiado, no una prueba de que el límite haya fallado.
Por último, ejecute pruebas de fallas acotadas en un entorno desechable. Asigne memoria gradualmente y correlacione las fallas con memory.events; ejecute trabajo de CPU y correlacione la latencia con nr_throttled; cree hilos o procesos hasta que la siguiente creación retorne EAGAIN y se incremente pids.events. Detenga las pruebas antes de generar presión a nivel de host y verifique que los cgroups hermanos permanezcan saludables.
Paso 6: Transformar las observaciones en criterios de aceptación
Un registro de aceptación defendible contiene valores, identidades y resultados:
- los IDs de namespaces difieren donde se requiere aislamiento y coinciden solo donde compartir es intencional;
- el mapeo de UID 0, las capabilities efectivas,
NoNewPrivs, el modo de seccomp y la etiqueta LSM coinciden con el modelo de amenazas; - la propagación de montajes, los bind mounts, las rutas enmascaradas, las rutas con permisos de escritura y el acceso a dispositivos coinciden con la configuración de OCI;
memory.max,cpu.maxypids.maxson iguales a 536870912,50000 100000y 128 en el cgroup efectivo;- la presión de memoria cambia los contadores de eventos de memoria relevantes, la carga de CPU incrementa los contadores de throttling sin matar tareas y la creación de la tarea número 129 es rechazada cuando ya hay 128 tareas contabilizadas;
- los cgroups padre y hermanos se mantienen dentro de sus propios presupuestos durante cada prueba;
- las pruebas de reinicio y fallas forzadas no dejan montajes, interfaces, namespace pins ni cgroups poblados inesperados.
La afirmación sobre la tarea número 129 está condicionada a que exactamente 128 tareas ya estén cargadas a la jerarquía efectiva y no haya finalizaciones concurrentes. En una prueba real, lea pids.current inmediatamente antes de la creación en lugar de asumir que una aplicación tiene una sola tarea.
Respuesta de muestra sólida
"Comenzaría con el modelo de procesos del host. El runtime toma un rootfs y una configuración de OCI, crea o se une a los namespaces solicitados de PID, mount, network, UTS, IPC, user, cgroup y time, configura los montajes y la red, asocia el árbol de procesos a un cgroup, aplica credenciales y políticas de seguridad, y ejecuta la aplicación con exec. El PID 1 interno sigue siendo un proceso del host con otro PID en el exterior. El contenedor tiene una vista de userspace privada, mientras que el kernel del host permanece compartido.
Los namespaces y los cgroups resuelven problemas diferentes. El PID namespace cambia la visibilidad de los procesos; el mount namespace junto con el rootfs cambia el sistema de archivos visible; el network namespace proporciona sus propias interfaces, rutas, puertos y sockets. Los user namespaces pueden mapear el UID 0 interno a un UID no privilegiado del host. Los cgroups contabilizan y controlan el árbol de procesos, pero no ocultan los objetos del host.
Para los valores indicados de cgroup v2, memory.max=536870912 es un límite estricto de 512 MiB. El kernel intenta el reclaim y luego puede invocar el manejo de OOM del cgroup si el uso no se puede reducir; leería memory.events para distinguir max, oom y oom_kill. cpu.max=50000 100000 suministra como máximo 50 ms cada 100 ms al trabajo de fair-class. Una vez consumida la cuota, las tareas ejecutables sufren throttling hasta que haya más cuota disponible, y cpu.stat reporta nr_throttled y throttled_usec; no hay terminación de procesos por límite de CPU. pids.max=128 cuenta las tareas del kernel, incluidos los hilos. Un fork o clone infractor retorna EAGAIN, y pids.events registra el evento.
Debido a que el kernel es compartido, aplicaría en capas un user namespace donde sea apropiado, un conjunto mínimo de capabilities, no_new_privs, seccomp, una política de AppArmor o SELinux, montajes de solo lectura o enmascarados y un conjunto mínimo de dispositivos. Rechazaría el modo privilegiado, namespaces del host, montajes amplios del host o acceso al socket del motor a menos que cada uno sea un requisito explícito y de confianza. La multitenencia con cargas hostiles puede requerir un límite mediante VM o microVM.
Para verificar, compararía las identidades de dispositivo/inodo de /proc/{PID}/ns/*, mapas UID/GID, montajes, interfaces, rutas de cgroup, archivos de controladores efectivos, capabilities, modo seccomp y etiquetas LSM desde el host y el contenedor. Luego ejecutaría pruebas acotadas de memoria, CPU y tareas, exigiendo los contadores del kernel y modos de falla correspondientes. Un contenedor que simplemente inicia no ha demostrado aislamiento."
Errores comunes y mejoras
- Llamar al contenedor una pequeña VM → esto oculta el kernel compartido y genera suposiciones de seguridad erróneas → describa los procesos del host con el estado de namespaces, cgroups, sistema de archivos, credenciales y políticas.
- Decir que los namespaces limitan la CPU y la memoria → los namespaces aíslan vistas, no el consumo → asocie los límites de recursos a controladores y archivos de cgroup.
- Decir que los cgroups aíslan archivos y procesos → los cgroups agrupan, contabilizan y restringen tareas → asocie la visibilidad a los namespaces de PID y mount.
- Tratar a
chrootcomo un contenedor → cambiar la raíz aparente no añade aislamiento de PID, red, usuario ni recursos → combine un rootfs con mount y otros namespaces requeridos además de políticas. - Afirmar que el límite de CPU mata un proceso → la cuota de CPU normalmente aplica throttling al trabajo ejecutable de fair-class → verifique
cpu.statpara detectar throttling. - Esperar que el uso de memoria se detenga exactamente en 512 MiB → el reclaim, la sincronización de la contabilidad y los excesos temporales complican la lectura instantánea → utilice
memory.maxy contadores de eventos para determinar el resultado aplicado. - Contar únicamente procesos contra
pids.max→ el controlador cuenta tareas del kernel, por lo que los hilos lo consumen → inspeccionepids.currentantes de una prueba de límite. - Asumir que root dentro del contenedor es inofensivo → sin un user namespace puede seguir siendo el UID 0 del host, restringido solo por otros controles → inspeccione
uid_mapy las capabilities. - Equiparar la separación de namespaces con un límite seguro entre tenants → una vulnerabilidad del kernel o un montaje peligroso del host pueden atravesar el límite de procesos → defina el modelo de amenazas y añada políticas o un límite mediante VM.
- Comprobar la configuración pero no el estado efectivo → los flags del runtime pueden ser anulados, heredados o fallar parcialmente → lea
/procy los archivos de cgroup, luego ejercite cada límite.
Preguntas de seguimiento
Pregunta de seguimiento 1: ¿Por qué el PID 1 necesita un tratamiento especial dentro de un contenedor?
El primer proceso en un PID namespace es visible como PID 1 para sus descendientes. Adopta procesos hijos huérfanos y debe recolectarlos (reap), o de lo contrario los procesos zombies se acumularán y consumirán el presupuesto de pids. El PID 1 también tiene una semántica especial de manejo de señales, por lo que un wrapper que no reenvíe señales puede hacer que la terminación ordenada falle. Verifique el proceso init real, la recolección de hijos, el reenvío de señales y el tiempo límite de apagado en lugar de asumir que el framework de la aplicación los gestiona.
Pregunta de seguimiento 2: ¿Cuál es la diferencia entre cpu.max y cpu.weight?
cpu.max establece un ancho de banda máximo por período para el trabajo de fair-class. Puede aplicar throttling a un cgroup incluso cuando el host tenga CPU ociosa después de que ese grupo haya consumido su cuota actual. cpu.weight es una preferencia proporcional entre cgroups hermanos ejecutables durante períodos de contención y no define por sí mismo un límite estricto de 0.5 CPU. Una política de producción puede utilizar ambos para diferentes objetivos.
Pregunta de seguimiento 3: ¿Puede root en el contenedor ser un usuario no privilegiado en el host?
Sí, cuando un user namespace mapea el UID 0 interno a un rango de UID no privilegiados en el exterior. Confirme el mapeo en /proc/{PID}/uid_map y /proc/{PID}/gid_map. Esto reduce los privilegios en el host, pero la propiedad de bind mounts, la asignación de IDs subordinados, las capabilities en el user namespace propietario y la superficie de ataque del kernel aún requieren revisión.
Pregunta de seguimiento 4: ¿Por qué un mount namespace privado es insuficiente para la seguridad del sistema de archivos?
Aísla la tabla de montajes, pero el runtime decide qué sistemas de archivos de respaldo y bind mounts aparecen allí. Un namespace privado que contenga un bind mount con permisos de escritura de / sigue exponiendo la raíz del host. Revise en conjunto los orígenes de montaje, la propagación, los flags de escritura, las rutas enmascaradas y de solo lectura, los nodos de dispositivos, las credenciales del proceso y la política LSM.
Pregunta de seguimiento 5: ¿Cuándo debería preferirse una VM o MicroVM?
Prefiera un límite más fuerte cuando tenants que no confían mutuamente ejecuten código arbitrario, un escape de kernel compartido esté fuera del riesgo aceptado, el cumplimiento normativo requiera kernels separados o las versiones de kernel y módulos deban diferir. El costo es una sobrecarga adicional de inicio, memoria, imagen y operaciones. La decisión responde al modelo de amenazas y a las restricciones medidas de la plataforma, no a la etiqueta de contenedor o VM por sí sola.
Pregunta de seguimiento 6: ¿Cómo diagnosticaría un contenedor que funciona lento pero no es terminado por OOM?
Correlacione la latencia de la aplicación con el throttling en cpu.stat, la presión alta/máxima en memory.events, la información de pressure-stall, las estadísticas del controlador de E/S, la programación en el host y los errores de red. Un aumento en nr_throttled o throttled_usec con contadores OOM estables apunta a la cuota de CPU. La presión de reclaim o de E/S también puede detener el avance del trabajo sin provocar una terminación, por lo que el diagnóstico requiere marcas de tiempo alineadas y el análisis de la jerarquía efectiva del cgroup.