PowerStack para CentOS-6

Hoy el proyecto PowerStack ha dado otro pequeño paso: el repositorio ahora también es compatible con CentOS-6. Con el mismo objetivo: facilitar la instalación de las últimas versiones del stack LAMP (actualmente: PHP 5.3.8, MySQL 5.5.17 y Apache 2.2.21), así como empaquetar software indispensable no disponible en la base de CentOS: Varnish, memcached, nginx, Maatkit, Keepalived, etc. hasta un total de casi 100 paquetes.

El roadmap a corto plazo: activar los delta-RPMs para descargar con yum-presto las diferencias en las actualizaciones en lugar de los paquetes completos, nuevo repositorio “unstable” a modo de “technology preview” (PHP 5.4, MySQL 5.6, etc.), y empaquetar software NoSQL (MongoDB, Redis, CouchDB, etc.) + node.js.

Desde que anunciamos la versión 0.2 de PowerStack -hace apenas 4 meses- el número de servidores que están utilizando el repositorio se ha triplicado (~600 instalaciones activas) y más de 1.500 usuarios lo han probado.

Agradecimientos: Raul Moreno (Hostalia y #kutxashare) y Jonathan Lopez (blackslot.com) por el gran trabajo de “testing“, a los foreros de OVH y a todos aquellos que nos han enviado sugerencias a través de Twitter, Facebook, etc. gracias!

Posted in Linux, Proyectos | Tagged , | 3 Comments

Colaboración de Hostalia con PowerStack

Un post breve para anunciar una buena noticia para PowerStack: la semana pasada firmamos un acuerdo de colaboración con Hostalia, reafirmando así el compromiso de esta compañía con el software libre. Lo más importe de esta cooperación es la cesión de un servidor dedicado en su centro de datos en Madrid y además, como siempre han hecho, nos seguirán ayudando como “betatesters” en la etapa de QA.

Hasta ahora el proceso para construir los RPMs de PowerStack ha sido prácticamente manual, ahora que tenemos un servidor dedicado podemos utilizar herramientas tipo mock o koji (el buildsystem que utilizan en Fedora) para automatizar gran parte del trabajo, de modo que será posible pensar en nuevos proyectos:

- Un nuevo repositorio “unstable” a modo de technology preview, otro objetivo del proyecto PowerStack es facilitar al usuario la instalación de versiones beta (PHP 5.4, MySQL 5.6, etc.)

- Al contar con un buildsystem para automatizar la construcción de RPMs sería posible colaborar con CentOS, Scientific Linux, etc.. incluso pensar en una distribución spin-off con compatibilidad binaria con RHEL.

La colaboración con Hostalia es una buena noticia para PowerStack que ayudará a que el proyecto siga evolucionando y mejorando día a día! :)

Posted in Proyectos | Tagged , | Leave a comment

Preload de tablas InnoDB en el buffer pool de MySQL

Este post se basa en un enlace que ha compartido Asier Marqués de blackslot.com en Twitter: How to preload tables into InnoDB buffer pool with MySQL?. El thread de stackoverflow.com describe como precargar tablas InnoDB en el buffer pool para tener el contenido en memoria y reducir los “misses” a disco.

Esta técnica es interesante cuando tenemos un pool de slaves MySQL y queremos que funcionen a pleno rendimiento desde el primer momento. Por ejemplo, si las primeras querys con el buffer “frio” necesitan 1 segundo para ejecutarse en lugar de unos pocos milisegundos, al conectar el slave MySQL al balanceador/proxy se puede degradar la experiencia de navegación durante el “warming up” (proceso para calentar el buffer InnoDB moviendo registros de disco a memoria que puede llevar minutos, horas, etc.).

Escenario: MySQL de PowerStack con la configuración por defecto y 1GB de datos InnoDB (30 millones de registros aprox.) sobre una VM con 4 cores y 2GB de RAM. El objetivo es cargar el contenido completo de la tabla InnoDB en el buffer pool y ver que tras el preload la memoria de “mysqld” crece en +1GB y las siguientes querys no generan I/O a disco. Antes de la precarga de datos MySQL está usando ~150MB de RAM y ha leído unos ~12MB desde disco:

# grep VmRSS /proc/`pidof mysqld`/status
VmRSS:    152848 kB

# grep read_bytes /proc/`pidof mysqld`/io
read_bytes: 12455936

La primera técnica consiste en forzar un full tablescan con un SELECT sobre una columna no indexada para que MySQL tenga que recorrer todas las filas y moverlas al buffer pool (si existe un índice lo podemos evitar con IGNORE INDEX):

mysql> SELECT COUNT(*) FROM tabla WHERE columna_no_index=0;
30 segundos

