Sin Imaginación

De todo un poco

Introducción a los clusters con Debian y Kerrighed

June 6th, 2013

Introducción

Computación Paralela y Distribuida

HPC es el acrónimo de high performance computing, en español, computación de alto rendimiento. Que una máquina tenga alto rendimiento implica que posee una capacidad de cálculo y procesamiento mayor que la media de las computadoras.

Este campo del hpc pertenence a la computación distribuida, el cual a la vez es un sub-conjunto de la computación paralela y ésta de la ciencia computacional. En la computación distribuida se utilizan un gran número de ordenadores interconectados y estructurados en diferentes modelos para la resolución de problemas que requieren una cantidad de procesamiento masiva, cosa que con equipos corriente e individuales, usualemtne tomaría una larga cantidad de tiempo.

La computación paralela es una forma de cómputo en la que muchas instrucciones se ejecutan simultáneamente, operando sobre el principio de que problemas grandes, a menudo se pueden dividir en unos más pequeños, que luego son resueltos simultáneamente (en paralelo).

Clusters y Grids

Los clusters (racimos o conjunto en su traducción al español) de computadoras, son muy utilizados en la computación distribuida pues nos permiten compilar la fuerza de procesamiento de varios equipos y utilizarlos en conjunto para distintas aplicaciones.

Hay varios tipos de clusters según la forma en la cual se les estructure y los requisitos que cumplan, están:

Los Clusters de Alto Rendimiento, los de Alta Disponibilidad y los de Alta Eficiencia.

A nivel empresarial son muy utlizados los de alta disponibilidad y los de alta eficiencia cuando se necesita ofrecer un servicio que esté disponible todo el tiempo, utlizando técnicas como Failover en donde si ocurre una falla en algún equipo se migran los procesos que estaban corriendo en éste hacia otro que esté inutilizable.

En las comunidades científicas a nivel de investigación se utilizan clusters de altos rendimientos pues se requiere gran capacidad de cómputo para aplicaciones que van desde simulaciones del medio ambiente, biomedicina, física de partículas, estadísticas, criptografía, etc.

La computación en grid o en malla es un nuevo paradigma de computación distribuida en el cual todos los recursos de un número indeterminado de computadoras son englobados para ser tratados como un único superordenador de manera transparente.

Estas computadoras englobadas no están conectadas o enlazadas firmemente, es decir no tienen por qué estar en el mismo lugar geográfico. Se puede tomar como ejemplo el proyecto SETI@Home, en el cual trabajan computadoras alrededor de todo el planeta para buscar vida extraterrestre.

En un cluster todos los nodos se encuentran en el mismo lugar, conectados por una red local para así englobar todos los recursos. En cambio, en un grid no tienen por qué estar en el mismo espacio geográfico; pueden estar en diferentes puntos del mundo.

Para que un clúster funcione como tal, no basta solo con conectar entre sí los ordenadores, sino que es necesario proveer un sistema de manejo del clúster, el cual se encargue de interactuar con el usuario y los procesos que corren en él para optimizar el funcionamiento.
En nuestro caso utilizaremos un SSI.

SSI (Single Sistem Image)

Un sistema de una única imagen es aquél que se encarga de darnos la sensación de que todas las computadoras trabajan como una sola, proveyendo una capa de abstracción intermendia entre las aplicaciones y el sistema operativo de modo que se centralizen y compartan los recursos ejectuados. Como ejemplo tenemos:

* Quantian
* BProc
* DragonFly BSD
* Genesis
* Kerrighed
* Mosix/OpenMosix
* OpenSSI
* Plurix
* Scyld
* TruCluster

Implementando un Cluster (HPC) con Kerrighed

Debo decir de antemano que hay formas más fáciles de montarse un cluster, simplificado todo el proceso al alcanze de dos o tres clicks de distancia. Sin embargo, el ensuciarse y hacer las cosas “manualmente” siempre ayuda a aprender, y como hay una variopinta cantidad de protocolos que interactúan el uno con el otro para llevar todo acabo resulta una experiencia gratificamente verlos en acción. Bien, empecemos.

