El hábito de reiniciar es un impuesto que pagas para siempre. Te compra unos minutos de calma, borra tus huellas de la escena y garantiza silenciosamente que verás el mismo incidente otra vez—usualmente a las 2:13 AM, durante un deploy, cuando alguien “solo necesita que vuelva”.
Ubuntu 24.04 es una base sólida. Cuando algo sale mal, rara vez es porque el SO se levantó sintiéndose caótico. Es porque pasó algo medible: se acumuló una cola, la presión de memoria cruzó un umbral, un worker del kernel se atascó, una NIC hizo flapping, un sistema de archivos se pausó, un servicio quedó en un estado malo. Tu trabajo no es reiniciar la evidencia. Tu trabajo es aislar la causa raíz y decidir la corrección más pequeña y segura.
Reiniciar no es una solución: la mentalidad en producción
Un reinicio es un instrumento contundente. Limpia la memoria, reinicia controladores, mata procesos atascados y hace que las métricas se vean “bien” porque reinicias los relojes. Es el equivalente técnico de bajar la música para encontrar el ruido en el motor del coche: te sentirás mejor, pero el motor sigue muriendo.
En producción optimizas para la recuperación repetible y el aislamiento de la causa raíz. Eso significa:
- Contención primero: detener el impacto al usuario, limitar el radio de afectación, reducir la carga.
- Captura de evidencia: logs, estado, contadores, colas—antes de reiniciarlos.
- Cambio más pequeño reversible: reiniciar un servicio, recargar configuración, drenar un nodo, deshabilitar una feature flag.
- Causa raíz: demuéstrala con datos, no con sensaciones.
Si tu proceso es “reiniciar y esperar”, estás entrenando a tu organización para aceptar caídas inexplicadas como normales. Eso no es resiliencia. Es síndrome de Estocolmo con dashboards de uptime.
Una cita para tener en la pared: Gene Kranz (director de vuelo del Apollo) promovía una cultura de “duros y competentes”. Idea parafraseada: Sé duro y competente—usa procesos disciplinados bajo presión.
Eso es trabajo de ops un martes cualquiera.
Broma #1: Reiniciar para arreglar producción es como meter tu teléfono en el microondas porque va lento. Puede que se caliente, pero no estás resolviendo el problema correcto.
Hechos y contexto: por qué esto sigue ocurriendo
Aquí hay hechos concretos, no mitos, que ayudan a explicar por qué “un reinicio lo arregló” es tan común—y tan engañoso:
- Linux solía necesitar menos “reiniciar para aplicar cambios” que Windows, pero aún existen reinicios de controladores y bugs del kernel. Muchas “soluciones con reinicio” son en realidad historias de “reseteo del estado del driver”.
- systemd hizo la gestión de servicios mucho más consistente que scripts init ad-hoc. Eso también significa que a menudo puedes arreglar problemas con un
systemctl restartdirigido en lugar de un reinicio total. - El movimiento de Ubuntu a nombres de interfaz de red predecibles redujo el caos de “eth0 desapareció”, pero una netplan mal configurada aún puede causar problemas sutiles de enlace/ruta que persisten hasta recargarla.
- cgroups evolucionaron de “agradables de tener” a “plano de control de recursos” (especialmente con contenedores). Muchos “ralentizaciones aleatorias” son en realidad throttling de cgroup, presión de memoria o pesos de IO haciendo exactamente lo que pediste.
- NVMe trajo latencias increíbles—más nuevos modos de fallo: peculiaridades de firmware, administración de energía PCIe y errores intermitentes de medio que aparecen como bloqueos de IO, no fallos limpios.
- El OOM killer no es un error; es una decisión de política. Mata algo para mantener vivo el kernel. Reiniciar tras un OOM a menudo es negarse a aprender qué proceso se comió la máquina.
- journald y sus logs estructurados cambiaron la respuesta a incidentes: puedes filtrar por boot, unidad, prioridad, PID y ventana de tiempo. Esa es la evidencia que no tenías con archivos de texto dispersos.
- Los kernels modernos pueden “colgarse” sin crashear: soft lockups, stalls de RCU, IO bloqueado y esperas de transacción en sistemas de archivos. El servidor parece vivo, pero el progreso hacia delante desaparece.
- Los entornos cloud hicieron que “reiniciar” fuera peligrosamente barato: el hábito se trasladó de equipos de escritorio a flotas, y de repente nadie recuerda preservar datos forenses.
Ubuntu 24.04 (Noble) es especialmente “observable” si usas lo que ya incluye: systemd, journald, logs del kernel, contadores de rendimiento y las métricas que deberías tener de todos modos. El playbook abajo asume que estás dispuesto a mirar.
Playbook de diagnóstico rápido (primero/segundo/tercero)
Esta es la secuencia de triage que encuentra cuellos de botella rápidamente sin perderte en trivialidades. Úsala cuando suene la página y tengas minutos para apagar parcialmente el fuego.
Primero: establece el modo de fallo (¿es CPU, memoria, disco o red?)
- ¿El equipo es receptivo? ¿Puedes SSH? ¿Puedes ejecutar comandos en 1–2 segundos?
- ¿El load average miente? Load puede estar alto por presión de CPU ejecutable o porque tareas están atascadas en sleep de IO ininterrumpible.
- ¿Hay swapping activo u OOM? La presión de memoria causa fallos en cascada: asignaciones lentas, tormentas de swap, IO, timeouts.
- ¿Está subiendo la latencia de disco? Await alto / colas largas congelarán todo lo que toque almacenamiento.
- ¿La red es el cuello de botella? Retransmisiones, drops, fallos de DNS, incompatibilidades MTU—clásico “está abajo pero está arriba”.
Segundo: identifica el “quién” (qué proceso/unidad y qué dependencia)
- Ofensores principales: hog de CPU, fuga de memoria, hilos atascados o demasiados procesos.
- Mapeo de dependencias: ¿tu app espera DB, DNS, NFS, object store o disco local?
- Salud del servicio: estado de unidad systemd, loops de reinicio, triggers de watchdog.
Tercero: toma la acción correctiva más pequeña y segura, luego confirma con métricas
- Reduce la carga: drena el nodo del LB, pausa trabajos batch, limita la tasa, desactiva feature flags costosos.
- Reinicio dirigido: reinicia el servicio, no la máquina, a menos que estés haciendo un reset controlado de kernel/driver por un problema conocido.
- Confirma: ¿bajó la latencia, disminuyó la tasa de errores, se vaciaron las colas, se normalizó el uso de recursos?
- Captura evidencia: incluso si debes reiniciar, guarda extractos del journal, logs del kernel y el estado antes.
Esa secuencia evita la trampa de “vi load alto, por lo tanto CPU,” que es cómo la gente termina reasignando instancias mientras el verdadero culpable es una cola de disco atascada detrás de un triste timeout de NVMe.
Tareas prácticas (comandos, salidas, decisiones)
A continuación hay tareas prácticas que puedes ejecutar en Ubuntu 24.04 durante un incidente. Cada una incluye: comando, un fragmento de salida realista, qué significa y la decisión que tomas.
Tarea 1: Identificar si miras presión de CPU o espera de IO
cr0x@server:~$ uptime
14:22:10 up 18 days, 3:11, 2 users, load average: 18.72, 17.95, 16.40
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
6 0 0 412180 90244 3218120 0 0 12 110 980 2100 45 10 40 5 0
3 2 0 398200 90244 3221200 0 0 240 9010 1200 2600 18 6 22 54 0
2 4 0 390112 90244 3221456 0 0 180 12050 1180 2500 10 4 18 68 0
Significado: el load está alto, pero b (bloqueados) está subiendo y wa (IO wait) es enorme. Esto no es “solo CPU.” Es “hilos atascados esperando almacenamiento”.
Decisión: deja de escalar CPU. Pivotar a latencia de disco y comprobaciones de filesystem/RAID/NVMe.
Tarea 2: Comprobar latencia por disco y profundidad de cola
cr0x@server:~$ iostat -x 1 3
Linux 6.8.0-41-generic (server) 12/30/2025 _x86_64_ (8 CPU)
Device r/s w/s rkB/s wkB/s aqu-sz await r_await w_await %util
nvme0n1 12.0 220.0 384.0 9012.0 18.40 78.20 6.10 82.10 99.2
nvme1n1 0.0 0.0 0.0 0.0 0.00 0.00 0.00 0.00 0.0
Significado: %util ~99% y await ~78ms en nvme0n1 es malo para un sistema que espera latencias de milisegundos bajos. aqu-sz está profundo: las solicitudes están encoladas.
Decisión: encuentra qué está escribiendo, revisa el sistema de archivos, busca saturación o errores y considera limitar al causante.
Tarea 3: Identificar los mayores escritores de IO por proceso
cr0x@server:~$ sudo iotop -oPa
Total DISK READ: 1.10 M/s | Total DISK WRITE: 102.45 M/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
8921 be/4 postgres 0.00 B/s 68.20 M/s 0.00 % 7.10 % postgres: checkpointer
25140 be/4 root 0.00 B/s 22.30 M/s 0.00 % 3.20 % /usr/bin/rsync -aH --delete /var/lib/app/ /mnt/backup/
Significado: PostgreSQL checkpointer y un job de backup están escribiendo intensamente. El backup puede estar robando IO en el peor momento.
Decisión: pausa/renice/ionice el backup, confirma que los checkpoints de la DB no estén mal sintonizados y verifica que no estés snapshotando en pico.
Tarea 4: Confirmar presión de memoria y comportamiento de swap
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 31Gi 28Gi 510Mi 2.1Gi 2.5Gi 1.1Gi
Swap: 4.0Gi 3.6Gi 410Mi
Significado: Swap se está usando mucho; “available” es baja. Esto a menudo convierte una latencia “aceptable” en un pantano.
Decisión: encuentra el consumidor de memoria, detén la fuga, constríñelo via systemd/cgroups, o escala memoria—pero solo después de probar que no es un job descontrolado.
Tarea 5: Capturar eventos OOM y la víctima
cr0x@server:~$ journalctl -k -b | grep -i -E "oom|out of memory|killed process" | tail -n 5
Dec 30 13:58:41 server kernel: Out of memory: Killed process 18221 (java) total-vm:9643212kB, anon-rss:6123400kB, file-rss:10240kB, shmem-rss:0kB, UID:1001 pgtables:18432kB oom_score_adj:0
Significado: El kernel mató un proceso Java por agotamiento de memoria. Reiniciar “lo arregla” porque eliminaste al agresor y limpiaste caches, no porque el sistema sanó.
Decisión: arregla el dimensionamiento/límites de memoria, busca la fuga, añade guardrails (MemoryMax en systemd, límites de contenedor) y confirma que los ajustes de heap de la app coinciden con la realidad.
Tarea 6: Encontrar qué unidad está haciendo flapping o en loop de reinicio
cr0x@server:~$ systemctl --failed
UNIT LOAD ACTIVE SUB DESCRIPTION
● app-api.service loaded failed failed App API service
cr0x@server:~$ systemctl status app-api.service --no-pager -l
× app-api.service - App API service
Loaded: loaded (/etc/systemd/system/app-api.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Mon 2025-12-30 14:10:18 UTC; 2min 1s ago
Process: 24410 ExecStart=/usr/local/bin/app-api (code=exited, status=1/FAILURE)
Memory: 1.2G
CPU: 11.203s
Dec 30 14:10:18 server app-api[24410]: FATAL: cannot connect to Redis: dial tcp 10.20.0.15:6379: i/o timeout
Dec 30 14:10:18 server systemd[1]: app-api.service: Main process exited, code=exited, status=1/FAILURE
Dec 30 14:10:18 server systemd[1]: app-api.service: Failed with result 'exit-code'.
Significado: La app no está “rota”; falla porque Redis es inalcanzable o lento. Reiniciar el host de la app no arreglará una ruta de red o una sobrecarga de Redis.
Decisión: pivotar a la dependencia: prueba la accesibilidad a Redis, comprueba su latencia y valida enrutamiento/firewall.
Tarea 7: Revisar advertencias del kernel que insinúan stalls o resets de drivers
cr0x@server:~$ journalctl -k -b -p warning..alert --no-pager | tail -n 20
Dec 30 14:01:12 server kernel: INFO: task kworker/u16:3:1123 blocked for more than 120 seconds.
Dec 30 14:01:12 server kernel: nvme nvme0: I/O 224 QID 3 timeout, aborting
Dec 30 14:01:42 server kernel: nvme nvme0: Abort status: 0x371
Dec 30 14:02:10 server kernel: EXT4-fs warning (device nvme0n1p2): ext4_end_bio:340: I/O error 10 writing to inode 524313 (offset 0 size 4096)
Significado: Timeouts de NVMe y errores de IO en ext4 no son “lentitud aleatoria”. Son un problema de almacenamiento, potencialmente hardware o firmware.
Decisión: protege los datos, planifica mantenimiento, revisa SMART/NVMe health, considera retirar el dispositivo y deja de pretender que un reinicio es “reparación”.
Tarea 8: Inspeccionar salud de NVMe y log de errores
cr0x@server:~$ sudo nvme smart-log /dev/nvme0
Smart Log for NVME device:nvme0 namespace-id:ffffffff
critical_warning : 0x00
temperature : 49 C
available_spare : 100%
available_spare_threshold : 10%
percentage_used : 7%
data_units_read : 193,421,112
data_units_written : 882,100,420
media_errors : 12
num_err_log_entries : 98
cr0x@server:~$ sudo nvme error-log /dev/nvme0 | head -n 8
Error Log Entries for device:nvme0 entries:64
Entry[ 0]
error_count : 98
sqid : 3
cmdid : 0x00d1
status_field : 0x4004
lba : 182736128
Significado: media_errors y un log de errores creciente se correlacionan con los timeouts del kernel. Esto tiende hacia una falla real.
Decisión: planifica el reemplazo, reduce la amplificación de escritura, verifica backups y mueve servicios críticos fuera de ese dispositivo.
Tarea 9: Validar espacio/inodos del sistema de archivos (el generador de outages aburrido)
cr0x@server:~$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p2 220G 218G 1.2G 100% /
tmpfs 16G 1.2G 15G 8% /run
cr0x@server:~$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/nvme0n1p2 14417920 14399811 18109 100% /
Significado: Disco lleno o agotamiento de inodos causa fallos “aleatorios”: el servicio no puede escribir archivos PID, fallan logs, las bases de datos rechazan commits, apt se rompe, los sockets fallan.
Decisión: borra/rota logs, limpia releases antiguos, arregla creación masiva de archivos, añade cuotas y configura alertas antes de que llegue al 100% otra vez.
Tarea 10: Detectar agotamiento de descriptores de archivo (el limitador furtivo)
cr0x@server:~$ cat /proc/sys/fs/file-nr
10240 0 1048576
cr0x@server:~$ sudo lsof | wc -l
245112
Significado: El techo de manejadores de archivos a nivel sistema está bien aquí, pero la enorme cantidad de archivos abiertos sugiere alta concurrencia o una fuga (sockets/archivos que no se cierran).
Decisión: revisa límites por proceso (ulimit, systemd LimitNOFILE=), identifica el proceso que filtra y arréglalo—no reinicies para “cerrar archivos”.
Tarea 11: Probar pérdida de red, retransmisiones y rarezas de ruta
cr0x@server:~$ ip -s link show dev enp5s0
2: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 3c:ec:ef:12:34:56 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
10498312323 8123312 0 24810 0 12901
TX: bytes packets errors dropped carrier collsns
9983211121 7921101 0 120 0 0
cr0x@server:~$ ss -s
Total: 2135 (kernel 0)
TCP: 1980 (estab 1120, closed 650, orphaned 3, timewait 645)
Transport Total IP IPv6
RAW 0 0 0
UDP 62 55 7
TCP 1330 1211 119
INET 1392 1266 126
FRAG 0 0 0
Significado: Los drops en RX son significativos. Eso no es “la app está lenta”, eso es “paquetes se están perdiendo”, lo que provoca reintentos, timeouts y dashboards tristes.
Decisión: investiga tamaños de anillos de la NIC, saturación de softirq en CPU, errores en el puerto del switch, incompatibilidades MTU y picos de tráfico. Reiniciar puede limpiar colas temporalmente, pero no arreglará un enlace malo o oversubscription.
Tarea 12: Comprobar fallos de DNS rápidamente (porque todo depende de ello)
cr0x@server:~$ resolvectl status
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Current DNS Server: 10.10.0.53
DNS Servers: 10.10.0.53 10.10.0.54
Link 2 (enp5s0)
Current Scopes: DNS
DNS Servers: 10.10.0.53 10.10.0.54
cr0x@server:~$ dig +time=1 +tries=1 api.internal A @10.10.0.53
; <<>> DiG 9.18.24-1ubuntu0.1-Ubuntu <<>> +time=1 +tries=1 api.internal A @10.10.0.53
;; connection timed out; no servers could be reached
Significado: DNS está agotando el tiempo. Muchos servicios fallan “misteriosamente” cuando la resolución de nombres se paraliza.
Decisión: cambia a resolvers alternativos, arregla el DNS upstream y evita reinicios de apps que solo amplifican la carga en una capa DNS moribunda.
Tarea 13: Inspeccionar throttling de cgroup (contendores y systemd lo hacen)
cr0x@server:~$ systemctl show app-api.service -p CPUQuota -p MemoryMax -p IOWeight
CPUQuota=50%
MemoryMax=2147483648
IOWeight=100
Significado: Has limitado explícitamente CPU a 50% y memoria a 2GiB. Si el servicio está lento bajo carga, puede que esté obedeciendo tus restricciones, no comportándose mal.
Decisión: confirma si el throttling se alinea con los SLO; ajusta cuotas deliberadamente, no “arregles” reiniciando con los mismos límites.
Tarea 14: Capturar evidencia antes de cambiar nada
cr0x@server:~$ sudo journalctl -b --since "2025-12-30 13:30" --until "2025-12-30 14:30" -o short-iso > /tmp/journal-incident.txt
cr0x@server:~$ sudo dmesg -T > /tmp/dmesg-incident.txt
cr0x@server:~$ ps -eo pid,ppid,cmd,%cpu,%mem,stat --sort=-%cpu | head -n 15 > /tmp/ps-topcpu.txt
cr0x@server:~$ ps -eo pid,ppid,cmd,%cpu,%mem,stat --sort=-%mem | head -n 15 > /tmp/ps-topmem.txt
Significado: Ahora has preservado la historia. Si debes reiniciar servicios—o incluso el host—no estás tirando las pistas.
Decisión: procede con mitigaciones sabiendo que aún puedes hacer un RCA posterior basado en los artefactos capturados.
Broma #2: Si reiniciar es tu único paso de troubleshooting, felicidades—has inventado un botón de encendido muy caro.
Tres mini-historias corporativas (realistas, dolorosas, útiles)
Mini-historia 1: El incidente causado por una suposición equivocada
Tenían una capa interna de API en Ubuntu. Cuando la latencia subió, el reflejo on-call fue reiniciar el servicio API. Cuando eso falló, reiniciaron la VM. Funcionaba lo suficiente como para que nadie lo cuestionara.
Un viernes, el reinicio no ayudó. Los errores volvieron de inmediato: timeouts a un cluster de cache. El comandante del incidente supuso “el cache está caído”. Entonces llamaron al equipo de cache, luego al de red, luego a seguridad. Clásico deporte corporativo de sangre: tres equipos discutiendo en un chat mientras los clientes esperan.
El problema real fue más estúpido y más instructivo. Un cambio nuevo en netplan había añadido una ruta estática que accidentalmente sombreaba la subred del cache vía una puerta equivocada. La mayor parte del tráfico aún funcionaba porque la ruta por defecto estaba bien. Solo el tráfico de cache tomaba la ruta escénica por un firewall que lo rateaba.
Los reinicios “lo arreglaban” antes porque la ruta a veces no se aplicaba consistentemente después de pushes parciales de configuración—temporalidad y estado. Esta vez la ruta se aplicó limpiamente, por lo que rompió de forma determinista. El reinicio no reseteó la ruta mala; la recargó.
Después cambiaron dos cosas: (1) tratar “dependencia inalcanzable” como un problema de red/ruta hasta demostrar lo contrario, y (2) almacenar diffs de rutas y configurar validación en CI. El hábito de reiniciar estaba enmascarando una mala configuración, no resolviendo incidentes.
Mini-historia 2: La optimización que salió mal
Un servicio intensivo en almacenamiento fue “optimizado” moviendo logs a NVMe local más rápido y aumentando la verbosidad de logs para facilitar debug. El equipo también apretó la rotación de logs porque habían sufrido disco lleno antes. Motivos sensatos. Mala interacción.
A escala, los logs verbosos implicaron escrituras frecuentes. El cron de logrotate era agresivo y el hook post-rotate enviaba señales para recargar múltiples servicios. Bajo tráfico en ráfagas, logrotate entraba, comprimía logs y provocaba picos de CPU e IO justo cuando la app más lo necesitaba.
Los usuarios veían caídas de latencia periódicas cada hora. On-call reiniciaba nodos porque “limpia la lentitud”. El reinicio ayudaba porque interrumpía la compresión y reseteaba colas. Nadie conectó el patrón horario porque la gente es mala con series temporales en la cabeza.
Cuando finalmente graficaron await de disco e iowait de CPU, fue obvio: cada caída coincidía con logrotate. La solución fue aburrida: reducir volumen de logs, pasar a shipping asíncrono, repartir rotación y eliminar hooks de recarga innecesarios. También añadieron alertas en latencia de disco, no solo en “porcentaje de disco usado”.
La conclusión: “optimizar” sin medir efectos de segundo orden es solo apostar con mejor vocabulario.
Mini-historia 3: La práctica aburrida y correcta que salvó la noche
Una fintech ejecutaba nodos Ubuntu 24.04 para procesamiento de transacciones. Tenían una regla estricta de incidente: antes de cualquier reinicio, capturar journal y logs del kernel para la ventana relevante, más un snapshot del estado de procesos y red. Sin excepciones a menos que el host esté corrompiendo datos.
Una noche, un subconjunto de nodos empezó a estancarse. No caerse. Solo estancarse: load elevado, latencias subiendo, timeouts intermitentes. La “solución” más rápida habría sido reciclar los nodos. En cambio, el on-call siguió la regla y capturó evidencia.
Los logs del kernel mostraron timeouts de NVMe, pero solo tras patrones específicos: un pico de escrituras sincronas de una versión de servicio concreta. Los snapshots de procesos mostraron que esa versión había activado una feature flag que aumentó la frecuencia de fsync.
Hicieron rollback de la feature flag, la latencia se estabilizó y los nodos se recuperaron sin reinicios. Más tarde, con los logs preservados, trabajaron con el proveedor para actualizar el firmware NVMe y ajustaron la estrategia de durabilidad de la app. La evidencia convirtió un misterio de medianoche en un plan accionable.
Esa regla “aburrida” no solo ayudó a diagnosticar. Evitó una falla mayor: reiniciar habría ocultado un problema de fiabilidad de almacenamiento hasta que se convirtiera en pérdida de datos. En producción, aburrido suele ser otra palabra para “seguro”.
Errores comunes: síntoma → causa raíz → corrección
1) “Load average alto significa CPU saturada”
Síntoma: Load average es 20+, la app está lenta, pero los gráficos de CPU no parecen tan mal.
Causa raíz: Tareas bloqueadas en IO (estado D). Load incluye sleep ininterrumpible; a menudo es latencia de almacenamiento.
Corrección: Usa vmstat (b, wa), iostat -x (await, util), luego identifica procesos que hoggean IO (iotop).
2) “Reiniciar lo arregló, así que era un problema de kernel”
Síntoma: Reinicio limpia problemas por horas/días; el incidente se repite.
Causa raíz: Fuga de memoria, fuga de descriptores, acumulación gradual de colas, disco lleno o dependencia atascada.
Corrección: Captura evidencia; rastrea crecimiento (RSS, archivos abiertos, disco usado, longitudes de cola). Reinicia la unidad ofensora y arregla la fuga o los límites subyacentes.
3) “La aplicación está caída” cuando en realidad es DNS
Síntoma: Timeouts aleatorios a servicios internos; reiniciar apps no cambia nada.
Causa raíz: Timeouts del resolver, upstream roto o split-horizon mal configurado.
Corrección: Revisa resolvectl y prueba consultas con timeouts cortos (dig +time=1 +tries=1). Cambia resolvers o arregla la capa DNS.
4) “El disco no está lleno, así que no es storage”
Síntoma: Espacio libre hay, pero IO está lento; servicios se cuelgan.
Causa raíz: Picos de latencia por errores de dispositivo, firmware, amplificación de escrituras o un escritor ruidoso. También puede haber agotamiento de inodos con bytes libres (o viceversa).
Corrección: Revisa latencia (iostat), errores (journalctl -k), salud (nvme smart-log) e inodos (df -i).
5) “Debe ser networking” cuando en realidad es softirq de CPU o conntrack
Síntoma: Paquetes perdidos, timeouts intermitentes, conteos de conexión altos.
Causa raíz: CPU consumida en softirq tratando paquetes, o presión en la tabla conntrack causando drops/timeouts, a menudo por ráfagas.
Corrección: Correlaciona drops en RX con uso de CPU y estadísticas de conexiones; mitiga aislando tráfico, ajustando o distribuyendo carga entre nodos.
6) “Los loops de reinicio son inofensivos”
Síntoma: Un servicio hace flap; a veces “vuelve”, a veces no.
Causa raíz: Timeout de dependencia, configuración mala o límite de recursos alcanzado. Los loops de reinicio amplifican la carga y pueden causar cascadas (thundering herd).
Corrección: Inspecciona systemctl status, establece backoff de reinicio sensato y arregla la salud de dependencias o la configuración. Prefiere circuit breakers sobre reinicios a ciegas.
7) “Aumentamos rendimiento haciendo todo síncrono”
Síntoma: Caídas de latencia durante ráfagas; métricas de almacenamiento muestran picos.
Causa raíz: fsync excesivo o escrituras síncronas, especialmente si varios servicios comparten un dispositivo.
Corrección: Mide el patrón de IO; agrupa escrituras, ajusta configuraciones de durabilidad conscientemente, aísla cargas de trabajo o mueve logs/escrituras temporales fuera de rutas críticas.
8) “Es una fuga de memoria” cuando en realidad es cache de páginas + carga
Síntoma: Memoria libre baja, la gente entra en pánico.
Causa raíz: Linux usa memoria para cache; “free” bajo es normal. La señal es “available” y actividad de swap, no “free”.
Corrección: Usa free -h, vmstat (si/so) y tendencias de RSS de la app. Arregla solo si available colapsa o comienza churn de swap.
Listas de verificación / plan paso a paso
Checklist A: La rutina de 10 minutos “no reiniciar todavía”
- Confirma impacto: qué falla (API, DB, disco, DNS) y para quién (una AZ/nodo vs global).
- Captura evidencia: ventana del journal, dmesg, procesos top, snapshot de red. (Usa la Tarea 14.)
- Clasifica el cuello de botella: CPU vs memoria vs disco vs red usando
vmstat,iostat,free,ip -s link. - Encuentra al culpable: proceso top CPU/mem, escritores de IO, unidad flapping.
- Revisa errores de dependencias: logs de la app por “cannot connect” y timeouts; valida DNS rápidamente.
- Mitiga de forma segura: drena del LB, detén jobs batch, reduce concurrencia, pausa backups.
- Reinicio dirigido si es necesario: reinicia un servicio o recarga config; confirma recuperación con métricas.
- Solo entonces considera reiniciar: escenario de reset de driver/firmware, kernel panic loop o deadlock irrecuperable—después de capturar evidencia.
Checklist B: Si debes reiniciar, hazlo como adulto
- Declara tu motivo: “Reiniciando para resetear el controlador NVMe tras timeouts”, no “porque está lento”.
- Preserva evidencia primero: snapshots de journal/dmesg; registra versiones de kernel y firmware actuales.
- Drena tráfico: saca el nodo de rotación.
- Reinicia y valida: confirma que el síntoma desaparece y vigila si reaparece bajo carga.
- Abrir tarea de seguimiento: el análisis de causa raíz es obligatorio; si no, solo has programado el incidente otra vez.
Checklist C: Flujo de trabajo post-incidente (la parte que todos se saltan)
- Línea de tiempo: cuándo empezaron los síntomas, qué cambió, qué empeoró, qué lo arregló.
- Correlaciona señales: latencia de disco vs tasa de errores, presión de memoria vs timeouts, drops de paquetes vs reintentos.
- Prueba una causa raíz: elige el conjunto más pequeño de hechos que explique la mayoría de los síntomas.
- Define prevención: cambio de config, límite, alerta, plan de capacidad, actualización de runbook o política de rollback.
- Añade una prueba/guardrail: validación en CI para rutas netplan, alertas para uso de inodos, autoscaling basado en SLOs, etc.
Preguntas frecuentes
1) ¿Cuándo es realmente correcto reiniciar?
Cuando tienes evidencia de un deadlock de kernel/driver, reinicios repetidos de NVMe, o un bug conocido con workaround documentado—y has capturado logs antes. También cuando el host está corrompiendo datos o no puede avanzar y la contención requiere retirarlo.
2) ¿Por qué un reinicio “arregla” fugas de memoria?
Porque mata el proceso que filtra y limpia el estado de memoria. La fuga sigue ahí. Solo reinicias el temporizador hasta que vuelva a llenar la RAM.
3) ¿Cómo digo rápido si es saturación de CPU o espera de IO?
vmstat 1: alto us/sy con wa bajo sugiere CPU. b en aumento y wa alto sugiere IO wait. Confirma con iostat -x para latencia de dispositivo.
4) ¿Por qué el load average está alto aunque la CPU esté idle?
Porque load incluye tareas atascadas en sleep ininterrumpible (a menudo IO). Cuentan en load pero no consumen ciclos de CPU.
5) journald se siente “diferente”. ¿Cómo lo uso sin perderme?
Filtra por boot (-b), ventana de tiempo (--since/--until), unidad (-u) y prioridad (-p). Trátalo como un motor de consultas, no como una competición de scroll.
6) ¿Cuál es la señal de fallo de disco más infraestimada?
Picos de latencia y timeouts intermitentes de IO en logs del kernel. Los discos pueden estar “up” y “no llenos” pero fallando en lo que importa: completar IO de forma rápida y correcta.
7) ¿Qué hago si una dependencia está lenta pero no caída?
Mide y aísla: añade timeouts, circuit breakers y backpressure. Reduce la carga sobre la dependencia (control de cache stampede, límites de consultas) y separa inquilinos ruidosos. “No caída” puede significar “inutilizable”.
8) ¿Cómo evito que la gente reinicie como reflejo?
Haz que la captura de evidencia y la remediación dirigida sean la opción por defecto. Añade una regla simple: “No reinicio sin hipótesis declarada y logs preservados.” Luego recompensa mitigaciones rápidas y correctas—no heroísmos nocturnos dramáticos.
9) ¿Cuál es la forma más rápida de detectar “disco lleno” antes de que sea outage?
Alerta tanto por uso de df -h como por uso de inodos df -i, además de latencia de escritura. Disco lleno suele estar precedido por aumento en volumen de logs o creación masiva de archivos—ambos medibles.
10) ¿Por qué reiniciar un servicio ayuda más que reiniciar todo a veces?
Porque resetea el estado roto (conexiones muertas, hilos atascados, descriptores filtrados) sin borrar todo el sistema. Es más rápido, menos riesgoso y preserva otros servicios sanos.
Próximos pasos para reducir incidentes (sin heroísmos)
Deja de usar reinicios como soporte emocional. En Ubuntu 24.04 ya tienes las herramientas para aislar la causa raíz: systemd, journald, logs del kernel y contadores de rendimiento que te dicen dónde está realmente el cuello de botella.
Haz lo siguiente:
- Adopta la rutina de 10 minutos: captura evidencia, clasifica el cuello de botella, encuentra al culpable y luego mitiga.
- Establece “no reiniciar sin hipótesis” como norma: escribe la razón en el canal/ticket del incidente.
- Alerta sobre las cosas correctas: latencia de IO, uso de inodos, actividad de swap, drops en RX—no solo CPU y “porcentaje de disco usado”.
- Limita el radio de daño: cuotas/límites para servicios, rate limits para clientes e aislamiento para cargas ruidosas.
- Practica recuperación dirigida: reinicia unidades, drena nodos, desactiva features—demuestra que puedes recuperar sin reiniciar el mundo.
No necesitas ser un susurrador de kernel. Necesitas ser disciplinado, sospechar de historias convenientes y ser alérgico a “funcionó tras reiniciar” como respuesta final.