Tras el SELECT “mysqld” ha leído ~1GB desde disco y ha crecido +1GB en memoria RSS. Con la ayuda del contador interno innodb_buffer_pool_pages_data de MySQL vemos que esa memoria está destinada a InnoDB (el buffer pool está organizado en páginas de innodb_page_size bytes -generalmente 16KB-, para este caso: 64135 páginas x 16KB ~= 1GB):

# grep VmRSS /proc/`pidof mysqld`/status
VmRSS:   1177276 kB

# cat /proc/`pidof mysqld`/io
read_bytes: 1064693760

# mysqladmin extended | grep buffer_pool_pages_data
innodb_buffer_pool_pages_data = 64135

Lanzamos un segundo SELECT, en este caso con SQL_NO_CACHE para evitar sacar el resultado desde la query cache + un drop_caches para vaciar caches/buffers de Linux, y comprobamos que MySQL no ha generado I/O de lectura para obtener los datos, esto hace que la consulta sea mucho más rápida (de 30 a 5 segundos para un fullscan de 30M filas):

# echo 3 > /proc/sys/vm/drop_caches

mysql> SELECT SQL_NO_CACHE COUNT(*) FROM tabla WHERE columna_no_index=0'
5 segundos

# cat /proc/`pidof mysqld`/io
read_bytes: 1064693760

Podríamos agregar este “hack” a la función start() del script de inicio MySQL y aprovechar para desfragmentar los ficheros .ibd, así las futuras lecturas/precargas serán secuenciales = más rápidas:

iptables -I MySQL -p tcp --dport 3306 -j DROP
mysql db -e 'OPTIMIZE TABLE tabla'
mysql db -e 'SELECT COUNT(*) FROM tabla WHERE columna_no_index=0'
iptables -F MySQL
(..)

Este tip es útil cuando el tamaño de las tablas es menor a la RAM, si los datos no entran en el buffer de InnoDB sería interesante poder hacer un dump del pool antes de parar MySQL para recuperar su contenido al arrancar, así el LRU de la cache InnoDB nos ayudaría a iniciar con los registros mas “populares”. El motor XtraDB de Percona permite realizar dump+restore del buffer pool de InnoDB, el hack se basa en un parche para MySQL 5.1 de Jeremy Cole (MySQL Database Architect en Twitter) de la ya extinta Proven Scaling.

Una vez tenemos el contenido de las tablas InnoDB en memoria tenemos que evitar que se muevan a swap, para ello bajamos el swappiness de Linux al 0% (dejar un servidor sin swap mediante swapoff no sería buena idea) y arrancamos MySQL con innodb_flush_method=O_DIRECT para evitar el doble buffering (interno de InnoDB + el de Linux, este último tiene estructuras en el filesytem que se pueden mover a swap, lectura relacionada).

Posted in Linux, MySQL, Storage | Tagged , , | 6 Comments

Optimizar I/O scheduler en Linux + hardware RAID

Desde que un proceso hace un write() hasta que el dato se almacena en el medio físico este atraviesa varias capas (sistema de ficheros, gestor de volúmenes, controladora RAID + BBU, caches de disco, etc.) donde se realizan una serie de optimizaciones para mejorar el acceso a disco, en entornos virtuales estas capas pueden llegar a duplicarse:

Hoy en día es común encontrarnos escenarios con 3-4 capas de I/O scheduling y a priori podríamos pensar que sumarlas va a mejorar el rendimiento. En la práctica y aunque parezca increíble, en conexiones a sistemas RAID -ya sea por iSCSI, Fiber Channel o vía DAS- deshabilitar estas optimizaciones pueden darnos mejores resultados.

En Linux la optimización más importante se realiza en el planificador de E/S de los dispositivos de bloques (en inglés, I/O scheduler), una capa inteligente entre el sistema operativo y el hardware donde se aplican diferentes algoritmos (CFQ, deadline, anticipatory, noop, etc) para ordenar operaciones de E/S y hacer así un uso más eficiente de los discos: agrupar escrituras, reducir seeks, priorizar ciertas operaciones de I/O, etc. Este comportamiento tiene mayor impacto en sistemas con I/O aleatorias, por ejemplo en grandes bases de datos MySQL.

En estas dos gráficas vemos el %iowait y la carga de una máquina Linux con CentOS conectada vía iSCSI a una cabina NetApp, tras deshabilitar el I/O scheduler CFQ (planificador por defecto en RHEL) la carga baja de 10 a 1 y el iowait del %20 a %4:

En Linux podemos cambiar este comportamiento en caliente y por cada dispositivo vía SysFS (entre corchetes aparece el planificador de E/S activo):

# cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]

# echo noop > /sys/block/sda/queue/scheduler

