NFS — Network File System

Задача.

Сбалансировать нагрузку на 2 www+база данных сервера и заставить их использовать одно хранилище www-контента, базы данных и логов.

Вариант решения.

Резолв DNS имени www-сервера на 2 разных ip-адреса используемые www-серверами, и организация для них общего хранилища www-контента, базы данных и логов при помощи NFS

Настройка NFS-сервера

— Ядро должно быть собрано с опцией

options NFSSERVER # Network Filesystem Server

— Необходимо создать файл экспорта, в котором описываются локальные точки системы, доступные для монтирования клиентами, файл /etc/exports
— Формат файла:
/mnt/disk1/www /mnt/disk2/mysql /mnt/disk3/logs -maproot=0 192.168.0.10 192.168.0.11

Если требуется экспортировать более 3-х точек, например — 4, следует описывать их в другой строке файла. Иными словами, в одной строке должно быть не более 3х точек экспорта

Права доступа на точки экспорта в нашем случае описаны следующим образом:
— maproot=user
Права данного пользователя используются для удаленного подключения как root. Права включают все группы в которые входит пользователь на локальной машине. Может быть представлен по имени или uid (как в нашем примере).

192.168.0.10 192.168.0.11 — хосты которым разрешено монтирование.
Подробнее по синтаксису можно прочесть в man 5 exports

запуск сервера осуществляется последовательностью команд
/usr/sbin/rpcbind -l -h 192.168.0.1
/usr/sbin/mountd -r
/usr/sbin/nfsd -h 192.168.0.1 -t -n 8

Описание параметров
rpcbind
— l — Turn on libwrap connection logging
— h — биндинг адреса для UDP requests (если не указать — будет слушать на всех доступных)
mountd
— r — Allow mount RPCs requests for regular files to be served
nfsd
— h — биндинг адреса
— t — параметр, указывающий обслуживать только TCP-клиентов (если требуется работать по протоколу UDP, следует указать параметр -u)
— n — количество создаваемых серверов

Настройка WWW-серверов (NFS клиентов)

— Ядро должно быть собрано с опцией
options NFSCLIENT # Network Filesystem Client

Монтирование осуществляется командами вида
/sbin/mount_nfs -3 -T 192.168.0.1:/mnt/disk1/www /usr/local/www
/sbin/mount_nfs -3 -T 192.168.0.1:/mnt/disk2/mysqk /var/db/mysql
/sbin/mount_nfs -3 -T 192.168.0.1:/mnt/disk3/logs /var/log/httpd

Описание параметров
— 3 — использовать только версию 3 протокола NFS
— T — использовать TCP в качестве траспортного протокола (-U — udp по умолчанию)
192.168.0.1 — адрес nfs-сервера
/mnt/disk1/www — директория на сервере (описываются в /etc/exports на сервере)
/usr/local/www — локальная директория для монтирования на клиенте

Примечания
Для клиентов доступен демон nfsiod, который регулирует максимальное количество запускаемых клиентов (max — 20)
Для просмотра подробной статистики на сервере и клиентах можно использовать утилиту nfsstat.
Монтирование производится поверх локальных ресурсов (т.е. если примонтировать в директорию с данными, локальные данные не будут доступны до размонтирования).

Сетевая файловая система (Network File System – NFS) служит для обеспечения доступа компьютерам сети к общим каталогам на сервере.

Итак немного теории
NFS по смыслу и по организации работы похожа на разделяемые каталоги (shared folders) в системах Windows, но в этих службах используются совершенно разные протоколы работы и между собой они не совместимы. Однако, существует несколько программных продуктов, которые устанавливают поддержку NFS в системах Windows, поэтому применение NFS в сети с различными операционными системами не представляет проблемы, надо только помнить о необходимости использовать одинаковые версии NFS. В Данный момент используется в основном 3-я версия и внедрятся 4-я.

