Cuando algo falla en producción, el primer impulso suele ser tocar. Reiniciar servicios, relanzar procesos, mirar logs al azar o ejecutar comandos de memoria. Es normal: hay presión, usuarios afectados y responsables preguntando.
Pero los primeros minutos son críticos. Lo que hagas al principio puede ayudarte a resolver antes o puede borrar pistas, ocultar la causa real, empeorar el impacto o convertir una incidencia parcial en una caída completa.
Una incidencia no se gestiona solo con comandos. Se gestiona con método: alcance, síntomas, cambios recientes, logs, servicios afectados, contención, recuperación y validación.
Reiniciar puede recuperar servicio, pero también puede destruir información útil: procesos en fallo, conexiones abiertas, logs recientes o estados temporales.
date hostname uptime who last -n 10 df -h free -m top -b -n1 | head -40 systemctl --failed ss -lntp journalctl -p err -n 100 --no-pager
Antes de reiniciar, como mínimo conviene capturar estado. No para hacer una auditoría completa, sino para no quedarte ciego.
La primera pregunta real no es qué comando ejecutar, sino a quién afecta.
- Un usuario aislado - Una aplicación concreta - Un nodo - Una base de datos - Una red - Un clúster completo - Todos los clientes - Solo tráfico externo - Solo tráfico interno
No es lo mismo una caída total que un problema de acceso externo. El alcance reduce muchísimo el área de búsqueda.
¿Cuándo empezó? ¿A quién afecta? ¿Qué servicio falla? ¿Qué error ve el usuario? ¿Es intermitente o permanente? ¿Ha pasado antes? ¿Ha habido cambios recientes? ¿Hay despliegues nuevos? ¿Se ha tocado red, firewall, DNS o certificados? ¿Hay alertas relacionadas? ¿Hay otros sistemas afectados?
Una frase como “no funciona” no sirve técnicamente. Hay que convertirla en algo diagnosticable: “los usuarios externos reciben timeout desde las 09:15, pero desde red interna responde”.
08:45 - Primer aviso de lentitud 09:05 - Aumentan errores HTTP 500 09:12 - Alertas de CPU en nodo 2 09:18 - Usuarios externos reportan timeout 09:25 - Se detecta despliegue previo 09:31 - Se revisan logs de aplicación 09:40 - Se aplica rollback 09:48 - Servicio recuperado
Sin línea temporal, todo parece ruido. Con línea temporal puedes correlacionar alertas, cambios, errores y recuperación.
last last reboot journalctl --since "2 hours ago" grep -i "install\|upgrade\|remove" /var/log/dpkg.log 2>/dev/null grep -i "install\|upgrade\|remove" /var/log/yum.log 2>/dev/null grep -i "install\|upgrade\|remove" /var/log/zypp/history 2>/dev/null systemctl list-timers
Hay que revisar despliegues, configuración, firewall, certificados, DNS, actualizaciones, credenciales, secretos, tareas programadas, storage y balanceadores.
“Está caída la aplicación” puede significar muchas cosas: DNS, puerto cerrado, HTTP 500, backend caído, certificado caducado, balanceador mal configurado o base de datos no disponible.
dig dominio.com curl -I https://dominio.com curl -v https://dominio.com/api/health nc -vz host puerto ss -lntp systemctl status servicio journalctl -u servicio -n 100 --no-pager
hostname date uptime who last -n 10 df -h df -i free -m top vmstat 1 5 systemctl --failed journalctl -p err -n 100 --no-pager dmesg -T | tail -100 ip a ip r ss -lntp
Muchas incidencias complejas empiezan con algo básico: disco lleno, servicio caído, DNS roto, certificado caducado, filesystem en solo lectura, memoria agotada o puerto no escuchando.
df -h
df -i
du -sh /* 2>/dev/null
journalctl --disk-usage
du -sh /var/log/*
find /var/log -type f -size +500M -exec ls -lh {} \;
lsof | grep deleted
No basta con borrar. Hay que saber qué crece, por qué crece, qué servicio lo genera, si está abierto por un proceso y si hay rotación configurada.
uptime top mpstat 1 5 vmstat 1 5 pidstat 1 5
CPU alta no siempre significa problema. Hay que mirar carga por core, iowait, procesos bloqueados, latencia real y síntomas de servicio.
free -m cat /proc/meminfo vmstat 1 5 ps aux --sort=-%mem | head dmesg -T | grep -i "out of memory\|oom" journalctl -k | grep -i "out of memory\|oom"
Si el kernel ha matado procesos por OOM, reiniciar puede recuperar temporalmente, pero no resuelve la causa.
systemctl status servicio systemctl is-active servicio systemctl is-enabled servicio journalctl -u servicio -n 200 --no-pager systemctl --failed ss -lntp | grep puerto curl -v http://localhost:puerto/health
Un servicio puede aparecer como activo y no estar funcionando correctamente. Hay que validar proceso, puerto, logs y comportamiento real.
journalctl --since "30 minutes ago" journalctl -u servicio --since "30 minutes ago" journalctl -p err --since "2 hours ago" grep -i "error\|fail\|timeout\|denied\|refused" /var/log/syslog grep -i "error\|fail\|timeout\|denied\|refused" /var/log/messages
El último error no siempre es la causa. Muchas veces es consecuencia. Hay que buscar el primer error relevante dentro de la ventana temporal.
ip a ip r resolvectl status cat /etc/resolv.conf ping gateway dig dominio nc -vz host puerto curl -v URL traceroute host mtr host
Si desde localhost funciona pero desde fuera no, probablemente el problema no está en la aplicación: puede ser firewall, DNS, ruta, proxy, balanceador o certificado.
openssl s_client -connect dominio.com:443 -servername dominio.com /dev/null | openssl x509 -noout -dates curl -Iv https://dominio.com
Hay que revisar expiración, cadena completa, SAN correcto y qué certificado está sirviendo realmente el balanceador o backend.
nc -vz dbhost 5432 nc -vz dbhost 3306 ss -lntp journalctl -u postgresql -n 100 --no-pager journalctl -u mysql -n 100 --no-pager
Muchas aplicaciones no fallan por ellas mismas, sino porque su dependencia principal está lenta, bloqueada, llena o inaccesible.
kubectl get nodes -o wide kubectl get pods -A -o wide kubectl get events -A --sort-by=.lastTimestamp kubectl get svc -A kubectl get ingress -A kubectl get endpoints -A kubectl describe pod POD -n NAMESPACE kubectl logs POD -n NAMESPACE kubectl logs POD -n NAMESPACE --previous kubectl describe node NODE kubectl top nodes kubectl top pods -A
No basta con mirar si los pods están Running. Hay que revisar eventos, endpoints, servicios, ingress, storage, scheduling, readiness y logs anteriores.
Contener no es resolver. Es limitar impacto.
kubectl cordon NODE kubectl drain NODE --ignore-daemonsets --delete-emptydir-data kubectl rollout undo deployment/APP -n NS kubectl scale deployment APP --replicas=0 -n NS systemctl stop servicio systemctl restart servicio systemctl reload servicio
Hay que usar estas acciones con cuidado. Parar algo puede reducir el impacto o ampliarlo.
Recuperar servicio no significa resolver causa raíz. Puede recuperarse con rollback, limpieza de disco, reinicio controlado, aumento temporal de recursos o retirada de tráfico.
Después hay que entender por qué falló, por qué no se detectó antes, qué control faltaba y qué alerta o documentación hay que corregir.
curl -I https://servicio curl -s https://servicio/health systemctl status servicio journalctl -u servicio -n 100 --no-pager ss -lntp df -h free -m kubectl rollout status deployment/APP -n NS kubectl get pods -n NS kubectl get events -n NS --sort-by=.lastTimestamp kubectl logs deployment/APP -n NS --tail=100
Una incidencia no termina cuando el servicio “parece” levantado. Hay que validar usuarios, logs, métricas, colas, dependencias y estabilidad.
Comunicar bien también forma parte de la operación técnica.
Impacto: Usuarios externos no pueden acceder al login. Estado: Servicio degradado desde las 10:15. Acción: Revisando conectividad entre backend y base de datos. Siguiente paso: Validar logs de aplicación y estado de base de datos.
Una comunicación clara reduce ruido, llamadas repetidas y presión innecesaria sobre quien está resolviendo.
Qué ocurrió Cuándo empezó Cómo se detectó Qué impacto tuvo Qué acciones se tomaron Qué recuperó el servicio Cuál fue la causa raíz Qué controles fallaron Qué se hará para evitar repetición
Un buen postmortem no busca culpables. Busca mejorar el sistema.
1. Confirmar impacto 2. Identificar alcance 3. Crear línea temporal 4. Revisar cambios recientes 5. Capturar estado inicial 6. Validar síntomas 7. Revisar logs por ventana temporal 8. Comprobar recursos básicos 9. Comprobar dependencias 10. Contener impacto 11. Recuperar servicio 12. Validar recuperación 13. Comunicar estado 14. Documentar causa raíz 15. Definir acciones preventivas
Supongamos una aplicación web que empieza a responder lento y devuelve errores 500.
Primero confirmaría impacto:
curl -I https://aplicacion.com
curl -s -w "%{http_code} %{time_total}\n" -o /dev/null https://aplicacion.com
curl -s -w "%{http_code} %{time_total}\n" -o /dev/null https://aplicacion.com/api/health
Después recursos:
uptime df -h free -m vmstat 1 5 ss -lntp systemctl --failed
Luego logs por ventana temporal:
journalctl --since "30 minutes ago" -p err journalctl -u nginx --since "30 minutes ago" journalctl -u backend --since "30 minutes ago"
Si aparece timeout contra base de datos:
nc -vz dbhost 5432 journalctl -u postgresql --since "30 minutes ago"
Si el backend está saturado:
ps aux --sort=-%cpu | head ps aux --sort=-%mem | head
Si coincide con despliegue reciente, se revisa versión, se comparan cambios y se aplica rollback si procede. Después no se cierra la incidencia sin validar métricas, logs, usuarios y causa raíz.
Gestionar incidencias no consiste en saber muchos comandos. Consiste en saber en qué orden usarlos y qué pregunta responde cada uno.
Una buena operación técnica no elimina los fallos. Los convierte en situaciones diagnosticables, recuperables y cada vez menos repetibles.
Y eso, en producción, vale mucho más que reiniciar rápido y esperar que no vuelva a pasar.