# cat /sys/block/sda/queue/scheduler
[noop] anticipatory deadline cfq

Para hacer estos cambios persistentes a reinicios podemos utilizar udev y aplicar un planificador de forma selectiva, en este ejemplo establecemos “noop” solo en conexiones del tipo iSCSI o FC (podríamos afinar la regla y aplicarla únicamente a cabinas de un determinado fabricante, por ejemplo con vendor=”NETAPP” y model=”LUN”):

ACTION=="add", SUBSYSTEM=="scsi", ENV{ID_FS_USAGE}!="filesystem", \
        ENV{ID_PATH}=="*-iscsi-*|-fc-*", \
        RUN+="/bin/sh -c 'echo noop > /sys$DEVPATH/queue/scheduler'"

Un I/O scheduler da su máximo rendimiento cuando tiene una cola por cada disco y si los discos están bajo un RAID el kernel los verá como un único dispositivo y utilizará una única cola (aunque tengamos 10 discos).

En un sistema RAID el kernel entrega ordenado el I/O a la controladora a través de una cola única y esta a su vez lo distribuye entre los discos, este mecanismo funciona bien hasta alcanzar el límite de una cola/disco (~250 ops para discos de 15K aprox.) y a partir de aquí empieza a degradarse. Al deshabilitar el planificador el tráfico I/O llegaría desordenado a la controladora RAID y esta podría hacer el reparto de forma más eficiente (para una explicación más detallada recomiendo la lectura del post “Optimizing Linux for random I/O on hardware RAID“), gráficamente:

Como alternativa menos cómoda a modificar el I/O scheduler en vez crear un RAID con todos los discos podemos crear grupos y posteriormente unirlos por software, así el kernel podrá trabajar con más de una cola; Ejemplo: si tenemos un RAID con 10 discos podemos crear 5 grupos de 2 discos en RAID-1 y unirlos en stripe vía LVM (a efectos un RAID 1+0), de este modo Linux vería 5 dispositivos y trabajaría más eficientemente al utilizar 5 colas.

Finalmente, todo esto depende del tipo de cabina, tráfico I/O, discos, etc. pero en general si tienes un buen sistema RAID + BBU deshabilitar la reordenación de I/O en el kernel y delegar este trabajo al hardware especializado va a dar mejores resultados. Pero como siempre… lo mejor es realizar benchmarks con diferentes schedulers y comparar resultados :)

Posted in Linux, Storage | Tagged , , , , , , , | 1 Comment

Introducción a Cfengine

Cfengine es una herramienta que permite automatizar la gestión de sistemas desde un único punto utilizando un lenguaje de alto nivel basado en políticas de configuración con su propia sintaxis.

Su autor, Mark Burgess, empezó a desarrollarlo en 1993 en la Universidad de Oslo con el objetivo de crear un framework portable para gestionar las diferentes variantes de UNIX basándose en sus propias tesis sobre la convergencia de sistemas y la “Promise Theory“. A día de hoy, es la solución para centralizar la gestión de sistemas más extendida y empresas como Facebook, Google y NASA lo utilizan para controlar infraestructuras con más de 100.000 servidores.

Es software libre (licencia GPL) y desde la versión 3.0 (junio del 2008) existe una distribución comercial, Nova, que cuenta con soporte desde la empresa fundada por Mark Burgess, Cfengine AS. Como alternativas a Cfengine tenemos Chef, Quattor, Puppet, etc. siendo este último el más popular.

Ventajas de utilizar Cfengine

La automatización aporta valor cuando el número de servidores a controlar es importante (más de 10-20) y todos ellos comparten algo en común. De no ser así, no tiene mucho sentido utilizar este tipo de herramientas.

Cfengine es una herramienta pensada para solucionar problemas comunes a la gestión de un centro de datos, estas son algunas de sus principales ventajas:

Centralizar. Cfengine permite automatizar la gestión de toda una infraestructura Linux desde un único punto y con una única herramienta, esto lo convierte en una solución escalable: el esfuerzo necesario para gestionar 1 máquina es el mismo que para 100.000.

- Reducir errores. La automatización elimina tareas repetitivas y como consecuencia directa se evitan errores humanos reduciendo incidencias y mejorando la estabilidad de los servicios. El diseño de Cfengine basado en la “Promise Theory” permite propagar cambios de forma fiable y con garantías.

- Ahorrar tiempo. Al automatizar tareas con Cfengine ganamos tiempo de dos formas: 1) se reduce el tiempo necesario para la puesta en marcha de nuevos servicios y aplicar cambios -aquí es donde nace el concepto DevOps- y 2) al evitar tener que entrar vía SSH a los servidores para “trabajar” manualmente el administrador cuenta con más tiempo para su verdadero trabajo: mejorar la infraestructura evitando que errores conocidos vuelvan a ocurrir.

