Tema representativo de entrevista

Entrevista de Linux: ¿Por qué el Load Average es alto cuando el uso de CPU es bajo y cómo diagnosticarlo?

GeneralDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Un servidor Linux con 16 CPUs lógicas tiene un load average de 48, 36 y 18, mientras que el CPU idle agregado sigue siendo del 72%. ¿Demuestra esto una sobrecarga de CPU? Explica el load average y muestra cómo distinguirías el encolamiento de CPU, esperas de I/O o del kernel, presión de memoria y una discrepancia en el alcance de observabilidad.

Consigna y roles aplicables

Un servidor Linux con 16 CPUs lógicas se ha vuelto lento. uptime reporta promedios de carga (load averages) de 48 / 36 / 18, mientras que mpstat todavía reporta un 72% de CPU idle agregado. Determina si esto demuestra una sobrecarga de CPU y explica cómo identificar el recurso por el cual las tareas realmente están esperando.

La respuesta debe explicar las tareas ejecutables (runnable) e ininterrumpibles en la contabilidad de carga de Linux, interpretar correctamente los valores de 1, 5 y 15 minutos y luego utilizar los estados de las tareas, Pressure Stall Information (PSI) y métricas de subsistemas para distinguir estos casos:

  • la cola de ejecución (run queue) de la CPU está genuinamente congestionada;
  • el almacenamiento local, un sistema de archivos de red, un controlador u otra espera del kernel mantiene las tareas en estado D;
  • la recuperación de memoria (reclaim) o el swapping está generando esperas indirectas;
  • las métricas a nivel de host y las métricas a nivel de contenedor o servicio cubren alcances diferentes.

Esta pregunta es adecuada para entrevistas de SRE, DevOps, infraestructura, sistemas y backend. Los valores 16, 48, 36, 18 y 72% son datos ficticios de ejercicio, no umbrales de alerta universales. El escenario asume que las métricas provienen del mismo host y ventana de tiempo. Si diferentes recolectores o cgroups las produjeron, alinea el alcance antes de interpretarlas.

Qué evalúa el entrevistador

Primero, el candidato debe saber que el load average no es la utilización de la CPU. La carga global de Linux es un promedio con decaimiento exponencial de las tareas ejecutables más las tareas en suspensión ininterrumpible (uninterruptible sleep). Solo el primer grupo expresa directamente demanda de CPU; el segundo puede elevar la carga mientras las CPUs permanecen inactivas.

Segundo, los tres números necesitan una interpretación precisa. No son simples promedios aritméticos de muestras en los últimos 1, 5 y 15 minutos. Son valores con decaimiento exponencial con esas constantes de tiempo. 48 > 36 > 18 respalda la conclusión direccional de que la carga ha aumentado recientemente, pero no puede reconstruir la longitud exacta de la cola en un minuto pasado ni demostrar una causa raíz.

Tercero, un diagnóstico sólido pasa de un total a su composición y lugares de espera. Compara los campos r y b de vmstat, cuenta los hilos en R y D, y luego utiliza wchan, trazas de pila del kernel (kernel stacks), PSI y métricas de almacenamiento o de sistemas de archivos de red para identificar un recurso. Simplemente listar top y iostat no explica cómo la evidencia cambia la conclusión.

Cuarto, el candidato debe manejar contraejemplos. Las herramientas suelen etiquetar a D como disk sleep, pero una espera ininterrumpible no se limita a un disco local. NFS, sistemas de archivos, controladores de dispositivos y algunas esperas de recursos del kernel también pueden aparecer. %iowait es contabilidad de tiempo de CPU, por lo que un iowait bajo no descarta tareas bloqueadas.

Finalmente, la respuesta necesita una mitigación segura y un ciclo de verificación. Agregar CPUs, reiniciar, matar procesos o actualizar el almacenamiento solo es apropiado ante evidencia particular. Tras una corrección, el recuento de tareas R/D, PSI, la latencia de subsistemas y la latencia de cola (tail latency) del negocio deben recuperarse juntos. Esperar únicamente a que el load average decaiga es insuficiente.

