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
nixCraft - Debian / Ubuntu Linux: Setup NFSv4 File Server