Documentación. El trabajo del administrador de sistemas queda “auto-documentado“: cada regla en Cfengine define una tarea. Generalmente la configuración de Cfengine se combina con un sistema de control de versiones (Git, Subversion, etc.), por lo que tendremos un registro completo de todos los cambios realizados históricamente en la infraestructura, información que podemos “reciclar” con herramientas tipo “cf-know” y convertirlas en documentación. Cuando entra un nuevo empleado leyendo este código tendría una idea actualizada de la configuración de los sistemas.

¿Qué se puede hacer con Cfengine?

Estos son algunos ejemplos de las diferentes tareas que se pueden llevar a cabo con Cfengine, acompañas de porciones de código para ir familiarizándonos con las sintaxis del lenguaje:

- Copiar ficheros: podemos distribuir cualquier tipo de fichero (configuración, binario, etc.) desde el servidor central de políticas de Cfengine a cualquier número de máquinas (a todas o a un grupo determinado). En una infraestructura Linux es muy común que todos los servidores mantengan actualizada la misma configuración de SSH (sshd_config y authorized_keys), resolución DNS (resolv.conf), etc. En este ejemplo, se distribuye la configuración de “mod_status” para Apache en todos aquellas máquinas que pertenezcan a un determinado grupo (“frontend”), y solo si, se realiza la copia se fuerza un reinicio del servidor web para que entre en funcionamiento la nueva configuración:

copy:

frontend::
	# Configuracion de mod_status para Apache
	$(master_cfinput)/cfengine/apache/mod_status.conf
	dest=/etc/httpd/conf.d/mod_status.conf
	server=$(policyhost)
	trustkey=true
	type=binary
	mode=0644
	define=service_httpd_graceful

- Comprobar y establecer permisos y propietario/grupo en ficheros/directorios. En este ejemplo forzamos a que el directorio /tmp tenga la configuración de seguridad recomendada en UNIX, permisos 777 junto al “sticky bit” y “root” como propietario y grupo:

files:

any::
	/tmp
	mode=1777
	owner=root
	group=root

- Edición de ficheros: es uno de los módulos más potentes de Cfengine que nos permite realizar cualquier tipo edición sobre ficheros: reemplazar una cadena, comentarla, eliminar una línea, agregar un texto, etc. Ejemplo: en todas las máquinas con CentOS-5 se comentan las líneas que contengan “requiretty” en /etc/sudoers:

editfiles:

centos_5::
	{ /etc/sudoers
		SetCommentStart '#'
		CommentLinesMatching '.*requiretty.*'
	}

- Borrar ficheros: podemos borrar ficheros temporales, eliminar aquellos que por seguridad no queremos que estén presentes, etc. En este ejemplo se borran aquellos ficheros del directorio “/var/spool/repackage” con más de un mes de antigüedad:

tidy:

any::
	# Borrar RPMs temporales para rollback de operaciones con Yum
	/var/spool/repackage
	pattern=*
	recurse=inf
	links=stop
	rmdirs=false
	age=30
	inform=off

- Ejecución de comandos: se utiliza básicamente en dos escenarios: 1) ejecutar un comando si una determinada condición/clase está definida y 2) definir una clase tras la condición de salida de un script. En este primer ejemplo, si la clase “service_sshd_restart” está definida se realiza un reinicio del servicio SSH (la clase “service_sshd_restart” se puede definir, por ejemplo, si se realiza un cambio en el fichero de configuración de OpenSSH):

copy:

any::
	$(master_cfinput)/cfengine/sshd/sshd_config
	dest=/etc/ssh/sshd_config
	server=$(policyhost)
	trustkey=true
	type=binary
	mode=0600
	define=service_sshd_restart

shellcommands:
	service_sshd_restart::
		"/etc/init.d/sshd restart"

En este segundo ejemplo ejecutamos el script “halfduplex.sh” (detecta interfaces en half-duplex) y si el código de retorno de este script es “cero” se define la clase “halfduplex”, posteriormente si dicha clase está definida se genera una alerta que le llegará al administrador (por email, syslog, etc.), el código en lenguaje Cfengine:

classes:
	# Clase para detectar si existen interfaces en Half-Duplex
	halfduplex = ( ReturnsZero("/root/scripts/halfduplex.sh") )

alerts:
	!halfduplex::
		"ERROR! El servidor tiene interfaces de red en Half-Duplex!"