Preguntas para aclarar antes de responder

  • ¿Cubren las métricas el mismo alcance? El load average generalmente abarca todo el host, mientras que la CPU de la aplicación puede describir solo un contenedor o proceso. Compara primero las métricas de host, cgroup y servicio; de lo contrario, "carga alta, CPU baja" puede ser una discrepancia de alcance.
  • ¿Es el CPU idle un valor agregado o por CPU? Una CPU, nodo NUMA o carga de trabajo restringida por afinidad puede estar encolada mientras las otras CPUs están inactivas. Inspecciona mpstat -P ALL, la afinidad y la cuota de CPU de cgroup.
  • ¿Qué solicitudes se ralentizaron y cuándo? Alinea el síntoma con despliegues, tráfico, respaldos, latencia de almacenamiento, cambios de montaje y recuperación de memoria para que la señal del host pueda vincularse al impacto en el usuario.
  • ¿Predominan las tareas R o D? Muchas tareas R con CPUs ocupadas respaldan contención de CPU. Muchas tareas D con CPUs inactivas respaldan una espera ininterrumpible. Ambas pueden coexistir, así que agrupa por hilo y carga de trabajo.
  • ¿Qué ruta de almacenamiento está involucrada? NVMe local, almacenamiento en bloque en la nube, FUSE, NFS y una base de datos remota requieren evidencia diferente. iostat no puede ver un RPC de red ordinario, y NFS necesita métricas de montaje y del sistema de archivos de red.
  • ¿Existe presión de memoria o de virtualización? Swap-in/out, recuperación directa (direct reclaim), fallos de página mayores (major faults), steal time del hipervisor y límites de cgroup cambian el orden de investigación.
  • ¿Se pueden leer las trazas de pila de tareas de forma segura? /proc/12345/stack, algunos valores de wchan y los datos de I/O de procesos pueden requerir permisos adicionales. Comienza con muestreos de baja sobrecarga y utiliza solo el privilegio mínimo de producción necesario.

Estructura de respuesta en 30 segundos

"El load average no es un porcentaje de CPU. Linux cuenta las tareas ejecutables y las tareas en suspensión ininterrumpible, y luego calcula promedios con decaimiento exponencial con constantes de tiempo de 1, 5 y 15 minutos. Una carga de 48 en 16 CPUs lógicas indica que muchas tareas están activas o esperando de forma ininterrumpible. Con un 72% de CPU idle, no puedo concluir que las CPUs estén saturadas.

Primero alinearía el alcance de las métricas y verificaría la utilización por CPU. Luego usaría vmstat para comparar las tareas ejecutables en r con las tareas bloqueadas en b, y contaría los hilos en R y D. Muchas tareas R, un PSI de CPU alto y CPUs ocupadas indican encolamiento de CPU. Muchas tareas D con un PSI de I/O alto me llevan a wchan, trazas de pila de tareas, pidstat, iostat, métricas de NFS y registros del kernel. Si el PSI de memoria, el swapping y los major faults aumentan juntos, investigo presión de memoria. Después de la solución, verifico el p99 del negocio, recuentos de R/D, PSI y latencia de subsistemas en lugar de esperar únicamente a que baje el número de carga."

Análisis detallado paso a paso

Paso 1: Dividir el Load Average en sus dos fuentes

La entrada principal para la contabilidad de carga global de Linux se puede resumir como:

nr_running + nr_uninterruptible

nr_running incluye tareas que se están ejecutando actualmente en una CPU y tareas que son ejecutables pero esperan ser planificadas. nr_uninterruptible representa tareas en suspensión ininterrumpible. Los primeros tres campos de /proc/loadavg son los valores de carga de 1, 5 y 15 minutos para esta población de tareas activas. El cuarto campo tiene la forma 7/1280: el primer número corresponde a las entidades de planificación ejecutables en este momento y el segundo a todas las entidades de planificación presentes en total. El quinto campo es el PID creado más recientemente.