El cluster lo van a formar 2 máquinas secundarías y el servidor principal. Usaré Debian Squeeze como distribución y Kerrighed como SSI. Sobra decir que el mismo procedimiento se aplica en otras distribuciones derivadas y no necesariamente tienen que ser 2 máquinas, sino que son las que utilizo para ilustrar el turorial.(y son las que tengo en casa 😛 ) Ignoro si por igual todo funcione en máquinas virtuales (pues no lo probé) pero teóricamente debería funcionar si el proceso se lleva a cabo d manera correcta.

Lo primero que haremos es construir una pequeña estructura en donde los nodos secundarios puedan iniciar desde la red (en vez del disco duro o la usb), todos conectados por medio de un pequeño swtich (al igual que el servidor).

null

Para que todo se lleve a cabo debemos montar en el nodo principal un servidor:

DHCP
PXE
TFTP
NFS

Procedimiento:

El nodo principal debe tener los servicios DHCP, NFS, TFTP y PORTMAP configurados y ejecutándose correctamente, así como tener montada toda la infraestructura de archivos que serán exportados y usados por los protocolos de red para servírsela a los nodos esclavos. Una vez iniciados los nodos, el servidor DHCP reparte las direcciones correspondientes a cada una de las máquinas conectadas basándose en la MAC de el equipo que haya hecho la petición, el protocolo PXE (cliente) leerá el archivo de configuración que le será enviado del servidor y descargará en la RAM de cada uno de los nodos secundarios el kernel de Kerrighed previamente configurado por medio del protocolo TFTP. Una vez descargado, se ejecutará y empezará el proceso de booteo en donde posteriormente se importará el directorio de archivos a través del protocolo NFS. Finalmente el cluster de Kerrighed iniciará cargando los nodos que se encuentren conectados y comenzará la repartición de carga.

Instalación de paquetes necesarios:

Primero instalaremos todo lo necesario para ejecutar los servidores:

sudo apt-get install isc-dhcp-server tftpd-hpa syslinux nfs-kernel-server nfs-common

En su orden correspondiente, los paquetes para el servidor dhcp, tftp, pxe y nfs.
Cuando se esté instalando el paquete tftpd-hpa, (si lo pide) recordar poner la ruta siguiente (/var/lib/tftpboot) como directorio en donde se encontrarán los archivos que se suban o descarguen del servidor. De lo contrario, sigan con la guía, más adelante se arregla.

Montar el servidor DHCP

Por medio del protocolo DHCP el servidor podrá otorgarle una dirección IP a los nodos de la red en función de la MAC de cada computadora, así podrán identificarse entre ellas. Primero verificamos la interfaz por la cual el servidor escuchará los paquetes DHCPREQUEST que les enviarán los nodos cuando inicien. Abrimos el archivo isc-dhcp-server (acá usamos nano pero pueden abrir el archivo con su editor de preferencia, dígase gedit, vim, emacs, etc):

nano /etc/default/isc-dhcp-server

# Defaults for dhcp initscript
# sourced by /etc/init.d/dhcp
# installed at /etc/default/isc-dhcp-server by the maintainer scripts
#
# This is a POSIX shell fragment
#
# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
# Separate multiple interfaces with spaces, e.g. “eth0 eth1″.
INTERFACES=”eth0″

En nuestro caso es la interfaz eth0 al estar utilizando nuestra tarjeta de red cableada.