- Gestión de paquetes software RPM y DPKG. Cfengine cuenta con un módulo con el que podemos realizar tareas básicas relacionadas con la gestión de paquetes de software: instalar, borrar, actualizar, etc. abstrayendo el sistema operativo sobre el que se ejecuta el agente (Linux, FreeBSD, etc.) y el gestor de paquetes utilizado (RPM, DPKG, etc.). En este ejemplo, nos aseguramos de que todas las máquinas tengan el paquete “rsync” instalado y que las máquinas del cluster “backend” el compilador GCC no esté instalado:

packages:

any::
	rsync
	action=install

!backend::
	gcc
	action=remove
	version=0.1
	cmp=ge

- Gestión de procesos y servicios del sistema. Podemos definir políticas en Cfengine para gestionar que servicios se ejecutan al arrancar la máquina, comprobar que un determinado proceso se está ejecutando (monitorización) y que no tenga más de un determinado número de hijos, memoria consumida, tiempo en ejecución, etc. En este ejemplo nos aseguramos de que el servicio “cron” se ejecuta al arrancar la máquina y que “cups” está deshabilitado:

classes:
	# Clase para comprobar si esta DESACTIVADO el servicio "cups"
	service_cups_off = (ReturnsZero("/sbin/chkconfig --level 3 cups"))

	# Clase para comprobar si esta ACTIVADO el servicio "crond"
	service_crond_on = (ReturnsZero("/sbin/chkconfig --level 3 crond"))

shellcommands:
	service_cups_off::
		"/sbin/chkconfig --del cups ; /etc/init.d/cups stop"

	!service_crond_on::
		"/sbin/chkconfig crond on ; /etc/init.d/crond start"

Todas estas tareas se pueden aplicar con independencia del sistema operativo (Solaris, FreeBSD, etc.) y distribución Linux. Es decir, si añadimos una regla para instalar el paquete “sudo” en todos los servidores, Cfengine se encargará de “traducir” el código en cada servidor y ejecutar los comandos corrrespondientes (en Debian se utilizaría APT, en RHEL se usaría Yum, etc.).

Cfengine es una herramienta sencilla de manejar pero con una curva de aprendizaje importante. La introducción ha sido algo extensa pero necesaria para comprender las ventajas y familizarnos con los conceptos de la automatización en Linux. Los siguientes posts serán más prácticos y al final acabaremos montado un laboratorio que se podrá gestionar en su totalidad desde un único punto con Cfengine :)

Posted in Linux, System Automation | Tagged | 2 Comments

PowerStack 0.2

Han pasado ya tres meses desde que decidimos dar el paso, registrar un dominio y compartir con la comunidad el proyecto PowerStack. En este tiempo han sido muchos los usuarios que han instalado el repositorio en sus servidores y nos han hecho llegar sus impresiones, la última estadística indica que más de 200 máquinas lo están utilizando. La acogida ha sido mucho mejor de lo que nunca hubiéramos imaginado y estamos muy contentos: nos han enviado muchas sugerencias (¡el post de bienvenida ha tenido más de 30 comentarios!), reportado errores, críticas, etc. y fruto de este valioso feedback han sido un total de 100 cambios en el código inicial de PowerStack 0.1, haciendo que esta nueva versión sea más estable y segura (sacamos un fix para el exploit shmop_read() de PHP antes que las principales distribuciones Linux).

Esta segunda versión se vuelve a centrar en mejorar el stack LAMP por defecto de CentOS y RHEL: últimas versiones estables (PHP 5.3.6, MySQL 5.5.13, Apache 2.2.19), se distribuyen ficheros de configuración más seguros y que mejoran el rendimiento (por ejemplo habilitando el query_cache en MySQL, deshabilitando la directiva enable_dl de PHP, etc.). Una instalación por defecto de PowerStack con PHP 5.3 + los parches de Google para MySQL 5.5 mejoran en un 30-40% el rendimiento de una instalación por defecto de CentOS. Para complementar el stack LAMP se han añadido nuevos paquetes: el acelerador web Varnish 2.1.5, memcached 1.4.5, servidor web nginx 1.0.2 y Keepalived 1.2 (balanceador LVS + VRRPv2). Además y a partir de esta versión los paquetes estarán firmados con GPG, cambio motivado de cara a hacer más segura la distribución de paquetes RPM en una red de mirrors en un futuro.

En los siguientes días publicaremos el roadmap para la versión 0.3, por ahora podemos adelantar que se seguirá centrando en su propósito inicial: empaquetar para RHEL y CentOS el software con el que se está construyendo la web actualmente. Algunos de estos paquetes serán: MongoDB, Redis, Cassandra, node,js, RabbitMQ, Cfengine, Puppet, Maatkit, Sphinx, etc. Además dedicaremos esfuerzos en automatizar el proceso de construcción de los paquetes RPM (posiblemente utilizando mock y koji de Fedora) y desarrollar una solución para que los usuarios puedan colaborar más fácilmente. Si tienes una idea para mejorar PowerStack puedes ponerte en contacto con nosotros a través de Twitter, Facebook o por email.