Por lo tanto, "carga 48" no significa "300% de utilización de CPU", ni significa exactamente 48 procesos encolados en este instante. Es una señal suavizada del recuento de tareas. Dividir la carga por el número de CPUs lógicas es solo un indicio aproximado de saturación para una carga de trabajo limitada por CPU (CPU-bound). Una vez que las tareas en estado D contribuyen materialmente, esa proporción ya no describe la cola de la CPU.

El kernel actualiza un promedio con decaimiento exponencial a intervalos fijos. Las nuevas muestras tienen mayor peso, mientras que las muestras más antiguas decaen. Así, 48 / 36 / 18 indica más tareas activas recientemente que antes. El valor de 15 minutos puede permanecer alto después de que desaparezca la causa, por lo que las decisiones de recuperación deben priorizar los estados actuales de las tareas, PSI y las métricas orientadas al usuario.

Paso 2: Alinear alcance, utilización por CPU y la cola actual

Comienza con observaciones con marca de tiempo y de baja sobrecarga:

bash
nproc
uptime
cat /proc/loadavg
vmstat 1 10
mpstat -P ALL 1 10

El primer reporte de vmstat generalmente es un promedio desde el arranque, así que utiliza las muestras posteriores para el incidente actual. Los campos importantes incluyen:

  • r: tareas ejecutables; un valor sostenido muy por encima de las CPUs disponibles junto con CPUs ocupadas respalda el encolamiento de CPU;
  • b: tareas en suspensión ininterrumpible; un aumento sostenido dirige la investigación hacia un recurso en espera;
  • us, sy, id, wa y st: tiempo de usuario, sistema, inactividad, espera de I/O y steal time del hipervisor;
  • si y so: actividad de swap-in y swap-out, a ser interpretada junto con el PSI de memoria y los fallos de página.

El setenta y dos por ciento de inactividad agregada aún puede ocultar una CPU saturada. Un hilo serial fijado a la CPU 3 puede saturar esa CPU mientras las otras 15 permanecen mayormente inactivas. La utilización por CPU, la afinidad de tareas, las cuotas de CPU de cgroup y el estrangulamiento (throttling) distinguen esto de una necesidad de más CPUs en todo el host.

Paso 3: Contar R y D por hilo y localizar el punto de espera

Múltiples hilos dentro de un proceso contribuyen a la carga, por lo que se debe usar una vista a nivel de hilo:

bash
ps -eLo state,pid,tid,ppid,wchan:32,comm --sort=state
ps -eLo state= | sort | uniq -c

R significa en ejecución o ejecutable (running o runnable). D significa suspensión ininterrumpible (uninterruptible sleep). Una señal normalmente no puede surtir efecto hasta que la tarea sale de esa espera, por lo que emitir repetidamente kill -9 no libera el recurso del kernel de inmediato ni preserva evidencia útil.

Para un grupo de hilos en estado D, agrupa por comando, proceso padre, cgroup y wchan. wchan muestra dónde está durmiendo un hilo en el kernel y puede reducir la búsqueda a I/O de bloques, NFS, un sistema de archivos o la ruta de un controlador. Cuando los permisos lo permitan, inspecciona la traza de pila del kernel de una tarea representativa:

bash
cat /proc/12345/stack
cat /proc/12345/wchan

El nombre de una función no es una causa raíz. Muchas tareas agrupadas en el mismo punto de espera, alineadas en el tiempo con la latencia del subsistema y el impacto en el usuario, constituyen una evidencia más sólida. El estado D tampoco demuestra que una aplicación haya generado intencionalmente I/O excesivo. Un dispositivo averiado, un montaje remoto inaccesible o una ruta del kernel atascada pueden acumular muchos hilos en espera a partir de una tasa de solicitudes pequeña.

Paso 4: Usar PSI para identificar qué recurso detiene el progreso

PSI cuantifica el tiempo perdido debido a la contención de CPU, memoria o I/O:

bash
for resource in cpu io memory; do
  echo "[$resource]"
  cat /proc/pressure/"$resource"
done

some es la proporción de tiempo en la que al menos algunas tareas están estancadas en un recurso. full es la proporción cuando todas las tareas no inactivas están estancadas simultáneamente. El full de CPU a nivel de sistema se conserva en cero y no debe usarse para inferir saturación de CPU. avg10, avg60 y avg300 describen las tendencias recientes de 10, 60 y 300 segundos; total es el tiempo de estancamiento acumulado en microsegundos.