Ahora editamos el archivo de configuración del servidor y agregamos el segmento de red que será repartido así como los archivos y las rutas que serán usadas por los demás protocolos. También agregamos la IP que le tocará a cada computador en función de su MAC. (para obtener la MAC de cada tarjeta de red basta con iniciar en windows y escribir en la consola (ipconfig /all) o en linux (ip addr) y anotarlas. (o en su defecto abrir la máquina y ver si está anotada en alguna etiqueta de la tarjeta de red).

nano /etc/dhcp/dhcpd.conf

Agregamos esta configuración en cualquier parte:

#Configuración en caso de que se quiera agregar un servidor DNS y proveer internet a los nodos.
option domain-name “kerrighed”; #el nombre de dominio del servidor, puede ser cualquiera.
option domain-name-servers 192.168.1.2; #la ip del servidor, configurada manualmente.

# Segmento de red repartido
subnet 192.168.1.0 netmask 255.255.255.0 {
option routers 192.168.1.2; # ip del servidor.
option broadcast-address 192.168.1.255; # la IP que servirá para los mensajes de broadcast de la red.
}
# La IP de los nodos y configuración para otros protocolos
group {
filename “pxelinux.0”; # archivo de configuración del protocolo PXE (/var/lib/tftpboot)
option root-path “192.168.1.2:/nfsroot/kerrighed”; # sistema de archivos que será exportado por el protocolo NFS

#nodo1
host kerrighednode1 {
fixed-address 192.168.1.101; #La ip del primer nodo.
hardware ethernet xx:xx:xx:xx:xx:xx; # MAC
}
#nodo2
host kerrighednode2 {
fixed-address 192.168.1.102; # La ip del segundo nodo.
hardware ethernet xx:xx:xx:xx:xx:xx; # MAC
}
server-name “kerrighedserver”; # El nombre del servidor, puede ser cualquiera.
next-server 192.168.1.2; # IP del servidor PXE, obviamente la de nuestro server.
}

Con esto terminanos la configuración del servidor DHCP. 😀

Montar el servidor TFTP y PXE

El servidor TFTP nos permitirá descargar el kernel de Kerrighed en cada uno de los nodos una vez el protoclo PXE lo permita. Iniciamos la configuración verificando que el archivo de configuración esté así:

nano /etc/default/tftpd-hpa

# /etc/default/tftpd-hpa

RUN_DAEMON=”yes”
TFTP_USERNAME=”tftp”
TFTP_DIRECTORY=”/var/lib/tftpboot”
TFTP_ADDRESS=”0.0.0.0:69″
TFTP_OPTIONS=”–secure”

En caso de que no nos haya pedido modificar la ruta del directorio tftp, lo arreglamos en el archivo, vamos a /var/lib y creamos la carpeta tftpboot.

El paquete syslinux que instalamos arriba nos provee de los archivos necesarios para permitir el booteo por medio del protocolo PXE. Copiamos el archivo que permite el booteo al directorio del servidor TFTP:

cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot

Creamos el directorio en donde estará el archivo de configuración por default que usarán los clientes PXE.

mkdir /var/lib/tftpboot/pxelinux.cfg

Se tiene la libertad de crear archivos de configuración distintos para cada uno de los nodos si se desea creando un archivo con la IP de cada nodo en hexadecimal. Por ejemplo:
Si la ip fuera 192.168.1.101, el nombre del archivo sería C0A80165.
Pero como no nos interesa, no lo haremos.

Montando el servidor NFS y el sistema de archivos

Por medio de este protocolo exportaremos el sistema de archivos que utilizarán y compartirán todos los nodos.

Creamos el directorio en donde estará el sistema de archivos:

mkdir /nfsroot/ && mkdir /nfsroot/kerrighed

Creamos una caperta que será necesaria para que el cluste funcione:

mkdir /nfsroot/kerrighed/config

Configuramos el archivo que contiene los directorios que serán exportados por NFS a los clientes:

nano /etc/exports

Y agregamos:

/nfsroot/kerrighed 192.168.1.0/255.255.255.0(rw,no_subtree_check,async,no_root_squash)

Re-exportamos el archivo pues acabamos de configurarlo:

exportfs -avr

Ahora vamos a crear una instalación minimalista de Debian Squeeze en el directorio que acabos de crear (/nfsroot/kerrighed), éstos serán los archivos que compartirán los nodos secundarios.

Instalamos la aplicación debootstrap, la cual nos permitirá crear la instalación minimalista:

apt-get install debootstrap

Creamos la instalación:

debootstrap –arch i386 squeeze /nfsroot/kerrighed http://ftp.us.debian.org/debian

Aquí squeeze (o wheezy, o lenny, etc) es la versión de Debian a descargar, /nfsroot/kerrighed es el directorio donde el nuevo sistema residirá, y http://ftp.us.debian.org/debian/ es el mirror desde donde se descargarán los paquetes. En caso de que estén en ubuntu cambian la versión (quantal x ejemplo) y el mirror (http://archive.ubuntu.com/ubuntu/).

Nota:la página oficial del proyecto de Kerrighed recomienda Debian Lenny como distribución para instalar su kernel.

Una vez terminada la instalación, debemos “loguearnos” al directorio creado para modificarlo sin problemas. Para ello usamos chroot como sigue:

chroot /nfsroot/kerrighed

Caeremos en la raíz del sistema, es decir, en el direcorio “/” . Solo recuerda que en realidad es el directorio /nfsroot/kerrighed en tu sistema anfitrión.

Creamos una contraseña para root:

passwd

Montamos el directorio /proc de nuestro sistema anfitrión en el sistema d archivos que será exportado de modo que podamos ejecutar programas en los nodos.

mount -t proc none /proc

Agregamos los paquetes básicos que necesitarán los nodos para comunicarse con el servidor:

nano /etc/apt/sources.list

deb http://ftp.us.debian.org/debian squeeze main non-free contrib
deb-src http://cdn.debian.net/debian/ squeeze main non-free contrib
deb http://cdn.debian.net/debian/ squeeze-updates main
deb-src http://cdn.debian.net/debian/ squeeze-updates main

Actualizamos e instalamos los paquetes:

apt-get update
apt-get install automake autoconf libtool pkg-config gawk rsync bzip2 libncurses5 libncurses5-dev wget lsb-release xmlto patchutils xutils-dev build-essential subversion dhcp3-common nfs-common openssh-server

Ahora necesitamos que se pueda comunicar con el servidor nfs, para eso modificamos este archivo:

nano /etc/fstab

y agregamos:

proc /proc proc defaults 0 0
/dev/nfs / nfs defaults 0 0
configfs /config configfs defaults 0 0
none /var/run tmpfs defaults 0 0

Modificamos el archivo hosts de modo que el servidor DHCP sepa a quién le asignará cual IP:

nano /etc/hosts

Agregamos:

127.0.0.1 localhost
192.168.1.2 kerrighedserver
192.168.1.101 kerrighednode1
192.168.1.102 kerrighednode2

Creamos un enlace simbólico de modo que el sistema de archivo se automonte en el servidor cuando éste esté disponible.

ln -sf /etc/network/if-up.d/mountnfs /etc/rcS.d/S34mountnfs

Configuramos la interfaz de red de modo que Network Manager no interfiera con el cliente NFS.

nano /etc/network/interfaces

Debe quedar:

# The loopback interface:
auto lo
iface lo inet loopback

# The primary network interface, manually configured to protect NFS:
iface eth0 inet manual

Creamos un nombre de usuario y salimos del chroot:

adduser nombre_de_usuario
exit

Una vez llegado hasta aquí podemos probar si los nodos secundarios pueden botear correctamente desde la red a la consola de nuestro debian squeeze recién instalado. Para eso creamos el siguiente archivo:

nano /var/lib/tftpboot/pxelinux.cfg/default

y agregamos el código d configuración para el cliente PXE:

LABEL linux
DEFAULT vmlinuz-KERNEL_VERSION console=tty1 root=/dev/nfs initrd=initrd.img-KERNEL_VERSION nfsroot=192.168.1.2:/nfsroot/kerrighed ip=dhcp rw

La versión del Kernel pueden obtenerla escribiendo en la consola:

uname -r

Ahora copiamos en el directorio del tftp el kernel y el initrd para poder bootear nuestro debian recién instalado.

cp /boot/vmlinuz-KERNEL_VERSION /boot/initrd.img-KERNEL_VERSION /var/lib/tftpboot/

Ahora reiniciamos todos los servicios:

/etc/init.d/tftpd-hpa restart
/etc/init.d/isc-dhcp-server restart
/etc/init.d/nfs-kernel-server restart

Finalmente entramos a la BIOS de cada nodo y configuramos el booteo desde la red. Si nos pide logearnos a la consola es porque todo ha ido bien. Ahora estamos preparados para instalar Kerrighed y centralizar nuestros nodos.

En caso de presentar el siguiente error una vez se ha cargado el kernel:

It display “Begin : Waiting for root file system…” and few minutes later :
“ALERT! /dev/nfs does not exist. Dropping to a shell!

Hay que reconstruir el initrd.img de modo que esté configurado para iniciar a través del NFS. En el sistema anfitrión hacemos lo siguiente:

nano /etc/initramfs-tools/initramfs.conf

Cambiamos la linea:
BOOT=local
a
BOOT=nfs

Guardamos y reconstruimos el initrd.

update-initramfs -u

Volvemos a ponerlo en el directorio del tftp y probamos de nuevo.

cp /boot/initrd.img-KERNEL_VERSION /var/lib/tftpboot/

Instalando Kerrighed

Kerrighed no es más que el kernel d linux en su versión 2.6.x con un conjunto de parches y aplicaciones creadas con el objetivo de permitir el sistema de única imagen. Para instalarlo hacemos lo siguiente:

Nota: Para compilar el kernel de Kerrighed desde la versión 2.3 el equipo de desarrollo ha dejado de darle soporte a las arquitecturas i386 / x86-32 / IA32 (32 bits), por lo tanto sólo desde las arquitecturas x86-64 (64 bits), será posible compilar el kernel desde la versión 2.4 en adelante. Voy a dividir la guía de instalación una para la versión 2.3.0 y otra para la 3.0 (última versión hasta el momento).

Nos “logueamos” dentro del sistema d archivo otra vez:

chroot /nfsroot/kerrighed

Versión 2.3.0

El Kernel de Kerrighed parece no poder compilar con versiones mayores de gcc-4.2, así que dependiendo de la distribución y la versión de ella que hayan instalado tendrán versiones distintas de gcc.

Para saber cuál versión tienen escribimos en la consola:

gcc -v

Si tienen una menor o igual que la 4.2 está bien, de lo contrario:

apt-get install gcc-4.1

Cambiamos el nombre del directorio original, remplazamos y likeamos:

mv /usr/bin/gcc /usr/bin/gcc.orig
ln -s /usr/bin/gcc-4.1 /usr/bin/gcc

Descargamos la versión 2.3.0 de la página oficial del proyecto, el kernel de linux en su versión 2.6 y lo guardamos en la ruta /usr/src.

wget -O /usr/src/kerrighed-2.3.0.tar.gz https://gforge.inria.fr/frs/download.php/4491/kerrighed-2.3.0.tar.gz
wget -O /usr/src/linux-2.6.20.tar.bz2 http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.20.tar.bz2

Nos desplazamos hasta el directorio y descomprimimos.

cd /usr/src
tar zxf kerrighed-2.3.0.tar.gz
tar jxf linux-2.6.20.tar.bz2

Accedemos al directorio y creamos el archivo de configuración.

cd kerrighed-2.3.0
./configure –with-kernel=/usr/src/linux-2.6.20

Patchamos el kernel, y creamos la configuración por defecto que usará el kernel:

make patch
make defconfig

Construimos los binarios e instalamos:

make kernel
make
make kernel-install
make install

null

Si todo ha ido bien, tendremos nuestro kernel de kerrighed compilado e instalado! 🙂
Ahora saltamos a la parte de verificar los archivos más abajo.

Versión 3.0

Descargamos la versión 3.0.0 de la página oficial del proyecto y lo guardamos en la ruta /usr/src

wget -O /usr/src/kerrighed-3.0.0.tar.gz http://gforge.inria.fr/frs/download.php/27161/kerrighed-3.0.0.tar.gz

Nos desplazamos a la ruta d la descarga, lo descomprimimos, renombramos el nombre de la carpeta y accedemos.

cd /usr/src
tar zxf kerrighed-3.0.0.tar.gz
mv kerrighed-3.0.0 kerrighed-src
cd kerrighed-src

Configuramos cómo será la instalación y se descargará la versión necesaria del Kernel d linux que será pacheado.

./configure –sysconfdir=/etc

En caso de que la descarga del kernel falle, ejecuten la siguiente linea:

wget -O /usr/src/kerrighed-src/patches/linux-2.6.30.tar.bz2 http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.30.tar.bz2 && ./configure –sysconfdir=/etc

Construimos los binarios e instalamos:

make
make install

Si todo ha ido bien deberíamos tener los siguientes archivos en las siguientes rutas:

/boot/vmlinuz-x.x.x-krg Kerrighed kernel
/boot/System.map Kerrighed kernel tabla de símbolos
/lib/modules/x.x.x-krg Kerrighed módulos
/etc/init.d/kerrighed Kerrighed service script *
/etc/default/kerrighed Configuración de Servicios
/usr/local/share/man Manpages
/usr/local/bin/krgadm Cluster herramientas de administración
/usr/local/bin/krgcapset Herramienta de capacidades de los procesos
/usr/local/bin/krgcr-run Process checkpoint/restart helper
/usr/local/bin/migrate Herramienta de migración de procesos
/usr/local/lib/libkerrighed-* Librerías de Kerrighed
/usr/local/include/kerrighed Archivos de Cabecera de Kerrighed

Ahora necesitamos atar los últimos cabos sueltos para dejar todo funcionando. Modificaremos el archivo kerrighed_nodes el cual se encarga de ver cómo el cluster trata a sus nodos.

nano /etc/kerrighed_nodes
session=1 #Es el identificador del cluster, esto es para cuando se tiene más de un cluster funcionando en una misma red. El valor puede ser de 1 a 255.
nbmin=2 #El número de nodos que deben cargar antes que el cluster se autoinicie.

Ahora verificamos el archivo que condiciona el comportamiento del cluster. Abrimos:

nano /etc/default/kerrighed

# Inicia el Cluster de Kerrighed
ENABLE=true
#ENABLE=false

# Inicia o desactiva el balanceador de carga automático.
LEGACY_SCHED=true
#LEGACY_SCHED=false

Salimos del chroot:

exit

Ahora debemos configurar el server TFTP para que cargue el kernel de Kerrgihed recién instalado y no el origianl de debian.

cp /nfsroot/kerrighed/boot/vmlinuz-x.x.x-krg /var/lib/tftpboot/

De igual forma modificamos el archivo de configuración que el server PXE envía a los clientes:

nano /var/lib/pxelinux.cfg/default

y le ponemos:

LABEL linux
DEFAULT vmlinuz-x.x.x-krg console=tty1 root=/dev/nfs nfsroot=192.168.1.2:/nfsroot/kerrighed ip=dhcp rw session_id=1

Ta dá! Ya tenemos todo atado, reiniciamos los servicios en el servidor y probamos:

/etc/init.d/tftpd-hpa restart
/etc/init.d/isc-dhcp-server restart
/etc/init.d/nfs-kernel-server restart

Utilizando Kerrighed

null

Desde el servidor nos logueamos a uno de los nodos por medio de ssh:

ssh usuario_del_cluster@192.168.1.101
También directamente como root:
ssh 192.168.1.101

Podemos verificar que todos los nodos están arriba de la siguiente manera:

krgadm nodes

Podemos tener los siguientes resultados:
101:online
102:present

Online implica que están participando activamente en el cluster. Present implica que están presentes pero no está formando parte del cluster.

Podemos verificar el proceso de booteo, viendo el log de inicio:

tail -f /var/log/messages

null

Podemos obtener información de los procesadores ejecutándose e información de la memoria disponible:

cat /proc/cpuinfo | grep “model name”
cat /proc/meminfo | grep “MemFree”

null

Para mostrar un ejemplo de la migración de procesos, compilamos el sgt programa:
#include

int es_primo(int n)
{
int tmp, lim;
for (tmp = 1, lim=0; tmp <= n; tmp++) if ( !(n%tmp) ) lim++; if(lim > 2) return 1;
return 0;
}
int main()
{


int tmp=0, countx;
while(tmp++ <= 2000000)
if( !(es_primo(tmp) ) )
printf("%d\n", tmp ), countx++;
return 0;


}

Compilamos:

gcc primo.c -o primo

Para monitorear el cluster ejecutamos el comando top y presionamos la tecla de número 1 para ver los cpu ejecutándose:

top

null

Ejecutamos el programa:

./primo

Observamos cómo aumenta la carga en un procesador:
null

Volvemos a ejecutar el mismo programa en el mismo cpu, pero ahora permitiendo que el proceso pueda migrar hacia otro nodo:

krgcapset -d +CAN_MIGRATE
./primo

Vemos el log del proceso migrado:
null

Y observamos cómo se distribuye la carga entre los nodos:
null

Leave a Reply

Powered by WordPress. Theme by Sash Lewis modified by 0aps.