Aprovecho para dar las gracias a todos mis compañeros de trabajo en Hostalia (¡gracias Raul!) y Acens, a todo el equipo de Blackslot, a Jordi Prats de systemadmin.es, a todos los foreros de OVH, etc. y en general a todos aquellos que de alguna forma habéis apoyado los primeros pasos de este proyecto, reportando errores, sugerencias o simplemente usándolo, muchas gracias!! :)

Posted in Linux, Proyectos | Tagged , , | 24 Comments

Certificación LPIC-1, examen 117-101

Hace unos días comentaba en Twitter que me presentaba al exámen 117-101 de la certificación LPIC-1. Tras el “tweet” he visto bastante interés en esta certificación para Linux por lo que voy a comentar mi experiencia.

Con un vistazo rápido en las principales webs de empleo, pronto nos damos cuenta de que es una certificación poco demandada. Si buscas una certificación que te abra puertas en el “mundo Linux” posiblemente otras mas específicas como RHCE de Red Hat sean mejor opción.

Es posible hacer el exámen en cualquier centro Pearson ó Prometic y el precio ronda los 250€/examen. Es importante preguntar en varios centros, incluso de otra ciudad, ya que los precios varían. Al tratarse de una certificación no es posible su financiación con las ayudas de la Fundación Tripartita. Para cualquier problema, Qindel Group lleva las certificaciones LPI en España.

Existen varios libros para preparar la certifcación LPIC-1, en mi caso he utilizado la tercera edición de “LPI Linux Certification in a Nutshell” de O’Reilly, consultando puntualmente algunos temas en las guias de IBM y realizando varios TestKings.

LPI contiene preguntas específicas de Debian y Red Hat por lo que es recomendable hacer las practicas en estos dos “sabores” de Linux. Ubuntu utiliza upstart por lo que no la recomendaría para las prácticas, ya que gran parte del temario se basa en el sistema de arranque System V de Unix (init + /etc/inittab), en mi caso he utilizado CentOS-5 y Debian Lenny.

Cada objetivo del temario tiene un peso y cada peso implica una pregunta, en total son 60 preguntas a responder en 90 minutos. El examen es en inglés, por lo que resulta recomendable hacer la preparación y los tests en este idioma. Las calificaciones van desde los 200 a 800 puntos y para aprobar se necesitan 500. Antes de presentarte al examen necesitas registrarte para obtener un LPI-ID.

En mi caso particular, las preguntas me han parecido algo mas complejas que las que había visto por los TestKing y algunas de ellas no se podían responder solo con la lectura del libro de O’Reilly. En cualquier caso, es una certificación asequible para el público que está destinado (2-3 años de experiencia).

Finalmente, comparto un PDF con preguntas tipo para el examen 117-101. La fundación LPI no permite la distribución de los examenes, por lo que he adaptado el contenido con preguntas y respuestas similares para que pueda ser de ayuda para futuros candidatos.

Posted in Linux | Tagged , , , , | 9 Comments

Presentación del proyecto PowerStack

Tras la presentación informal de PowerStack (por cierto, fue un guiño al mítico email de Torvalds!) voy a contar algo más sobre la idea en la que he estado trabajando en los últimos meses.

Existen muchas distribuciones Linux, cada una con su público. Para la mayoría de usuarios cualquiera es válida, pero cuando se trabaja con unos cuantos miles de máquinas Linux, el abanico de posibilidades disminuye. El grupo se reduce a distribuciones estables con ciclos de vida entre 5 y 10 años. Sin entrar a valorar cual es la mejor solución para estos entornos, voy a hablar de RHEL -que es la distribución que más conozco-, analizando los problemas con los que me he encontrado a lo largo de estos años trabajando en Hostalia y que han dado origen a este proyecto.

Todos conocemos cuales son los “problemas” de una distribución estable (versiones empaquetadas algo antiguas, no incluyen las últimas tecnologías, etc.) y todos también coincidimos en que “congelar” una release es el único camino para conseguir una solución segura, predecible, que implique poco mantenimiento, compatible con el ciclo de vida del hardware, etc.. en definitiva: una roca, pero una roca que lleva tiempo congelada.

Esta “roca” es válida para la mayoría de usuarios, otros se quedan fuera: ¿Cómo hago funcionar una aplicación que requiere PHP 5.3 cuando RHEL solo me ofrece la versión 5.1 (5 años más antigua)? ¿Cómo instalo el software NoSQL del que tanto se habla? Por otro lado tenemos las auditorías de seguridad, cuando un cliente paga por este servicio resulta complicado convencerle de que la versión 4.3.9 de PHP que lleva RHEL-4 no contiene las vulnerabilidades que le han hecho llegar en el informe (la rama PHP-4 no tiene soporte desde el 2007).