PSI y load average responden preguntas diferentes. El load average describe cuántas tareas están activas o esperando de forma ininterrumpible. PSI describe cuánto tiempo una carga de trabajo no puede avanzar. Combinarlos evita el reflejo de "agregar CPUs porque la carga es alta". Con cgroup v2, lee también cpu.pressure, io.pressure y memory.pressure en el cgroup objetivo para separar la presión del servicio del ruido del host.

Utiliza esta matriz para organizar la evidencia:

Combinación de observacionesPrimera hipótesisSiguiente evidencia
Alto uso de CPU, alto r, alto PSI de CPUContención en la cola de ejecución de CPUPuntos calientes por CPU, perfil de CPU, afinidad y cuota
Alto CPU idle, muchas tareas b/D, alto PSI de I/OI/O u otra espera ininterrumpible del kernelwchan/pilas, latencia de dispositivo o NFS, logs del kernel
Alto PSI de memoria, aumento de si/so o fallos mayoresPresión de recuperación o swappingMemoria de cgroup, working set, recuperación y lecturas de almacenamiento
Alta carga de host, bajo PSI en cgroup objetivoDiscrepancia de alcance u otro inquilinoAtribuir tareas y recursos por cgroup/proceso

Esta matriz es un punto de partida, no un detector automático de causa raíz. La presión de CPU, memoria e I/O puede formar un bucle de retroalimentación. La recuperación de memoria puede desencadenar lecturas de archivos, por ejemplo, lo que a su vez puede poner los hilos en estado D.

Paso 5: Entrar al subsistema relevante en lugar de calificar cada espera como "disco lento"

Si la evidencia apunta a dispositivos de bloque, examina el rendimiento, la latencia, el encolamiento y los errores:

bash
pidstat -d -p ALL 1 10
iostat -xz 1 10
dmesg -T | tail -200

pidstat ayuda a identificar procesos que emiten I/O, mientras que iostat reporta la actividad de dispositivos y particiones. Interpreta cada campo según el tipo de dispositivo y su línea base. Un valor de %util, por ejemplo, no tiene un umbral de saturación universal en todas las arquitecturas de almacenamiento. Tiempos de espera agotados (timeouts), reinicios, errores del sistema de archivos o un dispositivo desconectado en los registros del kernel están más cerca de la causa de una falla que la profundidad de cola por sí sola.

Si wchan o los puntos de montaje indican NFS, FUSE o almacenamiento de red, inspecciona el estado de montaje, nfsiostat, retransmisiones de cliente, latencia de red y salud del servidor. Las esperas ordinarias de RPC por HTTP o base de datos suelen ser interrumpibles y pueden no entrar en el load average de Linux, por lo que las trazas de aplicaciones, los pools de conexiones y la latencia de dependencias aún pertenecen a la misma línea de tiempo.

Si aumentan el PSI de memoria, el swapping o los major faults, inspecciona los eventos de memoria de cgroup, los working sets anónimos y de archivos, la recuperación directa y el dispositivo de swap. Un almacenamiento más rápido puede reducir el costo del swapping sin solucionar un working set que supera el presupuesto de memoria.

Paso 6: Mitigar a partir de la evidencia y verificar la causalidad

La mitigación debe coincidir con el recurso de espera confirmado:

  • contención en la cola de CPU: reducir la admisión, bajar la concurrencia o la prioridad de lotes (batch), eliminar la afinidad incorrecta y agregar CPU solo en función de un modelo de capacidad medido;
  • falla de almacenamiento o NFS: detener la amplificación de I/O, cambiar a una réplica o ruta de montaje en buen estado y reparar el dispositivo, la red o el servidor;
  • presión de memoria: limitar el working set y la concurrencia, detener la carga de trabajo en thrashing y agregar memoria dentro de un límite de capacidad compatible;
  • discrepancia de alcance: aislar la carga de trabajo ruidosa o corregir las cuotas de cgroup antes de decidir si el servicio objetivo necesita escalamiento.