NFS работает посредством механизма удаленного вызова процедур (RPC – Remote Procedure Call).
Идеология RPC очень проста и привлекательна для программиста. Как обычно работает сетевое приложение? Оно следует некоему протоколу (например, HTTP): формирует пакет с запросом, вызывает системную функцию установления соединения, затем функцию отправки пакета, затем ждет ответного пакета и вызывает функцию закрытия соединения. Это значит, что вся работа с сетью является заботой программиста, который пишет приложение: он должен помнить о вызове функций сетевого API системы, думать о действиях в случае сбоев сети.

RPC предполагает иной способ обмена данными между клиентом и сервером. С точки зрения программиста, приложение клиента, работающее с помощью RPC, вызывает функцию на сервере, она выполняется и возвращает результат. Пересылка запроса на выполнение функции через сеть и возврат результатов от сервера клиенту происходит незаметно для приложения, поэтому последнее не должно беспокоиться ни о сбоях сети, ни о деталях реализации транспортного протокола.

Для того, чтобы обеспечить прозрачность пересылки данных через сеть, придумана двухступенчатая процедура. На сервере любое приложение, которое хочет предоставлять свой сервис через RPC, регистрируется в программе, которая называется транслятором портов (port mapper). Функция этой программы – устанавливать соответствие между номером процедуры RPC, которую запросил клиент, и номером TCP или UDP порта, на котором приложение сервера ждет запросов. Вообще говоря, RPC может работать не только с TCP или UDP

Приложение, которое регистрируется у транслятора портов, сообщает ему номер программы, номер версии и номера процедур, которые могут обрабатываться данной программой. Эти процедуры будут впоследствии вызываться клиентом по номеру. Кроме этого, приложение сообщает номера портов TCP и UDP, которые будут использоваться для приема запросов на выполнение процедур.

Клиент, желающий вызвать выполнение процедуры на сервер, сначала отправляет запрос транслятору портов на сервер, чтобы узнать, на какой TCP или UDP порт надо отправить запрос. Транслятор портов запускается при старте системы и всегда работает на стандартном порте 111. Получив ответ от него, клиент отправляет запрос на тот порт, который соответствует требуемому приложению. Например, сервер NFS работает на порту 2049.

Процедура монтирования общего каталога через NFS

Прежде чем мы перейдем к описанию настроек сервера и клиентов NFS, следует понять, как осуществляется монтирование удаленных файловых систем в принципе.

Клиент NFS посылает запрос на монтирование удаленному компьютеру, который предоставляет свою файловую систему (обычно – некоторую ее часть) для общего пользователя. При этом говорят, что сервер NFS «экспортирует» тот или иной каталог (подразумевается – с подкаталогами). Запрос от клиента NFS попадает на обработку демону mountd. Тот выдает клиенту NFS специальный ключ. Этот ключ является идентификатором, который однозначно идентифицирует каталог, смонтированный по сети.

По NFS можно смонтировать как целые файловые системы, так и отдельные каталоги. Из соображений безопасности запрещено монтировать каталоги «через раздел». Это означает, что если каталог /var расположен на одном разделе диска, а каталог /var/adm – на другом, то при монтировании каталога /var каталог /var/adm не будет автоматически смонтирован. Если требуется монтировать те подкаталоги экспортируемого каталога, которые расположены в другой файловой системе (на другом разделе), следует экспортировать их отдельно и указывать в /etc/dfs/dfstab еще один разделяемый каталог – тот самый подкаталог с другого раздела.

Ключ, выданный клиенту при монтировании и идентифицирующий сеанс работы с данным удаленным каталогом, сохраняется при перезагрузке NFS-сервера, чтобы после восстановления его работы клиенты, замершие в ожидании, продолжили работу с удаленным сервером как ни в чем ни бывало. При демонтировании и новом монтировании файловой системы через NFS ключ обычно изменяется. На практике перезагрузка NFS-сервера все-таки может привести к сбою в работе клиентского приложения, особенно, если приложение читает или записывает файл в удаленный каталог во время перезагрузки.

После монтирования файловой системы через NFS клиент посылает серверу запросы на передачу и прием файлов, эти запросы обрабатывает демон nfsd.