Todo esto no es nuevo, hace poco veíamos como Ubuntu -a modo de globo sonda- anunciaba una “rolling release” para “estar a la última en software”. También tenemos el reciente backport de Red Hat para PHP 5.3 en RHEL-5 (eso sí, con “php53” como paquete opcional), etc.

Aquí es donde nace la idea de PowerStack: un repositorio para RHEL (y clones como CentOS, Oracle Linux, etc) que contiene el software con el que se está construyendo la web ahora, para usuarios que necesitan mantener una base estable.

Esta primera versión se centra en el stack LAMP, empaquetando las últimas versiones de Apache + MySQL + PHP y aprovechando para incluir algunas mejoras: reiniciar servicios tras actualizar paquetes (Red Hat no lo hace, indispensable para una gestión centralizada desde Satellite), flags GCC para optimizar compilaciones + strip de binarios, compatible con EPEL (el repositorio extra “oficial” de Red Hat), etc.

A falta de definir una licencia, el proyecto ya está en GitHub y será libre. El wiki contiene el listado completo de paquetes junto a las instrucciones para habilitar el repositorio, así como el roadmap para ver hacía donde tiende PowerStack ;-)

Posted in Linux, Proyectos | Tagged , , | 40 Comments

Cuando los hombres eran hombres…

y construían sus propios RPMs:

Hello everybody out there using RHEL/CentOS-

I’m doing a (free) package repository with latest LAMP versions (just a hobby, won’t be big and professional like Red Hat) for RHEL and clones (CentOS).

This has been brewing since December 2009, and is starting to get ready. I’d like any feedback on things people like/dislike in RHEL, as my repo backports it somewhat (same package structure (due to practical reasons) among other things).

I’ve currently backported PHP 5.3.5, MySQL 5.5.9 and Apache 2.2.17, and things seem to work. This implies that I’ll get something practical within a few months, and I’d like to know what features most people would want. Any suggestions are welcome, but I won’t promise I’ll implement them :-)

Santi Saez

PS. Yes – it’s free of any Atomicorp code, and it has more features. It’s portable (i686 and x86_64 are supported), and it probably never will support anything other archs like s390, alpha, etc., as that’s all I have :-( .

Posted in Linux, Proyectos | Tagged | 3 Comments

Ejemplo práctico Cfengine: Actualización masiva de PHP

Tengo prácticamente acabado un post a modo de introducción a los sistemas de administración centralizada + automatización (Cfengine, Puppet, Spacewalk, etc..), mientras tanto iré comentado casos reales donde estos sistemas me han parecido realmente útiles e interesantes. A modo de ejemplo, empiezo explicando -a grandes rasgos- el método que utilizamos en Hostalia para actualizar PHP en la plataforma de alojamiento compartido, un cambio que afecta a más de 60.000 dominios distribuidos en unos cuantos cientos de servidores.

Ante un escenario así, donde la máxima de las leyes de Murphy siempre se cumplirá, no podemos actualizar todos los servidores en bloque y tampoco podemos actualizarlos manualmente uno por uno sin saber que pasará: necesitamos un método flexible, totalmente automatizado, que nos alerte de posibles errores antes de que lleguen al usuario, con un método sencillo de rollback para volver al estado anterior a la actualización, y por supuesto, todo ello sin cortes y totalmente transparente para los usuarios. Aquí es donde Cfengine nos ayuda día a día en este tipo de tareas ;-)

Vamos “directos al grano” y analizamos el fragmento de la configuración de Cfengine que se encarga de esta tarea:

- La definición de clases o grupos es una de las características mas potentes a la hora de trabajar con cualquier sistema de administración centralizada, permiten agrupar servidores sobre los que realizar una acción común, por ejemplo: podemos tener servidores bajo clases con nombre “PHP4″, “PHP5″, etc.. para diferenciar servidores que ejecutan diferentes versiones de PHP.

- Cfengine define internamente una serie de clases (Sistema Operativo, arquitectura, versión del kernel, distribución Linux, etc…), permitiendo además que el usuario pueda gestionar nuevos grupos y realizar operaciones sobre ellas: sumas de grupos, exclusiones, etc… por ejemplo, podemos agrupar las clases PHP4 y PHP5 bajo la clase PHP, para realizar una acción común sobre ellas, por ejemplo sincronizar el fichero de configuración php.ini en todos las máquinas que pertenezcan a este grupo. Recomiendo la lectura del documento de Jeremy Mates sobre las clases en Cfengine, una buena definición de grupos/clases será un punto clave para el éxito de cualquier sistema de administración centralizada.

