Diagnosticando problemas en el hardware
Seguro alguna vez nos ha pasado, la máquina tiene un problema de hardware. Los momentos más angustiosos que se pueden pasar administrando un servidor es cuando este tiene problemas en el hardware.
Sin embargo, debemos en efecto establecer que un problema muchas veces no depende de que un dispositivo (pieza o chip) no funcione correctamente por fallas de diseño, sino que muchas veces existen conflictos entre dispositivos de la máquina (colisiones con las mismas interrupciones, etc).
Uno de los síntomas más comunes de este tipo de problema son:
1. La máquina se apaga inesperadamente
2. La PC se queda colgada (congelada) sin responder al teclado o demás
3. Los discos duros comienzan a parpadear interminablemente, o al contrario, no se mueven en largos periodos de tiempo
4. El sistema comienza a dar pánicos
5. El sistema no obedece a comandos desde el shell
Planteamiento del problema
Expondremos un caso real de un servidor que es un clon de redhat enterprise (www.centos.org) que repentinamente deja de funcionar sin previo aviso. El servidor aloja aproximadamente 120 sitios web con sus usuarios (es un servidor de hosting) el cual tiene un disco duro de 80GB, una tarjeta de red realtek 8139 (rtl8139), 1GB de memoria RAM y el procesador Intel(R) Pentium(R) 4 CPU 2.80GHz.
La situación real, al momento de ocurrir el problema es que
* el servidor deja de responder a peticiones de casi cualquier tipo, sean http, smtp, pop3, imap, ftp o ssh.
* Cualquier tipo de conexión que se intente abrir al servidor termina dando timeout.
* El servidor no rechaza las conexiones inmediatamente, sino que hace como si intenta abrir, pero al poco tiempo da timeout la conexión.
* Si se hace un telnet al puerto 25 del servidor, por ejemplo, no obtenemos la tradicional bienvenida que nos da el smtp; en vez del tradicional:
telnet srv3.misitio.com 25
Trying zzzz.www.yyy.xxx...
Connected to srv3.misitio.com (zzzz.www.yyy.xxx).
Escape character is '^]'.
220 srv3.misitio.com ESMTP Sendmail 8.12.11/8.12.11; Fri, 1 Apr 2005 15:42:18 -0500
Obtenemos sólo el inicio (es decir, el demonio responde, pero no acaba abriendo la conexión), así:
telnet srv3.misitio.com 25
Trying zzzz.www.yyy.xxx...
Connected to srv3.misitio.com (zzzz.www.yyy.xxx).
Escape character is '^]'.
Es decir, no está abriendo la sesión correcta ni completamente.
Estimación de las causas del problema:
Lo primero que hay que hacer es un estimado de qué está causando este tipo de problemas en el servidor. Es decir, que es lo que nos parece que está dejando de funcionar.
Muchas personas tienden a confundir causas con consecuencias. Por ejemplo, el que se llene la memoria ram de una máquina no significa que solucionemos el problema agregándole más ram. Pues no hemos determinado la causa que puede ser en efecto que requiramos de más memoria, pero sin embargo puede ser un script usando memoria descontroladamente y el incrementar la RAM no la solucione. Sólo nos fijamos en que la memoria se llenaba sin ver más atrás.
Así que procedamos. Por el tipo de síntomas que estamos viendo en el sistema. Al parecer existen algunas causas, muchas con tremenda validez, y otras un poco dudosas:
1- La tarjeta de red no está funcionando 100% efectivamente por la cantidad de colisiones que se dan en la red.
2- La memoria RAM del servidor se llena, pues uno de los síntomas típicos de ram llena es que el servidor no logra abrir las sesiones completamente. Sin embargo cuando es problema de ram, salen algunas indicaciones sobre procesos que no se pueden abrir en los logs. No aparece nada en los logs.
3- El disco duro o la controladora han dejado de funcionar temporal o permanentemente, pues uno de los síntomas típicos de problemas con los dispositivos de almacenamiento es que no se logran abrir las sesiones y que no se logra listar directorios o ejecutar ningún comando estando en el shell. También cuando es problema de I/O, no se pueden guardar los logs.
Estas son las conclusiones preliminares de por qué el servidor está dejando de funcionar correctamente. Todavía no es momento de atacar cualquiera de los problemas sino de estudiar un poco.
Comencemos con el punto 1
1- La tarjeta de red no funciona correctamente
Este es un problema visible, que logramos determinar al ver las estadísticas en el comando “ifconfig”
Aqui un ejemplo real de la tarjeta (hemos cambiado la IP solamente)
ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:6E:C1:3A:8A
inet addr:zzzz.xxxx.yyyy.wwww Bcast: zzzz.xxxx.wwww.223 Mask:255.255.255.224
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1875602 errors:0 dropped:0 overruns:0 frame:0
TX packets:2232760 errors:208 dropped:0 overruns:0 carrier:465
collisions:30 txqueuelen:1000
RX bytes:258344392 (246.3 Mb) TX bytes:2444720372 (2331.4 Mb)
Interrupt:10 Base address:0xf000
De toda esa información, lo más preocupante son dos errores:
carrier:465 errores. Esto normalmente significa que la portadora en el cable que conecta al equipo con el switch, está fallando y está dando errores. Puede deberse normalmente la causa a:
* el cable está dañado,
* el cable está viejo,
* la conexión de los puntos del cable tiene falsos contactos o
* el puerto del switch o de nuestra tarjeta de red están malos
collissions: 30. En un ambiente de red donde se maneje todo a base de switches (lo 100% comun en este momento en las redes) el servidor no debe tener ninguna colisión, por lo tanto hay que aclarar con el datacenter para que no nos pongan en un hub, sino en un switch decente que no genere colisiones.
Sin embargo, no es nuestra opinión que este es el problema por el que el servidor no responde, aunque puede ser un elemento que agudice la crisis, al tenerse que repetir paquetes, descartar paquetes, en fin trabajar con una red poco amiga. En todo caso, pedimos al proveedor que:
1. cambie el cable de red, y verifique que no tenga falsos contactos, y que tenga las medidas mínimas o máximas permitidas para cables 10baseT
2. De no funcionar el cable, que por favor, verifique que el server esté conectado a un switch y no a un hub y que el puerto del switch esté bueno. En todo caso que nos cambien de puerto para verificar
De no trabajar ninguno de estos dos arreglos, les solicitamos que manteniendo los dos cambios anteriores, procedan a cambiar la tarjeta.
3. Para poner las cosas peores, el proveedor no obedece a lo que le decimos (estamos en un ambiente de administración remota, el servidor en norteamérica nosotros en Ecuador) sino que procede a directamente cambiar la tarjeta de red por una 3com que supuestamente es mucho mejor.
El resultado del cambio fue que los paquetes con errores por causa de portadora (carrier) llegaban a ser casi los mismos que el total de paquetes procesados, lo que empeoró el asunto y nos demostró (?) indirectamente que parece que la tarjeta anterior no era la problemática sino que hay algo en el cable o el puerto. Posteriormente vuelven a poner la tarjeta realteck, realizan estos cambios a la vez (punto 1 y 2) y el problema de errores por carrier y colisiones se va.
Resumen para este punto: no se deben permitir colisiones en las tarjetas de red, ni errores de carrier. Cualquier otro error puede ser normal y deberse a condiciones propias de la red, y es más los otros errores a veces ocurren en ambientes de servidores congestionados o con muchos días activos (15, 30 o más días). Pero los errores por carrier siempre deben estar en 0 o muy cerca de cero si la máquina lleva varias semanas en funcionamiento (a veces pasa que falla la luz por un microcorte y sí falla el carrier pero uno o dos errores). Lo que no es normal es que una máquina con 10 o 30 minutos de funcionamiento ya tenga errores de carrier.
2- La memoria RAM del servidor se llena
Pues uno de los síntomas típicos de ram llena es que el servidor no logra abrir las sesiones completamente
Normalmente la memoria no se llena de repente, sino que se va notando que el servidor se va llenando.
Podemos monitorear la memoria RAM mediante el comando “free”, por ejemplo:
free -m
total used free shared buffers cached
Mem: 995 970 24 0 63 721
-/+ buffers/cache: 185 809
Swap: 1999 101 1898
¿Qué nos está indicando este comando? Para empezar, por mi parte no considero que tengo problemas con la memoria, veo que a simple vista está todo bien. Pero veamos los detalles:
El servidor tiene 1GB de Ram (reporta 995 pero está bien). De los cuales está usando 970 MB de memoria y tiene 24 libres (no es para asustarse, esperen!).
Estos 970 se pueden desglosar aproximadamente en:
* 63 MB buffers - son memorias de intercambio, que no son permanentes ni obligatorias tenerlas siempre
* 721MB cacheados - son páginas tomadas en algún momento del disco para ser servidas y que por su nivel de acceso el servidor ha decidido guardarlas en memoria para tener más rápido acceso, definitivamente es mejor acceder a la memoria RAM que no a disco; estas páginas pueden ser descartadas, desechadas en cualquier momento, no indican que la memoria está llena sino que el servidor como tiene memoria libre, ha ido viendo las páginas más solicitadas y las ha mantenido en memoria. Eso es buen síntoma.
* 185 de memoria core: Digámosle así, porque no tengo un nombre exacto. (eso de -/+ buffers/cache no me gusta). Esto indica cuál es la memoria que realmente el sistema está usando, tanto para el kernel como para los procesos que están corriendo e indica que es una memoria bloqueada que no puede ser descartada (como sí puede ser el buffer y el caché). Es decir, si esta memoria se acerta al total (995 en mi caso) preocupémonos!!! pues significa que el servidor en cualquier momento se queda sin memoria para asignarle a los procesos.
De swap, tengo 2 GIGAS (normalmente pongo la misma swap que ram, pero en este caso de prueba puse el doble). Y estamos usando 101 megas, no es nada de alarmarse sobre todo que es un momento bien popular para el servidor y hace que tenga algunos procesos que pueda swapear para tener un poco más de memoria core y para cache y demás.
En definitiva. No estamos usando más que 185 megas en RAM de 1GB que tenemos y 101 megas en swap de 2GB, no creemos que el problema sea por memoria llena.
Además hemos implementado un script que chequea cada un minuto la memoria y lo guarda a un archivo, así que cuando el servidor se cae y lo levantamos, verificamos el uso de memoria al momento de la caída, y definitivamente es super normal en ese momento.
Aquí el script:
#!/bin/bashecho "`date "+%d-%H:%M.%S"`" >> /var/log/memoria .log/usr/bin/top -bn1 >> /var/log/memoria .loguptime >> /var/log/memoria .logcat /proc/meminfo >> /var/log/memoria .logps fuaxww >> /var/log/memoria.lognetstat -na >> /var/log/memoria.log
Lo que hace es bien simple, lo ponemos en el crontab cada unos 2 minutos (o un minuto o 3, como deseen) y el scriptcito guardará en /var/log/memoria.log una serie de detalles como procesos corriendo, memoria en uso, tiempo al aire y procesos de red.
Este script no nos indica (en la última lectura antes de la caída) ni una cantidad inusual de conexiones de red ni tampoco un uso exagerado de memoria ni de procesador. Por lo que al implementarlo, pudimos descartar la teoría número dos que era que la ram se llenaba.
También hemos logrado descubrir que en los logs no se guarda nada en el periodo que el servidor deja de funcionar, como que no nos parece que sea un problema de red pues aunque no haya red sí se guardan los logs...
nos parece más bien la opción 3
3- El disco duro o la controladora han dejado de funcionar temporal o permanentemente
Es la tercera opción que nos queda, y además la resforzamos con la teoría planteada anteriormente de que el servidor no está guardando los logs a partir de que falla. Por lo tanto hacemos una prueba y es guardar los logs en un servidor remoto.
¿Qué logramos con esto? Bueno, si el problema es que el disco no está escribiendo en esos momentos, entonces los logs no se guardarán y no nos podremos enterar de lo que el kernel nos quiere indicar. Cómo lo resolvemos? Simple, no escribamos los logs a disco, sino que los podemos mandar a una máquina remota.
Atención, la conexión entre la máquina remota y la máquina con problemas debe ser estable y buena, de lo contrario, se perderán los logs. De ser posible que sea una conexión local, aunque en nuestro ejemplo lo hicimos con una máquina a miles de millas de distancia pero ambas con un excelente canal a internet (para eso revisamos la tarjeta de red no?!) Además, sugerimos que al acabar las pruebas que pueden durar algunas horas o días, quitemos el logueo remoto y pongamos nuevamente a guardar los logs localmente.
En la máquina que va a servir de servidor de logs (la máquina buena, la que sencillamente sabemos que el disco funciona) editamos:
vi /etc/sysconfig/syslog
Veamos la primera linea descomentada:
SYSLOGD_OPTIONS="-m 0"
Sencillamente agreguémosle: -r, esto sirve para que la máquina acepte conexiones UDP por el puerto 514 que es el de syslog. Recueden en caso de haber un firewall, abrir este puerto en UDP para la IP de la máquina con problemas.
así quedaría:
SYSLOGD_OPTIONS="-m 0 -r"
Ahora reiniciemos el syslog:
service syslog restart
con esto basta, nuestra máquina amablemente aceptará que logueen en ella remotamente. Ahora indiquemosle a la problemática (el servidor que nos está fallando) que mande los logs para allá. Editemos:
vi /etc/syslog.conf
*.info;mail.none;authpriv.none;cron.none[tab]/var/log/messages
authpriv.* /var/log/secure
mail.* /var/log/maillog
cron.* /var/log/cron
*.emerg *
uucp,news.crit /var/log/spooler
local7.* /var/log/boot.log
Muy bien, básicamente estamos diciendo aqui hacia dónde van nuestros logs, todos están yendo a algún lugar dentro de /var/log, esto es, al disco, y no es lo que queremos, queremos evitar escribir a disco pues tenemos la duda de que esté fallando. Cambiémos TODO y pongamos a loguear al servidor remoto (1.2.3.4 le llamaremos, es el que anteriormente configuramos para que aceptara conexiones remotas -r)
kern.* @1.2.3.4
#*.info;mail.none;authpriv.none;cron.none /var/log/messages
*.info;mail.none;authpriv.none;cron.none @1.2.3.4
#authpriv.* /var/log/secure
authpriv.* @1.2.3.4
#mail.* /var/log/maillog
mail.* @1.2.3.4
#cron.* /var/log/cron
cron.* @1.2.3.4
#*.emerg *
*.emerg @1.2.3.4
#uucp,news.crit /var/log/spooler
uucp,news.crit @1.2.3.4
#local7.* /var/log/boot.log
local7.* @1.2.3.4
service syslog restart
y listo, nuestra máquina no va a guardar los logs del syslog en el disco de ella, sino en otra (1.2.3.4 en el ejemplo, insisto porque conozco la mente del ser humano y no dudo que ya pronto me preguntarán por qué no funciona 1.2.3.4).
Miren en la máquina remota (1.2.3.4) y verán que ya comienza a recibir los logs de nuestra máquina problemática. Y ese es el objetivo.
Ahora vigilamos a que falle nuevamente el servidor nuestro y listo, nos pasó, falló, sólo repondía a los ping y a más nada.. así que vamos al servidor remoto y velos los logs (/var/log/messages en nuestro caso) encontrando un error sobre IRQ:
Apr 1 09:11:04 srv3 kernel: hda: lost interrupt
Apr 1 09:11:04 srv3 kernel: hda: lost interrupt
Apr 1 09:11:44 srv3 last message repeated 4 times
Apr 1 09:11:44 srv3 last message repeated 4 times
Apr 1 09:12:54 srv3 last message repeated 7 times
Apr 1 09:12:54 srv3 last message repeated 7 times
Eso sí NO nos gusta. Hay algo raro con las interrupciones. El disco no parece estar físicamente dañado pues no emite errores al syslog de daño, sino algo de interrupciones, colisiones con interrupciones. Normalmente esto se debe a una controladora de disco bien maluca o más fácilmente, que algún otro dispositivo está usando la misma interrupción que el disco.
Veamos las interrupcciones que hay en el sistema y quién las ocupa:
lspci -v
En mi caso sale mucha información, pero sobre todo veo un conflicto entre la controladora de disco y el audio:
00:1f.5 Multimedia audio controller: Intel Corp. 82801DB/DBL/DBM (ICH4/ICH4-L/IC
H4-M) AC'97 Audio Controller (rev 02)
Subsystem: Giga-byte Technology GA-8PE667 Ultra
Flags: bus master, medium devsel, latency 0, IRQ 10
I/O ports at e000 [size=256]
I/O ports at e400 [size=64]
Memory at e8181000 (32-bit, non-prefetchable) [size=512]
Memory at e8182000 (32-bit, non-prefetchable) [size=256]
Capabilities: [50] Power Management version 2
00:1f.1 IDE interface: Intel Corp. 82801DB (ICH4) IDE Controller (rev 02) (prog-
if 8a [Master SecP PriP])
Subsystem: Giga-byte Technology GA-8PE667 Ultra
Flags: bus master, medium devsel, latency 0, IRQ 10
I/O ports at
I/O ports at
I/O ports at
I/O ports at
I/O ports at f000 [size=16]
Memory at 20000000 (32-bit, non-prefetchable) [size=1K]
Ambos usan la misma interrupción, y eso sí que no es agradable. Si hay algo que no debe compartir interrupciones son el DISCO y la tarjeta de RED. Por lo tanto procedamos con las medidas, que deben ser:
1.
Eliminar desde el BIOS o físicamente cuanto dispositivo no estemos usando, estos pueden ser pero no se limitan a: unidad de floppy, puertos USB, tarjeta de sonido, modem, pci para VGA. Estos dispositivos normalmente no se usan cuando damos un servicio de hosting así que al quitarlos hacemos que no hayan conflictos de interrupciones.
2.
Verificar (viendo en /proc/dma) que no hayan situaciones con los DMA, en nuestro caso no las hay.
3.
Desactivar apm y/o acpi y/o apci en el grub. Esto se hace editando /etc/grub.conf y agregando lo siguiente en la linea que comienza con “kernel”
nousb apm=off acpi=off noapic
quedaría algo así (es un ejemplo, tomar la linea correcta del kernel de ustedes):
kernel /vmlinuz-2.4.21-27.0.2.EL ro root=LABEL=/ nousb apm=off acpi=off noapic
Conclusiones
No estamos indicando que estos pasos a seguir son la solución para todos los problemas en un hardware, sino que sencillamente estos fueron los pasos lógicos que seguimos, la determinación del problema y la causa de este.
Después de estas medidas, hemos logrado controlar las caídas del servidor y ya no son misteriosas.
Recomendaciones: