[Jderobot-admin] Caída del servidor del finde pasado

Oscar Garcia oscar.robotica en linaresdigital.com
Lun Nov 5 14:20:31 CET 2012


El 05/11/2012 12:06, Borja Mon Serrano escribió:
> Puede ser que solo fuese un hijo, aunque con estas dos líneas:
> Oct 27 22:54:42 jderobot kernel: Out of Memory: Kill process 6758
> (apache2) score 41572 and children.
> Oct 27 22:54:42 jderobot kernel: Out of memory: Killed process 6758
> (apache2).
>
> Yo entiendo que lo que se cargó es apache y a todos sus procesos hijos.
> Tampoco es algo que pueda afirmar rotundamente, ya que hasta el jueves
> pasado no me había parado a analizar un syslog.


Precisamente loguea el motivo de la decisión y fue que tenía una 
puntuación de 41572 (basada en tiempo de ejecución) _Y_ que era un hijo, 
no que matara ese y sus hijos (de hecho en la siguiente línea explica 
que sólo ha matado ese proceso).

>     El problema es que hay que dimensionar el servidor (o los procesos
>     servidor) para la RAM que se tiene. Por ejemplo, limitar el número de
>     procesos hijos que puede levantar apache (con zabbix sería bueno
>     monitorizar el número) o usar un acelerador web como squid para
>     aligerarle el trabajo.
>
> He estado echándole un ojo a squid y parece un buen servicio. ¿Se
> asemejaría al mod_pagespeed de Google [1] o es un servicio complementario?


Nunca he usado mod_pagespeed, pero ese es un módulo de apache que 
_MODIFICA_ la página web, hojas de estilos, javascripts e imágenes para 
mejorar el rendimiento de carga de la web. Es decir, pone "inline" 
scripts y hojas de estilo dentro de la página, limpia campos de la misma 
innecesarios para evitar abrir una conexión para la página y luego ir 
abriendo nuevas conexiones para dichos scripts u hojas de estilo, 
mejorando la latencia.

Por otro lado modifica las imágenes haciéndolas coincidir en tamaño con 
el espacio reservado en la página, recomprimiéndolas optimizando la 
calidad para reducir el tiempo de carga. Esto es útil para gente que no 
tiene nociones de diseño web y mete una imagen de 5 MP de 2 MB de peso 
en un hueco de 300x200 pixeles, por ejemplo, cuando lo normal es usar 
una aplicación para reducir la imagen original al tamaño deseado y 
ajustar la calidad para conseguir el mejor compromiso calidad/tamaño.

Squid no modifica en nada la página, simplemente almacena en RAM los 
recursos más solicitados (páginas HTML estáticas, imágenes, javascripts, 
hojas de estilo, documentos PDF, DOC, etc) y los sirve directamente de 
ella sin pedírselas de nuevo al servidor web.

Con eso reduces el número de procesos apache2 levantados y también el 
número de accesos a disco y centras al servidor web en producción de 
páginas dinámicas.


>      También se puede limitar el número de sesiones activas de un usuario
>     en /etc/security/limits.conf (maxlogins) para evitar acumulaciones de
>     intentos de entrada svn, rsync, ssh, etc.
>
>
> Ahora mismo el control de acceso de usuarios al svn y a la wiki se hacen
> a través de ldap. ¿Valdría también en este caso?


Creo que en el caso particular de svn todo va por https (usando el 
servidor web con un módulo webdav), en ese caso no está influido por 
limits, si no por mpm_prefork_module de apache:

<IfModule mpm_prefork_module>
     StartServers          5
     MinSpareServers       5
     MaxSpareServers      10
     MaxClients          150
     MaxRequestsPerChild   0
</IfModule>

Esa es la configuración por defecto, pero hay que "tunearla" para 
maximizar el número de usuarios simultáneos que es capaz de atender el 
servidor web (sería ayudado por el acelerador si existiera) y, al mismo 
tiempo, conservar los recursos de memoria al máximo minimizando el 
número de procesos levantados.


>     Por otro lado hay que ver qué más procesos se levantan y si hay tareas
>     programadas o bots que hagan algo de manera automática que se puedan ir
>     acumulando si no terminan el trabajo en el tiempo que se suponía que
>     debían hacerlo.
>
> Hay varias tareas en cron que se ejecutan diaria o semanalmente.
> También, cada hora, se hace un log del blog y de la wiki con webalizer.
> También hay un proceso que se ejecuta cada media hora, aunque no sé
> quién lo está lanzando (porque cron no es), que fue el último en
> ejecutar antes de la catástrofe.
>
> Oct 27 22:44:51 jderobot /USR/SBIN/CRON[29129]: (root) CMD (  [ -d
> /var/lib/php4 ] && find /var/lib/php4/ -type f -cmin
> +$(/usr/lib/php4/maxlifetime) -print0 | xargs -r -0 rm)
> Oct 27 22:44:51 jderobot /USR/SBIN/CRON[29055]: (CRON) error (grandchild
> #29129 failed with exit status 1)


Ummm, depende de la versión que tengáis del sistema operativo no os 
habéis percatado de un bug que existe en el script de limpieza de 
sesiones QUE DEBE SER SUBSANADO CON URGENCIA. Parece que tenemos un 
presunto culpable de la caída del servidor (aunque puede ser que no lo 
sea, me ha recordado un problema que tuve en mi primer ubuntu 12.04 
server :)

En /etc/cron.d/php5 hay que comentar la línea existente y dejar esta más 
sencilla:

09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && [ -d 
/var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 
-type f -cmin +$(/usr/lib/php5/maxlifetime) -delete

La línea del log de cron no es exactamente la que usa "fuser" que es la 
que origina el problema, pero deberíamos tener en cuenta que podría ser 
una fuente del problema:

https://bugs.launchpad.net/ubuntu/+source/php5/+bug/876387


>     ¿Has restado a esa cantidad la caché de disco usada?
>     ¿Tuviste en cuenta esos datos para tomar la medida de uso de memoria? ¿O
>     usaste el valor que te ponía algún comando como top o free?
>
> No, no lo tuve en cuenta, cogí los datos que te ofrece free directamente
> sin tener en cuenta la caché. Por ejemplo, ahora mismo:
>
> jderobot:~# free -m
>               total       used       free     shared    buffers     cached
> Mem:          2020       1856        163          0        466        780
> -/+ buffers/cache:        609       1410
> Swap:         1608          0       1607
>
> Querría decir que tenemos 163MB (aproximadamente) libres, pero que si
> hiciese falta un poco más se liberaría parte (o toda, según se
> requiriese) de la cacheada, que son ~780MB, ¿no?


Sí, en ese caso sobra casi un giga de memoria RAM (incluso algo más si 
tenemos en cuenta que una parte de los buffers también podría ser 
liberada en caso de necesidad).

¿Comenté que suelo tener el swappiness a 2? Eso minimiza el movimiento 
entre RAM y disco (swap) si ésta no se agota realmente.

# echo "vm.swappiness = 2" >> /etc/sysctl.conf
# sysctl -p

O bien, más elegante, pero no actualiza al hacer "sysctl -p":

# echo "vm.swappiness = 2" > /etc/sysctl.d/swappiness.conf
# sysctl -w vm.swappiness=2


>     ¿Podéis comprobarlo? Cuando se instalan programas en paralelo que son
>     usados por los gestores de paquetes para ejecutar scripts de instalación
>     o configuración... ¡puf! es cuando te la juegas.
>
> /usr/local es el directorio por defecto, sí, pero, por ejemplo, perl
> está instalado en /root/perl5. Después de haber reinstalado perl he
> visto que este es el directorio que él mismo escoge por defecto. Al
> menos, con la instalación manual.


¿Habéis probado a reinstalar perl en dicho directorio?

Por cierto, ¿cuál es el motivo que os ha llevado a instalar una versión 
de perl diferente a la que vienen en los repositorios?

La ventaja de tener todo de los repositorios es que al meter una máquina 
nueva basta con un dpkg --get-selections en la máquina vieja y luego un 
dpkg --set-selections en la nueva para clonar los paquetes necesarios 
para que ambas se queden igual (se puede filtrar para que sólo lo haga 
con los php5-*, libapache2-mod-*, etc).

Como mucho habría que hacer algo similar con cpan (módulos de perl) y 
pecl (módulos de php).


>     Por cierto, ¿no habéis pensado en redundar la instalación?
>
> Es decir, ¿tener varios servidores?


Sí, por ejemplo. Si se diseña correctamente permite escalar fácilmente 
la infraestructura agregando nuevas máquinas y, sobre todo, ofrece 
tolerancia a caídas.

Otra solución es usar virtualización para redundar servicios usando 
menos máquinas físicas (openvz permite eso).


>     Por otro lado, podríais meter ciertos servicios dentro de un contenedor
>     virtual dentro de la misma máquina para limitar los recursos usados. Yo
>     soy un usuario compulsivo de openvz.
>
> ¿Qué ventajas proporcionaría esto? ¿Sería realmente necesario?


La más importante es separar máquinas virtuales entre sí, aislándolas y 
protegiéndolas ante problemas de memoria, etc.

Ya me he acostumbrado a separar base de datos (y/o almacenamiento) de 
máquinas de proceso, por lo que éstas son "máquinas virtuales ligeras" 
(como las de EC2) que requieren poca RAM y que en caso de caer la 
máquina física posee un balanceador que deja de usar dicha máquina para 
el trabajo.

En mi ejemplo particular tengo una máquina física en la que corro dos 
instancias openvz de debian 6 con únicamente el servidor web y todo lo 
necesario para ejecutar PHP, el servidor de bases de datos está en la 
máquina física y las instancias se conectan con ella a través de TCP 
(que es un poco más lento que los sockets UNIX, pero en este caso 
prefiero robustez a latencia).

En la máquina física también ejecuto un squid que hace de 
acelerador/balanceador web que detecta cuando una de las máquinas 
virtuales tarda más de 2 segundos en responder (o rechaza conexión) para 
dejar de usarla.

Es poco frecuente que se caiga un servidor web (aunque ocurre muy de vez 
en cuando) pero nos permite reiniciar el servidor apache de un nodo tras 
instalar las actualizaciones de seguridad sin que exista pérdida de 
servicio y, en caso de ataque al servidor web, sólo tendrían acceso al 
sistema de archivos "virtual" que "ve" el contenedor, no el sistema de 
archivos completo de la máquina host.

De los ataques (fructíferos) que hemos sufrido casi todos han sido a 
través del servidor web, accediendo al directorio de usuario de un 
servicio cuya contraseña no era segura o no estaba la cuenta 
deshabilitada, subiendo al servidor ftp un PHP que permite ejecutar 
comandos de consola. A partir de ahí instalar aplicaciones, bots, 
compilar exploits que te permitan "ascender" a root (como el que se 
puede hacer en las aulas de informática, no recuerdo a qué profesor le 
advertí que eran núcleos de linux inseguros).

En ese caso el servidor ftp correría de nuevo en un contenedor openvz 
que no contiene servicios innecesarios (y potencialmente con usuarios 
inseguros) y que en caso de ser infectado un usuario de sistema (adm, 
fuse, etc) no sería el de la máquina física, por lo que no se podría 
proseguir con el ataque ejecutando esos scripts inyectados desde el 
servidor web.


>     PD: Hablando de ataques, también recomendaría usar fail2ban para tener
>     una mínima defensa contra ataques de fuerza bruta en el servidor ssh (y
>     otros que se configuren) y tener watchlog enviando informes diarios de
>     actividad del servidor.
>
> Vuelvo a lo de antes, primero hay que eliminar el error de las
> dependencias de libc, aunque es cierto que es algo que habría que hacer.


Lo entiendo, probad con el tema de dejar funcionando correctamente perl 
en el directorio root (o averiguar el motivo por el que crea conflictos 
en los scripts de instalación de apt).

Otra ventaja de correr contenedores virtuales es poder hacer snapshots 
de estados en los que la máquina funciona correctamente y volver a ellos 
en caso de meter la pata y borrar algo importante que impida que ésta 
siga funcionando correctamente.

Si se redundan en máquinas físicas en vez de contenedores virtuales 
entonces se puede reinstalar la máquina sin perder servicio.

Aunque es un mensaje muy largo espero que al menos haya explicado bien 
las ventajas que tiene (al menos para mí) usar contenedores openvz 
dentro de una misma máquina física.

Un saludo.


More information about the Jderobot-admin mailing list