- Para simplificar, en este ejemplo vamos a trabajar únicamente con dos clases: PHP5 y TESTING. El grupo “PHP5″, como podemos intuir, contiene el grupo de servidores que ejecutan la versión 5 de PHP, y la clase “TESTING” agrupa aquellas máquinas donde vamos a actualizar PHP de forma “controlada” (desde la versión 5.2.6 a la 5.2.8, nos saltamos la versión 5.2.7 ya que introducía una regresión en el tratamiento de las “magic quotes”). De la combinación de estos dos grupos nacen dos nuevos entornos: PHP5.!TESTING con servidores que seguirán ejecutando la versión 5.2.6 y PHP5.TESTING que tendrá los servidores que serán actualizados a la versión 5.2.8. En Cfengine el operador “.” suma las máquinas de una clase y “!” es el operador de negación.

- En Cfengine es posible agregar servidores a grupos de muchas formas, una de ellas es con la directiva FileExists. En el ejemplo, tras hacer un touch del fichero /etc/cfengine/testing el servidor pasará a formar parte de la clase “testing”, es decir, será un candidato a actualizar desde la versión 5.2.6 a 5.2.8 de PHP “automágicamente” ;-)

- A partir de aquí tendremos dos flujos de ejecución en Cfengine: máquinas que no se verán afectadas por la actualización y las que pasarán a actualizar PHP. En cualquier momento es posible pasar de un estado a otro, con tan solo crear o borrar el fichero /etc/cfengine/testing.

- ¿Que pasa si una máquina entra en estado “testing” Cfengine instalará la nueva versión del módulo DSO para Apache de PHP, sustituyendo para ello el fichero libphp5.so. Para mayor flexibilidad en Hostalia compilamos PHP, así no dependemos de paquetes/compilaciones de terceros, y además así podemos personalizar las funcionalidades, aplicar parches, etc.. En cualquier caso, el proceso de actualización podría ser cualquier acción: actualizar PHP con el módulo de gestión de paquetes del propio Cfengine, con independencia de si estamos sobre una Debian, CentOS, Solaris, FreeBSD, etc..

- Además, si está definida la clase testing se modifica la configuración de PHP para enviar los errores por syslog a una máquina remota, donde los logs están centralizados en un servidor con syslog-ng. En un escenario de shared hosting con gran volumen de dominios, es muy habitual que PHP esté constamente reportando errores, por lo que algunos patrones los ignoramos directamente (ver fragmento con las regex), para dedicar la atención a aquellos que lo necesitan y pueden llegar a ser realmente graves. Desde un único punto podemos analizar “en vivo” lo que ocurre en las máquinas en estado “testing”, dejando a un lado las máquinas estables que tienen todavía la versión anterior de PHP. Por defecto, PHP envía a syslog los mensajes con el servicio y prioridad user.notice (ver la función php_syslog en main/main.c), si la queremos modificar el parche para hardening de PHP Suhosin permite personalizar este comportamiento de logging.

- Solo si se realiza cualquiera de las dos acciones anteriores (copiar el fichero libphp5.so y/o php.ini) se define la variable restart_apache en Cfengine: el resto de servidores no se verán afectados.

- Si la variable restart_apache está definida, se hace un reinicio graceful de Apache para evitar cerrar las conexiones establecidas en ese momento. Los procesos que estén con la versión anterior de PHP una vez terminen de ejecutarse pasarán a tener la nueva versión sin corte, esto es necesario para evitar cualquier corte en el lado cliente.

Al tener los errores de PHP de la nueva plataforma centralizados en un único punto es muy sencillo detectar cualquier problema y automatizar acciones ante determinados errores, por ejemplo: si aparece la cadena “segmentation fault” en los logs de Apache, podemos forzar un rollback automático a la versión anterior de PHP, con alguna herramienta de análisis de logs tipo swatch, etc.. con tan solo borrar el fichero /etc/cfengine/testing.

Cuando consideremos el cambio lo suficientemente maduro como para aplicarlo a todos los servidores en producción, podremos llevarlo acabo con unos pequeños cambios en la configuración de Cfengine, básicamente borrando las referencias a la clase “testing”.

Conclusión: el sistema de clases/grupos de Cfengine es uno de sus puntos mas potentes, en este caso nos ha proporcionado un método de actualización + rollback sencillo para actualizar un componente en un determinado grupo de servidores, sin afectar al resto de servidores.. un método flexible, fiable y sin cortes para una operación crítica, todo ello con apenas 20 líneas de código y dedicándole unos pocos minutos de atención :-)

Posted in Linux, System Automation | Tagged , | 6 Comments