En el artículo Introducción a ZFS en FreeBSD enumeré las grandes ventajas de ZFS y expliqué paso a paso como definir pooles y crear datasets. En esta oportunidad voy a demostrar cómo configurar el servicio NFS (Network File System) para definir un espacio de almacenamiento en la nube (o sistema de archivos en red), y así poder aprovechar todas las ventajas que posee ZFS en FreeBSD desde clientes GNU/Linux.

Escenario

Poseo un servidor FreeBSD con un pool de datos ZFS configurado y funcionando, y diferentes datasets ya definidos. Mi interés es poder montar estos datasets ZFS desde clientes GNU/Linux, utilizando el protocolo NFS, para aprovechar todas las ventajas de ZFS que posee FreeBSD.

En el servidor FreeBSD, el pool ZFS "ztarahui" tiene definidos los datasets "zrosamonte/postgres" y "zrosamonte/www-data":

root@fbsd10-nfs:~ # df -h | grep ztarahui
ztarahui                              46G     25K     46G     0%    /ztarahui
ztarahui/zrosamonte              46G     27K     46G     0%    /ztarahui/zrosamonte
ztarahui/zrosamonte/postgres     48G    2.4G     46G     5%    /ztarahui/zrosamonte/postgres
ztarahui/zrosamonte/www-data     46G     39M     46G     0%    /ztarahui/zrosamonte/www-data

Ambos directorios /ztarahui/zrosamonte/postgres y /ztarahui/zrosamonte/www-data serán utilizados por servidores de bases de datos y servidores Web respectivamente, y son propiedad de diferentes usuarios:

root@fbsd10-nfs:~ # ll /ztarahui/zrosamonte/
total 3
drwxr-x---  3 postgres  postgres  3 Dec 19 11:48 postgres/
drwxr-x---  3 www-data  www-data  3 Dec 19 12:52 www-data/

Donde "postgres" y "www-data" con usuarios (y grupos) locales en el servidor FreeBSD:

root@fbsd10-nfs:~ # ll -n /ztarahui/zrosamonte/
total 3
drwxr-x---  3 1002  1002  3 Dec 19 11:48 postgres/
drwxr-x---  3 1001  1001  3 Dec 19 12:52 www-data/

El objetivo de este artículo es montar, a través del protocolo NFS, los directorios /ztarahui/zrosamonte/postgres y /ztarahui/zrosamonte/www-data, desde clientes GNU/Linux (Debian).

Manos a la obra

El primer paso consiste en habilitar el servicio NFS en el servidor FreeBSD, para ello es necesario agregar las siguientes líneas en el archivo de configuración del sistema (man rc.conf):

root@fbsd10-nfs:~ # nano /etc/rc.conf
nfs_server_enable="YES"
nfsv4_server_enable="YES"
nfsuserd_enable="YES"
mountd_flags="-r"
mountd_enable="YES"

Luego iniciar el servicio:

root@fbsd10-nfs:/ztarahui/zrosamonte # service nfsd start
Starting nfsuserd.
Starting rpcbind.
Starting mountd.
Starting nfsd.

El último paso consiste en definir los puntos de montaje remotos para solicitudes NFS. El archivo /etc/exports especifica los puntos de montaje remotos para el protocolo NFS. Cada línea del archivo (excepto las líneas de comentarios que comienzan con el caracter '#') especifica un punto de montaje y los flags dentro del filesystem local, o el árbol NFSv4 para uno o más hosts.

En cada punto de montaje, el primer campo especifica las rutas a los directorio en el sistema de archivos de un servidor que pueden ser montadas en los correspondientes clientes. El segundo campo especifica cómo el sistema de archivos es exportado a los clientes (-maproot o -mapall). El tercer campo especifica el conjunto de hosts para el cual la regla aplica.

Entonces, para que el cliente "debian", cuya dirección IP es 192.168.20.34, pueda montar los directorios /ztarahui/zrosamonte/postgres y /ztarahui/zrosamonte/www-data del servidor FreeBSD, es necesario agregar las siguientes líneas en el archivo /etc/exports:

V4: /
/ztarahui/zrosamonte/postgres -mapall=postgres:postgres 192.168.20.34
/ztarahui/zrosamonte/www-data -mapall=www-data:www-data 192.168.20.34

El campo -mapall indica las credenciales (usuario/grupo) utilizadas para el acceso remoto.

La línea V4: / no exporta ningún punto de montaje, sino que se utiliza para indicar dónde se encuentra la raíz del directorio del servidor para los clientes que se conectan mediante NFSv4.

Configuración en el cliente Debian

Para ser capaz de montar sistemas de archivos remotos NFS, se debe instalar el paquete nfs-common:

# apt-get install nfs-common

Luego es necesario configurar el servicio editando el archivo /etc/default/nfs-common

# nano /etc/default/nfs-common

Dentro del mismo se debe habilitar el servicio imapd:

NEED_IDMAPD=yes

¡Importante! Ingresar el valor "yes" en minúsculas, de lo contrario el servicio no reconocerá la configuración. Perdí varias horas debugueando hasta que descubrí que el script de gestión del servicio nfs-common (/etc/init.d/nfs-common) sólo reconoce los valores "yes" o "no" en la variable NEED_IDMAPD (la cual había configurado en "YES", por lo que nunca se iniciaba el servicio imapd).