Un reinicio puede limpiar las tareas acumuladas, pero también puede borrar pilas y registros útiles. Si el recurso subyacente sigue sin estar disponible, los nuevos procesos se bloquearán de nuevo. Antes de actuar, preserva PIDs representativos, estados de tareas, wchan, PSI e instantáneas de subsistemas, y define el cambio métrico esperado.

La aceptación debe incluir la recuperación del p95/p99 y la tasa de errores del negocio, los recuentos de R/D de vuelta a la línea base, la disminución de la presión en el recurso PSI relevante, métricas de dispositivo/NFS/memoria/CPU recuperadas y el backlog drenado de forma segura. Dado que el load average decae gradualmente, es una señal de recuperación en lugar de la única compuerta de cierre del incidente.

Ejemplo de respuesta de alta calidad

"No catalogaría esto como sobrecarga de CPU solo porque la carga sea 48 en 16 CPUs. El load average de Linux suaviza el recuento de tareas que se están ejecutando o esperando CPU más las tareas en suspensión ininterrumpible. Con un 72% de CPU idle, la carga puede contener muchas esperas en estado D, o el agregado puede ocultar un problema por CPU, de cuota o de alcance de métricas.

48 / 36 / 18 son promedios con decaimiento exponencial. Direccionalmente, indican que las tareas activas aumentaron recientemente. No son promedios aritméticos en tres ventanas independientes y no identifican la causa. Primero me aseguraría de que la carga, la CPU y la latencia del negocio provengan del mismo host y ventana de tiempo, y luego inspeccionaría mpstat -P ALL en busca de una CPU saturada o steal time.

A continuación, compararía r y b con vmstat 1. Un valor alto y sostenido de r, CPUs ocupadas y un PSI de CPU alto me llevarían a analizar el perfil de CPU, la afinidad y el estrangulamiento de cgroup. Un valor alto de b y muchos hilos en estado D mientras las CPUs permanecen inactivas me llevarían a agrupar hilos por comando y wchan, inspeccionar /proc/12345/stack para tareas representativas y alinear el resultado con el PSI de I/O.

Supongamos que muchos hilos están esperando en una ruta relacionada con NFS, el PSI de I/O aumenta y el iostat de los dispositivos de bloque locales se mantiene normal. Investigaría los montajes, las retransmisiones de cliente, la latencia de red y el servidor NFS en lugar de actualizar el disco en la nube local. La mitigación puede consistir en detener el trabajo por lotes relevante, cambiar las lecturas a una réplica sana o retirar el nodo afectado. Matar repetidamente procesos en estado D generalmente no surtirá efecto de inmediato.

Tras la reparación, verificaría la latencia de cola (tail latency) y los errores del negocio, los recuentos de hilos R/D, el PSI del host y del cgroup, la latencia de NFS y el backlog acumulado. Los valores de carga de 1, 5 y 15 minutos decaen con el tiempo, por lo que un valor de 15 minutos aún elevado no debería desencadenar más cambios riesgosos si las esperas actuales y los resultados de los usuarios ya son estables."

Errores comunes

  • Tratar el load average como utilización de CPU → cuenta tareas e incluye suspensión ininterrumpible → separa r de b y R de D antes de diagnosticar contención de CPU.
  • Declarar sobrecarga siempre que la carga exceda el recuento de CPUs → esa regla es solo un indicio aproximado para la demanda dependiente de CPU → combina CPU busy, PSI de CPU y la cola ejecutable.
  • Tratar 1, 5 y 15 como simples promedios de ventana → Linux usa decaimiento exponencial y retiene muestras más antiguas → usa los tres valores para conocer la dirección y confirma el presente con métricas actuales.
  • Atribuir cada tarea D a un disco local → NFS, sistemas de archivos, controladores y otras esperas del kernel pueden ser ininterrumpibles → rastrea wchan, pilas y el subsistema correspondiente.
  • Descartar I/O porque iowait es bajo → iowait es contabilidad de tiempo de CPU, no un recuento de tareas bloqueadas → inspecciona tareas D, PSI de I/O, dispositivos y latencia de almacenamiento remoto.
  • Observar únicamente la CPU promedio del host → una CPU saturada, afinidad, cuotas u otro cgroup pueden quedar ocultos por el promedio → compara métricas por CPU, de host y del cgroup objetivo.
  • Emitir repetidamente kill -9 a tareas atascadas → la señal espera a que la operación ininterrumpible retorne y se puede perder evidencia → preserva la evidencia y repara el recurso esperado.
  • Llamar a un solo valor de wchan la causa raíz → solo identifica el sitio actual de suspensión en el kernel → exige agrupación, correlación temporal y evidencia de subsistemas.
  • Esperar a que el load average llegue a cero antes de declarar la recuperación → el decaimiento tiene retraso y los sistemas sanos no requieren carga cero → acepta la recuperación a partir de los resultados de los usuarios, tareas actuales, PSI y métricas de recursos.