Демонтирование файловой системы выполняется также, как и демонтирование любой другой файловой системы – командой umount.

Процесс установки соединения

Cilent |                                        |  Server
       |запрос транслятору портов на сервер,    |
mount  |чтобы узнать, на какой TCP или UDP порт |
nfs    |надо отправить запрос для доступа к nfsd|
       | -------------------------------------> | 111 UDP (rpcbind)
       | <------------------------------------- |
       | Запрос к самому приложению (nfsd)      |
       | -------------------------------------> | 2049 TCP или UDP
       | <------------------------------------- | на выбор (NFSD)
       | Запрос порта приложения mountd         |
       | -------------------------------------> | 111 UDP (rpcbind)
       | <------------------------------------- |
       | Запрос на монтирование к mountd        |
       | -------------------------------------> | 12345 (выставлен руками)
       | <------------------------------------- | UDP (mountd)
       | Обмен данных по протоколу NFS          |
       | -------------------------------------> |
       | <------------------------------------- |

Настройка NFS-сервера

Для настройки NFS сервера нам потребуется выполнить настройку как минимум трех приложений: rpcbind, mountd и nfsd.

Переходим непосредственно к настройке
Вся настройка будет рассматриваться на ОС FreeBSD
Настройка NFS-сервера
Для настройки NFS сервера нам потребуется выполнить настройку как минимум трех приложений: rpcbind, mountd и nfsd.
Добавляем их в rc.conf

# NFS
# запуск nfsd
nfs_server_enable="YES"
# флаги для nfsd:
# "-u" - используем тока протокол UDP - причина - это не инет, потери пакетов
# весьма малы, а по ресурсоёмкости UDP выгодней. TCP - весьма `дорогой`
# протокол, требует больше ресурсов
# "-t" - использовать протокол TCP (можно использовать и TCP и UDP одновременно
# - выбор, в конечном итоге, за клиентом)
# "-n 1" - максимальное число одновременно подключенных клиентов
# "-h 11.22.33.44" - работать на одном адресе (интерфейсе). Если не указано -
# работате на всех. Может быть указана неоднократно. У меня на этой машине
# всего один интерфейс (не считая lo0 :)) потому её наличие бессмысленно.
nfs_server_flags="-t -n 1 -h 11.22.33.44"
# демон монтированя - принимает подключения от клиентов. Запускается
# автоматически при опции nfs_server_enable="YES". Ключи:
# "-r" - для обслуживания файлов а не тока каталогов (если я правильно понимаю
# значение - то можно расшарить файл, а не каталог. Может для кого-то и имеет
# смысл...)
# "-l" - регистрация всх запросов на монтирование
# "-n" - для возможности монтированя из-под винды (вернее, никсовую
# шару на форточки)
# "-p" - на каком порту запускать
# "-h" - работать на одном адресе (интерфейсе). Если не указано -
# работате на всех.
mountd_enable="YES"
mountd_flags="-r -p 12345 -h 11.22.33.44"
# удалённый вызов процедур - необходим для фунциклирования NFS
rpcbind_enable="YES"
rpcbind_flags="-h 11.22.33.44"
# "-h" - работать на одном адресе (интерфейсе). Если не указано -
# работате на всех.

Настраиваем файл экспорта (/etc/exports)

# То, что расшариваем по NFS
/etc/PF/www      -alldirs  -maproot=root  11.22.33.55
/usr/ports -maproot=root -network 192.168 -mask 255.255.0.0

В первом случае расшаривание для конкретного ip.
Во втором случае расшаривание каталога /usr/ports для всей частной сети (192.168.0.0/16 — или 192.168.0.0/255.255.0.0), с правами root`a для всех root`ов с удалённых машин. Причём можно было это сделать для любого удалённого пользователя — хоть для nobody 🙂

Теперь, если перезагрузить сервак, все встанет,
либо можно перезапустить службы таким вот скриптом

#!/bin/sh
/etc/rc.d/rpcbind restart
/etc/rc.d/nfsd restart
/etc/rc.d/mountd restart

