Статья является пошаговым руководством по построению масштабируемого отказоустойчивого файлового хранилища, доступ к которому будет осуществлен по протоколам Samba, NFS. В качестве файловой системы, которая будет непосредственно отвечать за сохранение и масштабирование файловой шары будем использовать GlusterFS, о котором было уже достаточно написано хабрасообществом. Так как GlusterFS — часть Red Hat Storage, туториал написан для RH — like систем.
Использую версию 3.3.1, rpm-ки скачаны с официального сайта. После создания volume, клиент может получить к нему доступ несколькими способами:
Мы будем использовать первый вариант, так как в этом случае клиент устанавливает связь со всеми серверами и при отказе сервера к которому мы монтировались, мы получаем данные с рабочих серверов:

Отлично механика работы описана в этом посте. Хотелось бы добавить, что распределение нагрузки на кластер с использованием LVS в документации прописана только для сети NAT, по этому будем использовать Round Robbin DNS. Есть в стандартных репозиториях, так же как и SMB, NFS:
Допустим, у нас есть 2 ноды:
Еще необходима парочка IP, которые будут воплощать отказоустойчивость — мигрировать между серверами.
RR DNS для домена data выглядит так:
В создание volume для GlusterFS я углубляться не буду. Скажу, что нам необходимо распределенно — репликационный раздел (distributed+replicated volume). Назовём его smb. Для начала монтируем его локально для каждой ноды:
Каждый сервер в качестве опции использует свой hostname . Не забываем занести запись в /etc/fstab.
Теперь правим конфигурацию Samba (на каждом сервере).
…
# Основной параметр, отвечает за кластеризацию.
# Связь с БД, которая хранит обращения пользователей (см. ссылку про механику работы )
# Папка, с конфигурационными файлами
И туда же добавим секцию самой шары:
Папка получится для общего пользования, доступ от пользователя smbcli без авторизации. Пожже создадим его и назначим права.
Тепер на одном из серверов создаем папку, в которой будем размещать некоторые конфигурационные файлы CTDB
И добавим файл:
Конфигурационный файл CTDB на каждом сервере приводим к виду:
# Файл, который исполняется каждый раз, когда нода кластера CTDB изменяет свой статус (например письмецо отправлять)
Указываем наши public adresses (на каждом сервере):
Указываем ноды кластера CTDB (на каждом сервере):
SElinux я отключаю, IPtables выглядят следующим образом (естественно, для каждого сервера):
# Вместо названия цепочек, можно укзать просто ACCEPT.
Вернемся к Samba и пользователю smbcli (на каждом сервере):
Предпоследние штрихи:
Теперь можно наблюдать
Список публичных мигрирующих IP и их приналежность к серверам получаем командой
Монтируем клиенту по протоколу SMB или NFS командами:
Из личного опыта скажу, что падения сети тестирую до сих пор, результат очень даже сносный. Обрыв соединения практически не заметен. В��е обьясняет AndreyKirov
Приятного коддинга!

Каким же образом эти сервисы взаемодействуют?
GlusterFS
Использую версию 3.3.1, rpm-ки скачаны с официального сайта. После создания volume, клиент может получить к нему доступ несколькими способами:
# mount.glusterfs
# mount -o mountproto=tcp,async -t nfs
# mount.cifs
Мы будем использовать первый вариант, так как в этом случае клиент устанавливает связь со всеми серверами и при отказе сервера к которому мы монтировались, мы получаем данные с рабочих серверов:

CTDB
Отлично механика работы описана в этом посте. Хотелось бы добавить, что распределение нагрузки на кластер с использованием LVS в документации прописана только для сети NAT, по этому будем использовать Round Robbin DNS. Есть в стандартных репозиториях, так же как и SMB, NFS:
# yum install ctdb samba nfs-utils cifs-utils
Прис��упим
Допустим, у нас есть 2 ноды:
gluster1, 192.168.122.100
gluster2, 192.168.122.101
Еще необходима парочка IP, которые будут воплощать отказоустойчивость — мигрировать между серверами.
192.168.122.200
192.168.122.201
RR DNS для домена data выглядит так:
; zone file fragment
data. 86400 IN A 192.168.122.200
data. 86400 IN A 192.168.122.201
В создание volume для GlusterFS я углубляться не буду. Скажу, что нам необходимо распределенно — репликационный раздел (distributed+replicated volume). Назовём его smb. Для начала монтируем его локально для каждой ноды:
# mount.glusterfs gluster1:smb /mnt/glustersmb
Каждый сервер в качестве опции использует свой hostname . Не забываем занести запись в /etc/fstab.
Теперь правим конфигурацию Samba (на каждом сервере).
# vim /etc/samba/smb.conf
…
[global]
# Основной параметр, отвечает за кластеризацию.
clustering = yes
# Связь с БД, которая хранит обращения пользователей (см. ссылку про механику работы )
idmap backend = tdb2
# Папка, с конфигурационными файлами
private dir = /mnt/glustersmb/lock
И туда же добавим секцию самой шары:
[pub]
path = /mnt/glustersmb/lock
browseable = YES
force user = smbcli
force group = smbcli
writable = yes
guest ok = yes
guest account = smbcli
guest only = yes
Папка получится для общего пользования, доступ от пользователя smbcli без авторизации. Пожже создадим его и назначим права.
Тепер на одном из серверов создаем папку, в которой будем размещать некоторые конфигурационные файлы CTDB
# mkdir /mnt/glustersmb/lock
И добавим файл:
# touch /mnt/glustersmb/lock/lockfile
Конфигурационный файл CTDB на каждом сервере приводим к виду:
# vim /etc/sysconfig/ctdb
CTDB_RECOVERY_LOCK=/mnt/glustersmb/lock/lockfile
CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses
CTDB_MANAGES_SAMBA=yes
CTDB_NODES=/etc/ctdb/nodes
CTDB_MANAGES_NFS=yes
# Файл, который исполняется каждый раз, когда нода кластера CTDB изменяет свой статус (например письмецо отправлять)
CTDB_NOTIFY_SCRIPT=/etc/ctdb/notify.sh
Указываем наши public adresses (на каждом сервере):
# vim /etc/ctdb/public_addesses
192.168.122.200/24 eth0
192.168.122.201/24 eth0
Указываем ноды кластера CTDB (на каждом сервере):
# vim /etc/ctdb/nodes
192.168.122.100
192.168.122.101
SElinux я отключаю, IPtables выглядят следующим образом (естественно, для каждого сервера):
# vim /etc/sysconfig/iptables
-A INPUT -p tcp --dport 4379 -j ctdb
-A INPUT -p udp --dport 4379 -j ctdb
-A INPUT -p tcp -m multiport --ports 137:139,445 -m comment --comment "SAMBA" -j SMB
-A INPUT -p udp -m multiport --ports 137:139,445 -m comment --comment "SAMBA" -j SMB
-A INPUT -p tcp -m multiport --ports 111,2049,595:599 -j NFS
-A INPUT -p udp -m multiport --ports 111,2049,595:599 -j NFS
-A INPUT -p tcp -m tcp --dport 24007:24220 -m comment --comment "Gluster daemon" -j ACCEPT
-A INPUT -p tcp -m tcp --dport 38465:38667 -m comment --comment "Gluster daemon(nfs ports)" -j ACCEPT
# Вместо названия цепочек, можно укзать просто ACCEPT.
Вернемся к Samba и пользователю smbcli (на каждом сервере):
# useradd smbcli
# chown -R smbcli.smbcli /mnt/glustersmb/pub
Предпоследние штрихи:
# chkconfig smbd off
# chkconfig ctdb on
# service ctdb start
Теперь можно наблюдать
# ctdb status
Number of nodes:2
pnn:0 192.168.122.100 OK (THIS NODE)
pnn:1 192.168.122.101 OK
Generation:1112747960
Size:2
hash:0 lmaster:0
hash:1 lmaster:1
Recovery mode:NORMAL (0)
Recovery master:0
Список публичных мигрирующих IP и их приналежность к серверам получаем командой
# ctdb ip
Public IPs on node 0
192.168.122.200 node[1] active[] available[eth0] configured[eth0]
192.168.122.201 node[0] active[eth0] available[eth0] configured[eth0]
Монтируем клиенту по протоколу SMB или NFS командами:
# mount.cifs data:smb /mnt
# mount -o mountproto=tcp,async -t nfs data:smb /mnt
Из личного опыта скажу, что падения сети тестирую до сих пор, результат очень даже сносный. Обрыв соединения практически не заметен. В��е обьясняет AndreyKirov
Ликбез
Узел, который принял на себя IP адрес другого, знает о старых TCP соединениях только то, что они были, и не знает «TCP squence number» соединений. Соответственно, не может их продолжить. Также как и клиент, ничего не знает о том, что соединения теперь осуществляются с другим узлом.
Для того чтобы избежать задержек связанных с переключением соединения используется следующий прием. Для понимания этого приема нужно понимать основные принципы функционирования протокола TCP.
Новый узел, получив себе ip адрес, посылает клиенту пакет с флагом ACK и заведомо неправильным «squence number» равным нулю. В ответ клиент, в соответствии с правилами работы протокола TCP, отправляет назад пакет ACK Reply с корректным «squence number». Получив корректный «squence number» узел формирует пакет с флагом RST и этим «squence number». Получив его, клиент незамедлительно перезапускает соединение.
Приятного коддинга!