Preguntas de seguimiento y respuestas

Pregunta de seguimiento 1: ¿Por qué %iowait también puede ser bajo cuando el CPU idle es alto?

%iowait es la fracción de tiempo de CPU que está inactiva mientras el sistema contabiliza I/O pendiente. Es contabilidad de tiempo de CPU. Las tareas pueden estar bloqueadas en NFS, en un controlador o en otra espera ininterrumpible del kernel mientras las CPUs ejecutan otro trabajo o permanecen en inactividad ordinaria. La agregación entre muchas CPUs también puede diluir un síntoma local. Utiliza recuentos de estado D, PSI de I/O, wchan y latencia de subsistemas; un iowait bajo por sí solo no puede excluir I/O o una espera del kernel.

Pregunta de seguimiento 2: ¿El load average observado dentro de un contenedor representa a ese contenedor?

No asumas que lo hace. La carga visible y el alcance de /proc dependen del host, el namespace de PID, el runtime y la implementación de monitoreo, mientras que la CPU de la aplicación puede tener un alcance de cgroup. Lee el PSI de CPU, I/O y memoria del host y del cgroup objetivo más los eventos de cuota, y atribuye los hilos a los cgroups. Si la carga del host es alta pero el cgroup objetivo no tiene presión, escalar ese servicio puede no ayudar.

Pregunta de seguimiento 3: Con una carga de 48 y un 72% de CPU idle, ¿debe haber necesariamente muchas tareas en estado D?

No. Las métricas pueden estar desincronizadas, el idle agregado puede ocultar una CPU saturada, las tareas pueden estar limitadas por afinidad o una cuota de cgroup, o la carga puede haber caído recientemente mientras los promedios exponenciales todavía retienen el pico. Verifica el recuento ejecutable actual en /proc/loadavg, vmstat r/b, la utilización por CPU, los recuentos de hilos R/D y las marcas de tiempo de recolección para determinar la composición.

Pregunta de seguimiento 4: ¿Por qué un proceso en estado D a veces sobrevive a kill -9?

La suspensión ininterrumpible permite que algunas operaciones del kernel superen una fase crítica sin la interrupción de señales ordinarias. SIGKILL puede quedar pendiente, pero la tarea generalmente debe retornar de la espera y alcanzar una ruta que pueda salir antes de que el proceso desaparezca. Reparar la espera en el dispositivo, montaje, red o controlador suele ser más importante que repetir la señal. Un reinicio del host, si es necesario, debe evaluarse frente a la integridad de los datos y la redundancia del servicio.

Pregunta de seguimiento 5: ¿Cómo se deben configurar las alertas de load average?

No copies un umbral fijo de "carga mayor que el número de CPUs". Para servicios dependientes de CPU, combina carga, cola ejecutable, PSI de CPU, utilización y estrangulamiento de cgroup. Para servicios intensivos en I/O, combina PSI de I/O, estados D, latencia del dispositivo o almacenamiento remoto y el SLO del negocio. Establece los umbrales a partir de la línea base normal, la duración, el tiempo de escalamiento y el impacto en el usuario, y etiqueta el alcance de cada métrica.

Fuentes públicas

Preguntas relacionadas