Для проверки готовности всех служб NFS к работе через rpcbind
используется команда

rpcinfo -p
showmount -ae

можно также посмотреть провесились ли демоны или нет

[root@srv /etc/rc.d]# sockstat | grep nfs
root     nfsd       41300 3  tcp4   *:2049                *:*
root     nfsd       41300 4  tcp6   *:2049                *:*
[root@srv /etc/rc.d]# 

Настройки клиента
На клиентских машинах можно(не обязательно) прописать такие строки в /etc/rc.conf:
# Эта опция в-общем-то и не нужна, всё прекрасно монтируется и без неё,
# но с ней подрубается демон nfsiod, позволяющий проводить чтение-запись
# асинхронно, не дожидаясь окончания предыдущей операции.
nfs_client_enable="YES"
# скока демонов запускать (по одному на примонтированный ресурс)
nfs_client_flags="-n 1"
И пробуем подмонтровать (в хандбуке советуют на клиентах выполнить команду nfsiod -n 4
Теперь примонтируем шару с клиента (в данном случае по TCP и если сразу не получается, монтировать в фоне)

#В FreeBSD8
/sbin/mount_nfs -o tcp -o bg -i 192.168.20.251:/usr/ports /usr/ports
#В FreeBSD7 и ранее
/sbin/mount_nfs -T -b -i 192.168.20.251:/usr/ports /usr/ports

NFS-соединение работает по клиент-серверной схеме. Один компьютер является сервером и предоставляет свои файловые системы другим машинам. Это называется “NFS-экспортирование”, а предоставляемые файловые системы называют “экспортами”. Клиенты могут монтировать экспорты сервера почти точно так же как и локальные файловые системы.

Одним из интересных свойств NFS является отсутствие привязки клиента к текущему состоянию сервера (stateless). Вы можете перезагрузить сервер, при этом клиенты не “отвалятся”. Разумеется они не смогут получить доступ к экспортам сервера когда он отключен, однако как только сервер вернется в строй, вы сможете просто продолжить работу с места вашей остановки.

Ядро должно быть собрано с опцией

options NFSSERVER

Создаем файл экспорта /etc/exports, в котором описываются локальные точки системы, доступные для монтирования клиентами.
Мой файл выглядит так

/var/datas -maproot=root -alldirs 10.15.0.9
/var/data -maproot=root -alldirs 10.15.0.9

в моем файле две точки монтирования(/var/datas и /var/data). В одной строке максимум можно прописать три точки. Если их больше, то описываем их в следующей строке, но не более чем три точки на одну строку в файле.

Права доступа на точки экспорта в нашем случае описаны следующим образом:
— maproot=user
Права данного пользователя используются для удаленного подключения как root. Права включают все группы в которые входит пользователь на локальной машине. Может быть представлен по имени или uid (как в нашем примере).

10.15.0.9 – хост которому разрешено монтирование.

Далее делаем запись в /etc/rc.conf и перегружаем машину

rpcbind_enable=«YES»
nfs_server_enable=«YES»
nfs_server_flags=«-t -n 5 -h 10.15.0.2»
mountd_flags=«-r»
mountd_enable=«yes»

Описание параметров
rpcbind
— l – Turn on libwrap connection logging
— h – биндинг адреса для UDP requests (если не указать – будет слушать на всех доступных)
mountd
— r – Allow mount RPCs requests for regular files to be served
nfsd
— h – биндинг адреса
— t – параметр, указывающий обслуживать только TCP-клиентов (если требуется работать по протоколу UDP, следует указать параметр -u)
— n – количество создаваемых серверов

Ядро должно быть собрано с опцией

options NFSCLIENT

В /etc/rc.conf добавляем

nfs_client_enable=«YES»

Ну и собственно команды для монтирования

/sbin/mount_nfs -T 10.15.0.2:/var/data /var/data/ftp/pub/video1
/sbin/mount_nfs -T 10.15.0.2:/var/datas /var/data/ftp/pub/video2