====== Samba Cluster ====== ===== Введение ===== Предоставление файловых сервисов пользователям является типичной задачей и трудно найти офисную сеть в которой такие сервисы не работают. Наиболее распространенные протоколы - **NFS**(сетевая файловая система) и **CIFS**(windows shares и их аналог в *nix Samba), второй встречается намного чаще. В некоторых же бизнес-процессах файловый сервис занимает ключевую роль, например как в моей сети. У меня имеется хранилище объемом больше сотни терабайт и клиенты, которые исчисляются сотнями, работающие с этим хранилищем по протоколу CIFS. Каждый клиент подключен к сети по 1Гбит линку. Глядя на эти исходные данные, становится понятно, что CIFS-сервер должен быть достаточно производительным и иметь скоростной канал связи, например 10Гбит, но и этого со временем становится не достаточно, рано или поздно наступает момент, когда в высоту расти уже не получается(т.е. увеличивать производительность одного сервера), приходит время расти в ширину(т.е. увеличивать кол-во серверов), чем собственно в этой статье и займемся. Итак, исходные данные: имеем сотни терабайт данных и сотни высокоскоростных клиентов. Задача: построить отказоустойчивый высокоскоростной файловый кластер под управлением **Linux** и **Samba**. Кластер должен выполнять задачу подмены вышедших из строя узлов, а также распределение нагрузки по всем узлам кластера. Для решения этой задачи будет использоваться свободный аналог Red Hat 7 - Centos 7, хотя я и являюсь сторонником GNU/Debian, но в данной задачей, когда речь идет о дорогом брендовом оборудовании, чтобы не поиметь проблем с совместимостью, лучше использовать рекомендованные и поддерживаемые вендором ОС. Основные компоненты схематично указаны на рисунке ниже. {{ :samba_cluster:samba_cluster.png?direct&500 |}} Как видно из схемы, два(или более) сервера имеют доступ к общему хранилищу данных, чтобы корректно с ним работать, кто-то должен отвечать за контроль доступа к хранилищу и за блокировки, т.к. никак не связанные между собой сервера работают с общим ресурсом. Именно этой задачей, т.е. межпроцессной синхронизацией, и будет заниматься **DLM**(distrubuted lock manager). Далее нам понадобится кластерная файловая система, например **GFS**, в этой статье используется GFS2, она не работает напрямую с блочными устройствами, для нее нужен **LVM**(logical volume manager), но в нашем случае нужна кластерная его реализация - **CLVM**, но хорошая новость в том, что CLVM отличается от LVM по большому счету только наличием сервиса clvmd и небольшими настройками конфигурационного файла. Ну и наконец поверх DLM и CLVM находится сама кластерная ФС - GFS2. Всеми этими компонентами управляет [[pacemaker_theory|Pacemaker]], он обеспечивает запуск нужных служб, на нужных узлах и в нужном порядке, а также отслеживает их состояние, т.е. выполняет мониторинг. Итак, кластерная ФС, которая доступна на всех узлах у нас уже есть, осталось запустить файловую службу **Samba**, в этой статье используется 4-ая ветка. Но просто так это сделать нельзя, если мы не хотим получить неожиданные результат, например в виде испорченных данных. Т.е. Samba также нуждается в механизме управления блокировками, более того у всех узлов должна быть общая БД. В Samba используется **TDB**(trivial data base), в нашей конфигурации потребуется ее кластерная реализация - **CTDB**, которая кроме всего прочего умеет еще самостоятельно управлять службами **winbind** и **smbd**, т.е. запускать и останавливать их на нужных узлах и самое главное - CTDB берет на себя ф-ию по управлению IP-адресами узлов. Что это значит? Допустим у нас есть два узла с адресами 1.1.1.1 и 2.2.2.2 и один из узлов стал недоступен, об этом сразу станед известно CTDB и эта служба перенесет оба IP-адреса на оставшийся работающий узел, а также разошлет всем клиентам отказавшего узла уведомления о том, что TCP-соединение необходимо переустановить. Во всех документациях говорится, что по фен шую функционал по управлению службами smbd, winbind, а также IP-адресами должен выполнятся службой управления кластера Pacemaker. Т.е. CTDB должен быть сконфигурирован таким образом, что он не будет управлять ни службами, ни IP-адресами кластера. Он должен быть сконфигурирован как отдельный ресурс кластера, службы smbd и winbind также ресурсы кластера, которые запускаются после CTDB и IP-адреса аналогично, присваиваются после запуска smbd. Все это должно быть сконфигурировано таким образом с точки зрения красоты архитектуры, чтобы узлами кластера управляла одна система - Pacemaker, а не две Pacemaker и CTDB. В Pacemaker есть даже **RA**(resource agent) //ocf:heartbeat:CTDB//, который управляет службой CTDB, есть RA ocf:heartbeat:IPaddr2 для управления IP-адресами, есть даже RA ocf:heartbeat:portblock для отсылки уведомлений клиентам о том, что узел более недоступен(Tickle ACK), НО до сих пор нет RA для управления smbd и winbind, поэтому этими службами все же должен управлять CTDB, якобы это временно и вот-вот должны появится RA для Samba, но это было написано в 2010г и на текущий момент(2014г) ничего не изменилось. Поэтому лично я не вижу смысла отдавать управление адресами и Samba Pacemaker'у, потому что, во-первых, это несколько усложняет конфигурацию кластера, во-вторых, с этой задачей неплохо справляется сам CTDB и у него хорошо проработанные утилиты для мониторига и отслеживания состояния кластера. ===== Подготовка системы ===== Имеем два хоста с установленной ОС Linux Centos 7. Выполняем обновление системы. # yum update Отключаем SELinux, редактируем /etc/sysconfig/selinux: SELINUX=disabled Выключаем фаервол # systemctl stop firewalld # systemctl disable firewalld либо добавляем правила разрешающие узлам кластера взаимодействовать # firewall-cmd --permanent --add-service=high-availability # firewall-cmd --add-service=high-availability Настраиваем сеть, на каждом хосте по два сетевых интерфейса eth0 и eth1, первый используется для внутрикластерного взаимодействия и имеет сеть 192.168.232.0/24, а второй для обслуживания клиентов, сеть 10.0.0.0/24. Если в кластере всего два узла, то рекомендуется подключить интерфейсы eth0 напрямую друг к другу кросс-кабелем, для того, чтобы избежать лишней точки отказа - свитча. Итак, конфигурируем сеть, у первого узла будет адрес 192.168.232.10, у второго 192.168.232.20. Пример конфига /etc/sysconfig/network-scripts/ifcfg-eth0: DEVICE=eth0 ONBOOT=yes BOOTPROTO=static TYPE=Ethernet IPADDR=192.168.232.10 PREFIX=24 Настраиваем имена хостов, допустим samba_node1 и samba_node2, соответственно на каждом узле отдельно, /etc/hostname: samba_node1 Теперь надо настроить надежное разрешение имен на обоих узлах, а еще лучше, чтобы не зависеть еще от одного сервиса(DNS) и избавиться от дополнительной точки отказа, пропишем соответствие адреса и имени на каждом узле в /etc/hosts: 192.168.232.10 samba_node1 192.168.232.20 samba_node2 Перезагружаем оба узла # reboot Проверяем на обоих узлах [samba_node1 ~]# ping -c 1 samba_node2 PING samba_node2 (192.168.232.20) 56(84) bytes of data. 64 bytes from samba_node2 (192.168.232.20): icmp_seq=1 ttl=64 time=0.297 ms [samba_node2 ~]# ping -c 1 samba_node1 PING samba_node1 (192.168.232.10) 56(84) bytes of data. 64 bytes from samba_node1 (192.168.232.10): icmp_seq=1 ttl=64 time=0.323 ms Устанавливаем необходимое ПО # yum groupinstall "High Availability" # yum install samba samba-client gfs2-utils ctdb ===== Первоначальная настройка кластера ===== На всех узлах устанавливаем пароль на пользователя hacluster # passwd hacluster Включаем сервис pcsd на всех узлах # systemctl start pcsd.service # systemctl enable pcsd.service Авторизуем узлы в кластере(команда выполняется на любом узле), авторизуемся с пользователем hacluster и паролем, который установили ранее # pcs cluster auth samba_node1 samba_node2 Username: hacluster Password: samba_node1: Authorized samba_node2: Authorized Создаем кластер(команда выполняется на любом узле) # pcs cluster setup --start --name samba_cluster samba_node1 samba_node2 Shutting down pacemaker/corosync services... Redirecting to /bin/systemctl stop pacemaker.service Redirecting to /bin/systemctl stop corosync.service Killing any remaining services... Removing all cluster configuration files... samba_node1: Succeeded samba_node1: Starting Cluster... samba_node2: Succeeded samba_node2: Starting Cluster... Здесь samba_node1 и samba_node2 - имена узлов кластера, а samba_cluster - имя создаваемого кластера. В результате выполнения этой команды будет сгенерирован файл /etc/corosync/corosync.conf примерно такого содержания: totem { version: 2 secauth: off cluster_name: samba_cluster transport: udpu } nodelist { node { ring0_addr: samba_node1 nodeid: 1 } node { ring0_addr: samba_node2 nodeid: 2 } } quorum { provider: corosync_votequorum two_node: 1 } logging { to_syslog: yes } Включаем автозагрузку кластера(команда выполняется на любом узле) # pcs cluster enable --all samba_node1: Cluster Enabled samba_node2: Cluster Enabled Выключаем механизм stonith(команда выполняется на любом узле) # pcs property set stonith-enabled=false Механизм stonith отвечает за физическое отключение узла кластера, это может понадобится, когда связь с этим узлом потеряна и его состояние не известно, поэтому во избежании порчи данных узел с неизвестным состоянием изолируется(fence), т.е. физически выключается. Обычно для этих задач используют специальные адаптеры питания с функцией управления по сети. В боевых условиях отключать механизм stonith крайне не рекомендуется, но т.к. мы настраивает тестовую конфигурацию, мы так поступим. Вот и все, первичная настройка кластера завершена, убедиться в этом можно выполнив следующую команду: # pcs status Cluster name: samba_cluster Last updated: Tue Sep 16 19:00:28 2014 Last change: Tue Sep 16 19:00:11 2014 via cibadmin on samba_node2 Stack: corosync Current DC: samba_node1 (1) - partition with quorum Version: 1.1.10-32.el7_0-368c726 2 Nodes configured 0 Resources configured Online: [ samba_node1 samba_node2 ] Full list of resources: PCSD Status: samba_node1: Online samba_node2: Online Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled Как видно, оба узла онлайн, в качестве DC(Designated Co-ordinator) выбран узел samba_node1. Пока что наш кластер работает в холостую и не управляет никакими ресурсами(сервисами), этим мы займемся дальше. ===== Подключение LVM к кластеру ===== Включаем cluster locking в конфиге LVM и включаем автозагрузку демона lvmetad, все это можно сделать одной командой: # lvmconf --enable-cluster Проверяем, должно ровняться 3 # cat /etc/lvm/lvm.conf | grep "locking_type =" locking_type = 3 Теперь создаем два клонированных ресурса. Первый распределенный менеджер блокировок и второй - кластерный LVM(команды выполняются на любом узле) # pcs resource create dlm ocf:pacemaker:controld op monitor interval=30s on-fail=fence clone interleave=true ordered=true # pcs resource create clvmd ocf:heartbeat:clvm op monitor interval=30s on-fail=fence clone interleave=true ordered=true Настраиваем порядок запуска, dlm должен стартовать первым и оба демона должны выполняться на одном хосте # pcs constraint order start dlm-clone then clvmd-clone # pcs constraint colocation add clvmd-clone with dlm-clone Проверяем, что ресурсы успешно стартанули на обоих узлах # pcs resource show Clone Set: dlm-clone [dlm] Started: [ samba_node1 samba_node2 ] Clone Set: clvmd-clone [clvmd] Started: [ samba_node1 samba_node2 ] Ну а теперь создаем LVM том как обычно, все дальнейшие команды ничем не отличаются от обычной, не кластерной LVM(предполагается, что общий диск у всех нод - /dev/sdb). Команды выполнять только на одном узле. # pvcreate /dev/sdb # vgcreate samba_cluster /dev/sdb # lvcreate -n samba_cluster -l100%FREE samba_cluster Смотрим на обоих нодах(по-умолчанию тома должны быть видимы на всех нодах) # ls /dev/samba_cluster/samba_cluster ===== Создание кластерной ФС и подключение ее к кластеру ===== Создаем кластерную ФС GFS2 поверх только что созданного LVM тома. Кол-во журналов(-j 2) соответствует кол-ву нод кластера, протокол блокировки для кластера - lock_dlm # mkfs.gfs2 -p lock_dlm -t samba_cluster:cluster_FS -j 2 /dev/samba_cluster/samba_cluster /dev/samba_cluster/samba_cluster is a symbolic link to /dev/dm-2 This will destroy any data on /dev/dm-2 Are you sure you want to proceed? [y/n]y Device: /dev/samba_cluster/samba_cluster Block size: 4096 Device size: 10,00 GB (2620416 blocks) Filesystem size: 10,00 GB (2620413 blocks) Journals: 2 Resource groups: 40 Locking protocol: "lock_dlm" Lock table: "samba_cluster:cluster_FS" UUID: a750c8de-b4bc-2b0b-90ef-0a609319a657 После создания ФС можно попробовать ее примонтировать на обоих узлах # mount /dev/samba_cluster/samba_cluster /mnt/ Не забываем отмонтировать и проверить, что ФС не прописана в fstab, ее монтировать будет кластер. Настаиваем кластер(все команды выполняются на одном узле). Задаем поведение, требуемое при отсутствии кворума(чтобы не пострадали данные в случаи split brain) # pcs property set no-quorum-policy=freeze Создаем ресурс ФС, в случае необходимости к опциям можно добавить acl # pcs resource create clusterfs Filesystem device="/dev/samba_cluster/samba_cluster" directory="/mnt" fstype="gfs2" "options=noatime" op monitor interval=10s on-fail=fence clone interleave=true И наконец настраиваем порядок запуска и зависимости, т.е. ФС должна монтироваться после готовности LVM # pcs constraint order start clvmd-clone then clusterfs-clone # pcs constraint colocation add clusterfs-clone with clvmd-clone Проверяем, что все работает # pcs resource show Clone Set: dlm-clone [dlm] Started: [ samba_node1 samba_node2 ] Clone Set: clvmd-clone [clvmd] Started: [ samba_node1 samba_node2 ] Clone Set: clusterfs-clone [clusterfs] Started: [ samba_node1 samba_node2 ] # df -h /dev/mapper/samba_cluster-samba_cluster 10G 259M 9,8G 3% /mnt Как видим, ФС примонтирована и все ресурсы у кластера в рабочем состоянии. На этом настройка pacemaker закончена, переходим к заключительному этапу - настройка CTDB. ===== Настройка CTDB ===== Создаем на кластерной ФС директорию для Samba и файлы nodes, public_addresses для CTDB # mkdir /mnt/ctdb # touch /etc/ctdb/nodes # touch /etc/ctdb/public_addresses Редактируем конфиг /etc/sysconfig/ctdb CTDB_RECOVERY_LOCK="/mnt/ctdb/.ctdb.lock" CTDB_NODES=/etc/ctdb/nodes CTDB_PUBLIC_ADDRESSES=/etc/ctdb/public_addresses CTDB_MANAGES_SAMBA=yes CTDB_MANAGES_WINBIND=no CTDB_MANAGES_NFS=no CTDB_DEBUGLEVEL=NOTICE Если Samba интегрирована с Active Directory, то включаем еще опцию CTDB_MANAGES_WINBIND. В файле nodes перечислены IP-адреса всех узлов кластера, через которые взаимодействует ПО управления кластером - pacemaker и CTDB, эти адреса могут быть на отдельных интерфейсах, как уже упоминалось. # cat /etc/ctdb/nodes 192.168.232.10 192.168.232.20 Файл public_addresses содержит IP-адреса узлов через которые кластер обслуживает клиентов. Как упоминалось, этот файл нужен в случае если адресами управляет CTDB, он сам решит на какой узел какой адрес отдать. После адреса через пробел указывается сетевая карта, которой этот адрес присвоить, нужно перечислить все возможные варианты на всех узлах. # cat /etc/ctdb/public_addresses 10.0.0.100/24 eth1 10.0.0.200/24 eth1 И наконец редактируем конфиг Samba, он должен быть одинаков на всех узлах. [global] workgroup = COMPANY server string = Samba Test Cluster netbios name = MEGACLUSTER max protocol = SMB2 log file = /var/log/samba/log.%m max log size = 1000 security = user domain master = no domain logons = no local master = no os level = 33 preferred master = no load printers = no # ----------------------- Cluster Options ------------------------ clustering = yes # Две опции ниже важные, должны обязательно указывать на кластерную ФС, иначе можно # получить странные глюки private dir = /mnt/ctdb lock directory = /mnt/ctdb idmap backend = tdb2 passdb backend = tdbsam #============================ Share Definitions ============================== [test] comment = Cluster Share path = /mnt/share browseable = yes writable = yes Наконец включаем CTDB # systemctl enable ctdb.service # systemctl start ctdb.service После чего он должен распределить адреса по узлам и запустить Samba. Проверяем: # ctdb status Number of nodes:2 pnn:0 192.168.232.10 OK pnn:1 192.168.232.20 OK (THIS NODE) Generation:388325546 Size:2 hash:0 lmaster:0 hash:1 lmaster:1 Recovery mode:NORMAL (0) Recovery master:0 # ctdb ip Public IPs on node 1 10.0.0.100 0 10.0.0.200 1 # ip address show 3: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 00:0c:29:15:60:7b brd ff:ff:ff:ff:ff:ff inet 10.0.0.100/24 brd 10.0.0.255 scope global eno33554976 valid_lft forever preferred_lft forever # smbcontrol smbd ping PONG from pid 1:5658 Если Samba интегрирована с AD теперь можно попробовать подключиться со стороны клиента, если нет, то создаем учетную запись пользователя.