En el presente artículo vamos a desarrollar una
arquitectura de almacenamiento compartido a la que accederán de forma concurrente un par de máquinas. Las pruebas van a ser realizadas bajo un sistema operativo de tipo CentOS 5.3.
El área de datos sobre el que se configurará el acceso compartido será un volumen lógico (
LogVol00) cuyo sistema de archivos será GFS2 (
Global File System 2). GFS es un sistema de ficheros nativo creado por Red Hat y distribuido bajo licencia GNU, que puede ser utilizado de forma local (como por ejemplo ext3) o en cluster, de manera que varios nodos puedan estar trabajando simultáneamente sobre él sin peligro a que se corrompan los datos. La capacidad máxima de almacenamiento de GFS2 es de 8 EB.
En la figura siguiente puede observarse que el espacio de almacenamiento compartido se instalará sobre la máquina centos01, el cual será exportado a los nodos centos02 y centos03 a través del driver iSCSI (
Internet Small Computer Systems Interface).
iSCSI permite la interconexión directa entre dispositivos de almacenamiento y computadores, encapsulando para ello el protocolo SCSI (familia de protocolos para comunicaciones con dispositivos de entrada/salida, especialmente dispositivos de almacenamiento) a través de una red TCP/IP. iSCSI puede utilizar tarjetas hardware dedicadas o emplear
iniciadores iSCSI junto con targets (u objetivos) SCSI para establecer la conectividad a través de tarjetas Ethernet. En este artículo se empleará la segunda opción.
Cada una de las máquinas deberá tener registrado los nombres de todos los nodos en el fichero
/etc/hosts.
[... ~]# cat /etc/hosts
...
192.168.1.11 centos01 centos01.local
192.168.1.12 centos02 centos02.local
192.168.1.13 centos03 centos03.local
SELinux e iptables deberán estar desactivados en los tres nodos. Al final del artículo veremos la forma de configurarlos correctamente para que no interfieran en el sistema de almacenamiento.
[... ~]# setenforce 0
[... ~]# service iptables stop
Lo primero que vamos a hacer es instalar el software necesario en los tres nodos.
[root@centos01 ~]# yum install lvm2-cluster rgmanager gfs2-utils scsi-target-utils
[root@centos02 ~]# yum install lvm2-cluster rgmanager gfs2-utils iscsi-initiator-utils
[root@centos03 ~]# yum install lvm2-cluster rgmanager gfs2-utils iscsi-initiator-utils
En el nodo centos01 editaremos el fichero de configuración del demonio tgtd (encargado de servir los espacios de almacenamiento compartido), indicando el volumen o dispositivo a exportar, el nombre de usuario y contraseña que será necesario emplear por parte de los clientes para poder conectarse al volumen, y las direcciones IP de los clientes a los que se les estará permitido conectarse.
El volumen servidor se conoce como objetivo y es definido a través de un nombre cualificado. El estándar iSCSI establece que tanto los objetivos como los iniciadores tienen que tener un nombre que siga el patrón
iqn.[yyyy-mm].[dominio invertido]:[identificador].
Por último, haremos que el servicio tgtd no sea persistente tras sucesivos reinicios de la máquina, ya que como veremos más adelante, será el propio cluster el encargado de iniciarlo y detenerlo automáticamente.
[root@centos01 ~]# cat /etc/tgt/targets.conf
<target iqn.2009-08.local:vol00>
backing-store /dev/VolGroup01/LogVol00
incominguser iscsi_user d6m1p9
initiator-address 192.168.1.12
initiator-address 192.168.1.13
</target>
[root@centos01 ~]# chkconfig tgtd off
Y en los nodos centos02 y centos03 haremos lo mismo pero con los demonios iniciadores (iscsid e iscsi). En el fichero de configuración especificaremos los datos de autenticación para poder descubrir el volumen y conectarnos a él.
[... ~]# cat /etc/iscsi/iscsid.conf
...
node.session.auth.authmethod = CHAP
node.session.auth.username = iscsi_user
node.session.auth.password = d6m1p9
discovery.sendtargets.auth.authmethod = CHAP
discovery.sendtargets.auth.username = iscsi_user
discovery.sendtargets.auth.password = d6m1p9
node.conn[0].timeo.noop_out_interval = 15
node.conn[0].timeo.noop_out_timeout = 15
[... ~]# chkconfig iscsid off
[... ~]# chkconfig iscsi off
Seguidamente vamos a crear el volumen lógico que se empleará como espacio compartido en centos01, empleando para ello una partición de 64 GB que ya tendremos creada previamente y etiquetada como
Linux LVM.
[root@centos01 ~]# fdisk -l
...
Disposit. Inicio Comienzo Fin Bloques Id Sistema
/dev/sdb1 1 8354 67103473+ 8e Linux LVM
Primero habrá que crear un volumen físico sobre esa partición, después el grupo de volúmenes (
VolGroup01) y por último el volumen lógico (
LogVol00).
[root@centos01 ~]# pvcreate /dev/sdb1
[root@centos01 ~]# vgcreate VolGroup01 /dev/sdb1
[root@centos01 ~]# lvcreate -l 100%FREE -n LogVol00 VolGroup01
Una vez que ya se tenga el volumen lógico, crearemos dentro de él un sistema de archivos GFS2. El parámetro
lock_dlm indica el protocolo de bloqueo a emplear, siendo
lock_dlm (
DLM - Distributed Lock Manager) para el caso de acceso concurrente y
lock_nolock para el caso de acceso de un único nodo. Con la opción de
-t se especifica el nombre del cluster y el nombre que le queremos dar al sistema de archivos, y con la opción
-j se indica el número de nodos que accederán concurrentemente al sistema de archivos.
[root@centos01 ~]# mkfs.gfs2 -p lock_dlm -t mycluster:gfs2_data -j 3 /dev/VolGroup01/LogVol00
Una vez construido el volumen, reiniciaremos el servicio tgtd y haremos que los nodos centos02 y centos03 descubran ese espacio de almacenamiento ofrecido por centos01. Cuando se realice la operación, dicha información quedará registrada de forma permanente en los directorios
/var/lib/iscsi/nodes/ y
/var/lib/iscsi/send_targets/.
De esta forma cada vez que posteriormente se inicie el cluster, se utilizarán dichos datos para conectarse. Si en un momento dado se quiere prescindir de dicho volumen, habría que eliminarlo de los directorios mencionados, o si por ejemplo se quiere añadir un nuevo espacio de almacenamiento compartido, habría que volver a ejecutar el comando "
iscsiadm -m discovery..." para descubrirlo previamente.
Decir también que una vez que se tiene registrado un espacio de almacenamiento, el demonio encargado de realizar su importación será
iscsi.
[root@centos01 ~]# service tgtd restart
[... ~]# service iscsid restart
[... ~]# iscsiadm -m discovery -t sendtargets -p centos01.local
192.168.1.11:3260,1 iqn.2009-08.local:vol00
[... ~]# ls /var/lib/iscsi/nodes/
iqn.2009-08.local:vol00
[... ~]# ls /var/lib/iscsi/send_targets/
centos01.local,3260
Para ver los dispositivos exportados por el servidor centos01 se puede ejecutar el siguiente comando:
[root@centos01 ~]# tgtadm --lld iscsi --op show --mode target
A continuación se va a crear un archivo denominado
cluster.conf el cual refleje la arquitectura de los tres nodos (deberá estar situado en las tres máquinas).
[... ~]# cat /etc/cluster/cluster.conf
<?xml version="1.0"?>
<cluster alias="mycluster" config_version="1" name="mycluster">
<fence_daemon clean_start="0" post_fail_delay="0" post_join_delay="3"/>
<clusternodes>
<clusternode name="centos03.local" nodeid="1" votes="1">
<fence>
<method name="1">
<device name="centos03.local" node="centos01.local"/>
</method>
</fence>
</clusternode>
<clusternode name="centos02.local" nodeid="2" votes="1">
<fence>
<method name="1">
<device name="centos02.local" node="centos01.local"/>
</method>
</fence>
</clusternode>
<clusternode name="centos01.local" nodeid="3" votes="1">
<fence>
<method name="1">
<device name="centos01.local" node="centos01.local"/>
</method>
</fence>
</clusternode>
</clusternodes>
<cman/>
<fencedevices>
<fencedevice agent="fence_scsi" name="iscsi"/>
</fencedevices>
<rm>
<failoverdomains>
<failoverdomain name="failover_centos01" nofailback="0" ordered="0" restricted="1">
<failoverdomainnode name="centos01.local" priority="1"/>
</failoverdomain>
<failoverdomain name="failover_centos02" nofailback="0" ordered="0" restricted="1">
<failoverdomainnode name="centos02.local" priority="1"/>
</failoverdomain>
<failoverdomain name="failover_centos03" nofailback="0" ordered="0" restricted="1">
<failoverdomainnode name="centos03.local" priority="1"/>
</failoverdomain>
</failoverdomains>
<resources>
<script file="/etc/init.d/iscsi" name="iscsi"/>
<script file="/etc/init.d/iscsid" name="iscsid"/>
<script file="/etc/init.d/tgtd" name="tgtd"/>
<clusterfs device="/dev/sdb" force_unmount="1" fsid="45982" fstype="gfs2" mountpoint="/mnt/gfs2_iscsi/" name="resource_gfs2_iscsi" self_fence="0"/>
</resources>
<service autostart="1" domain="failover_centos01" exclusive="0" name="service_centos01">
<script ref="tgtd"/>
</service>
<service autostart="1" domain="failover_centos02" exclusive="0" name="service_centos02">
<script ref="iscsid">
<script ref="iscsi">
<clusterfs ref="resource_gfs2_iscsi"/>
</script>
</script>
</service>
<service autostart="1" domain="failover_centos03" exclusive="0" name="service_centos03">
<script ref="iscsid">
<script ref="iscsi">
<clusterfs ref="resource_gfs2_iscsi"/>
</script>
</script>
</service>
</rm>
</cluster>
En una primera sección (
clusternodes) se definen los nombres de los tres nodos (
clusternode name) así como su método fencing asociado. El fencing viene a ser una especie de protección o de bloqueo que hace que los nodos esperen en esa "barrera" para poder sincronizarse.
Para el caso del ejemplo anterior, se ha declarado un dispositivo (
fencedevice) de tipo
fence_scsi en el nodo centos01, y a continuación se ha asociado a los tres nodos (
fence). Esto significa que si por ejemplo iniciamos centos01, éste esperará a finalizar su proceso de arranque hasta que los otros dos nodos se hayan conectado al servidor iSCSI, o si por ejemplo arrancamos centos02 y centos03, y centos01 todavía no está inicializado, esos dos nodos esperarán hasta que el servicio iSCSI esté listo antes de lanzar el cliente.
La otra sección principal del fichero de configuración es la de los recursos. Se han definido cuatro recursos: los scripts de los iniciadores iSCSI (iscsi e iscsid), el script de gestión del objetivo iSCSI (tgtd) y un volumen a ser montado.
Cuando se importe automáticamente el volumen exportado en los nodos centos02 y centos03, éste será accesible a través del dispositivo
/dev/sdb (cuando un dispositivo iSCSI es importado, se crea un nuevo dispositivo de bloque de igual forma que si se añadiera un nuevo disco duro).
También se ha creado un dominio (
failoverdomain) exclusivo para cada uno de los nodos. De esta forma podremos asociar posteriormente a cada uno de los dominios un determinado servicio (
service), el cual iniciará y detendrá ciertos recursos (
script ref,
clusterfs, ...).
Así de esta forma el servicio
service_centos02 hará que cuando se inicie automáticamente (
autostart="1"), se ejecute en el nodo centos02 el script iscsid, a continuación el script iscsi y por último, se monte el volumen importado sobre el directorio
/mnt/gfs2_iscsi/, el cual tendremos que crear previamente en los nodos centos02 y centos03.
[... ~]# mkdir /mnt/gfs2_iscsi
Ahora sólo tendremos que reiniciar los demonios gfs2, cman, rgmanager y clvmd en cada uno de los nodos, y mediante el comando chkconfig haremos que dichos demonios se inicien automáticamente cada vez que arranque el nodo.
[... ~]# service gfs2 restart
[... ~]# service cman restart
[... ~]# service rgmanager restart
[... ~]# service clvmd restart
[... ~]# chkconfig gfs2 on
[... ~]# chkconfig cman on
[... ~]# chkconfig rgmanager on
[... ~]# chkconfig clvmd on
Si ejecutamos el comando clustat, podremos ver la configuración actual del cluster que acabamos de levantar. Por un lado se tiene la lista de miembros del cluster (
Member Name) y por el otro, la lista de servicios definidos (
Service Name), así como su propietario (
Owner) y estado (
State).
[root@centos01 ~]# clustat
Cluster Status for mycluster @ Thu Aug 6 12:55:51 2009
Member Status: Quorate
Member Name ID Status
------ ---- ---- ------
centos03.local 1 Online, rgmanager
centos02.local 2 Online, rgmanager
centos01.local 3 Online, Local, rgmanager
Service Name Owner (Last) State
------- ---- ----- ------ -----
service:service_centos01 centos01.local started
service:service_centos02 centos02.local started
service:service_centos03 centos03.local started
Si en un momento dado deseamos conocer el número de nodos asociados al sistema GFS2, podremos ejecutar el siguiente comando:
[root@centos02 ~]# gfs2_tool journals /mnt/gfs2_iscsi/
journal2 - 128MB
journal1 - 128MB
journal0 - 128MB
3 journal(s) found.