El servicio imapd se encarga de mapear identificadores de usuarios y grupos (UID, GID) entre diferentes sistemas. Antes de la versión 4, NFS sólo trabajaba con los identificadores de usuario/grupo (UID/GID) numéricos, pero afortunadamente a partir de la versión 4 trabaja con los nombres de usuario/grupo. Esto simplifica la configuración, ya que no es necesario contar con identificadores numéricos idénticos para un mismo usuario entre diferentes sistemas, pues el servicio imapd (o nfsuserd en FreeBSD) se encarga de realizar el mapeo automáticamente.

Por ejemplo, en el servidor FreeBSD, el usuario "postgres" posee el identificador de usuario numérico 1002:

root@fbsd10-nfs:~ # cat /etc/passwd | grep postgres | cut -d':' -f1,2,3
postgres:*:1002

Mientras que en el cliente Debian, el usuario "postgres" posee el identificador de usuario numérico 105:

root@debian:~# cat /etc/passwd | grep postgres | cut -d':' -f1,2,3
postgres:x:105

Esto traería problemas al montar, porque para el sistema operativo (kernel, el cual sólo reconoce valores numéricos) se trataría de diferentes usuarios (105 != 1002).

El servicio imapd (el cual debe correr tanto en el cliente como en el servidor) se encarga de mapear de forma transparente el UID 105 (correspondiente al usuario "postgres" en el cliente Debian) con el UID 1002 (correspondiente al usuario "postgres" en el servidor FreeBSD), para que efectivamente se trate del mismo usuario "postgres" en ambos sistemas.

Incluso es posible definir reemplazos en el archivo de configuración /etc/idmapd.conf si los usuarios poseen nombres diferentes en ambos sistemas. En mi caso no necesité realizar traducciones de nombres de usuarios, por ende dejé los valores por defecto. Sólo es necesario configurar el nombre de dominio correctamente (variable Domain), el cual debe coincidir entre cliente y servidor, para que el mapeo de IDs de usuario/grupo funcione correctamente:

root@debian:~# cat /etc/idmapd.conf
[General]

Verbosity = 0
Pipefs-Directory = /var/lib/nfs/rpc_pipefs
Domain = nfsdomain

[Mapping]

Nobody-User = nobody
Nobody-Group = nogroup

Por otro lado, si no se utiliza imapd y un recurso debe ser compartido por varios clientes (cuyos usuarios/grupos poseen diferentes UID/GID numéricos), lograr un correcto funcionamiento sería casi imposible.

Como mencioné anteriormente, en FreeBSD este servicio se llama nfsuserd, por lo tanto es necesario habilitarlo en la configuración del sistema (ver el contenido del archivo /etc/rc.conf más arriba).

Bien, luego de configurar nfs-common e imapd, es necesario iniciarlos ejecutando:

root@debian:~# service nfs-common start
Starting NFS common utilities: statd idmapd.

Comprobar que hayan iniciado tanto statd como imapd.

A partir de este momento es posible montar los sistemas de archivos remotos que se encuentran en el servidor FreeBSD. Pero antes es necesario crear los directorios donde montar, en mi caso decidí montar debajo de /nfs:

root@debian:~# mkdir /nfs
root@debian:~# mkdir /nfs/postgres
root@debian:~# mkdir /nfs/www-data
root@debian:/nfs# ls -l
total 19
drwxr-xr-x  2 root root 4096 dic 17 13:15 postgres
drwxr-xr-x  2 root root 4096 dic 17 13:15 www-data

Se observa que ambos directorios son propiedad de "root".

Montar un sistema de archivos remoto mediante NFS es una tarea trivial:

root@debian:/nfs# mount -t nfs4 fbsd10-nfs:/ztarahui/zrosamonte/postgres /nfs/postgres
root@debian:/nfs# mount -t nfs4 fbsd10-nfs:/ztarahui/zrosamonte/www-data /nfs/www-data

Luego de especificar el tipo nfs4 (versión 4) se indica el recurso a montar, utilizando la sintaxis host:directorio, y luego el punto de montaje.

En el ejemplo utilicé el nombre de host "fbsd10-nfs", el cual he definido en el archivo de configuración estático de nombres de host:

root@debian:/nfs# cat /etc/hosts | grep nfs
192.168.20.12 fbsd10-nfs

Luego de haber montado, se observa que los directorios muestran correctamente usuario/grupo, señal de que imapd y nfsuserd han funcionado correctamente:

root@debian:/nfs# ls -l
total 6
drwxr-x--- 3 postgres postgres   3 dic 19 11:48 postgres
drwxr-x--- 3 www-data www-data   3 dic 19 12:52 www-data

Debugging

En caso de fallos, sobre todo al momento de mapear usuarios, es posible utilizar la herramienta rpcdebug en el cliente, la cual habilita o deshabilita los flags de debug de NFS en el kernel:

# rpcdebug -m nfs -s all
# tail -f /var/log/syslog

Al trabajar con sistemas de archivos remotos, esta herramienta genera toneladas de logs, por lo tanto es importante no olvidar deshabilitar los flags de debug de NFS al finalizar:

# rpcdebug -m nfs -c

Información adicional

Como siempre, la mejor documentación se encuentra en las manpages:

En GNU/Linux:

man nfs
man idmapd
man idmapd.conf 
man rpcdebug
man useradd
man chown
man chmod

En FreeBSD:

man nfsv4
man nfsuserd
man adduser
man chfn
man pw

Referencias

Wikipedia - Network File System

FreeBSD Handbook - Network File System (NFS)

idmapd.conf(5) - Linux man page

Ubuntu Community Help Wiki - NFSv4Howto

initrdWiki - NFS Debugging

nixCraft - Debian / Ubuntu Linux: Setup NFSv4 File Server


Tal vez pueda interesarte


Compartí este artículo