Содержание

Ceph RBD + OCFS2 - распределенное хранилище на блочных устройствах

Что делать, если нужно, чтобы доступ к системе хранения данных был не просто быстрым, а желательно равным скорости обращения к локальному SSD-диску? Единственным реально быстрым методом будет доставка блочного устройства напрямую клиенту. Со стародавних времен серверные СХД предоставляют такой доступ по средствам протокола iSCSI, и эта статья могла бы быть про это, но в наше время появилось дополнительно требование к подобным системам - это масштабируемость и отказоустойчивость (или “Высокая доступность”). Тут на сцену выходят програмно определяемые хранилища, такие как Ceph, GlusterFS, cStor, MayaStor и другие. Но наибольшей популярностью пользуется именно Ceph, т.к., несмотря на достаточно сложный порог входа, он имеет ряд архитектурных ноу-хау, которые кажутся весьма перспективными. И, при правильной организации кластера, может быть быстрым, гибким и готовым к работе в “боевых” условиях, как говорят - “Production ready”. Он конечно не самый быстрый, но в совокупности требований к современной СХД, он подходит больше всего.

В принципе, описываемая в данной статье технология, не плохо себя показала даже на неблоьших скоростях сетевого соединения, а именно - в гигабитной сети, но нужно понимать, что для обеспечения приемлемых показателей по задержкам (latency) нужно, чтобы сам сетевой стек мог это обеспечить, и для этого рекомендуется использовать сеть со скоростью не ниже сорока гигабит. Тогда, то о чем я говорил в начале будет реализуемо. Но даже без этого скорость доступа можно улучшить, если где-то вместо CephFS начать использовать связку RBD+OCFS2.

В данном контексте, еще следует сказать, что под собой подразумевает “кластерная файловая система”. Она нужна для синхронизации операций ввода-вывода именно на уровне файловой системы, а не данных которые в ней хранятся. Данный механизм необходим, чтобы обеспечить согласованность размещения данных, и не допустить возможности записи двумя клиентами в один и тот же блок блочного устройства, тем самым обеспечивая их целостность.

Да, еще следует сказать, что OCFS2 (Oracle Cluster File System version 2) - не единственная кластерная файловая система, её ближайший конкурент - GFS2 (Global File System version 2), но есть и другие. В моём случае выбор именно OCFS2 был определен рекомендациями со стороны моего ближайшего окружения, плюс - ее простота, в плане начального входного порога, а так же, она практически из коробки работает в ОС Ubuntu 22.04 LTS, которая для меня является приоритетной из-за большой поддержки со стороны мирового коммьюнити и самого Canonical.

Данная статья подразумевает, что у вас уже есть кластер Ceph, и в этом кластере уже есть какой-то пул, в котором мы будем создавать RBD-образы. Писать про настройку самого Ceph не вижу смысла, т.к. уже много всего про него понаписано и он сам не плохо задокументирован.

Создание и подключение RBD-образа

Создание

Опираясь на офф.документацию, создаем образ блочного устройства но стороне кластера Ceph:

1
rbd create --size 100G --thick-provision --object-size=4M --stripe-unit=4M --stripe-count=1 --image-feature=deep-flatten,exclusive-lock,fast-diff,layering,object-map rbd_pool/test-disk

При использовании ключа --thick-provision, диск будет создаваться дольше, т.к. в этом режиме всё выделяемое под него место будет заполняться нулями. Сама команда создания может быть гораздо короче, достаточно указать только размер и имя создаваемого образа в пуле, но так мне нравится больше, т.к. можно точно знать с какими настройками будет создан образ.

Подключение

Для начала, на стороне кластера, создадим пользователя:

1
ceph auth get-or-create client.rbd-test mon 'profile rbd' osd 'profile rbd pool=rbd_pool' mgr 'profile rbd pool=rbd_pool'

В реузльтате мы должны получить токен клиента для доступа к пулу, вида:

1
2
[client.rbd-test]
	key = AQBp0GFlsT+oIxAAYhZaM2NUNXzgxYiXZnvlpA==

Если по каким-то причинам вы не сохранили данный токен, то можно его получить выполнив:

1
ceph auth get client.rbd-test

Если токен больше не нужен, то чтобы его удалить:

1
ceph auth rm client.rbd-test

Далее, переходим к настройке на самом клиенте:

Устанавливаем необходимые пакеты:

1
sudo apt update && sudo apt install -y ceph-common

Создаем минимальный конфиг кластера в файле /etc/ceph/ceph.conf, который в принциае, можно скопировать с любой из нод самого кластера. Он имеет вид:

1
2
3
[global]
	fsid = b2651dd0-73b0-11ed-93db-1dd0691f9a33
	mon_host = [v2:192.168.0.1:3300/0,v1:192.168.0.1:6789/0] [v2:192.168.0.2:3300/0,v1:192.168.0.2:6789/0] [v2:192.168.0.3:3300/0,v1:192.168.0.3:6789/0]

Создаем файл /etc/ceph/ceph.client.rbd-test.keyring с токеном клиента, который был получен на этапе создания пользователя:

1
2
[client.rbd-test]
	key = AQBp0GFlsT+oIxAAYhZaM2NUNXzgxYiXZnvlpA==

После чего, можно попробовать подключить наше блочное устройство командой:

1
rbd device map rbd_pool/test-disk --id rbd-test

Если все получилось и при выполнении команды lsblk, в системе появилось блочное устройство /dev/rbd0 нужного размера, то можно добавить запись в файле /etc/ceph/rbdmap, чтобы устройство подключалось автоматически при загрузке системы. Содержимое файла будет выглядеть так:

1
2
3
4
# RbdDevice             Parameters
#poolname/imagename     id=client,keyring=/etc/ceph/ceph.client.keyring

rbd_pool/test-disk      id=rbd-test

Данный набор операций будет одинаковым на всех клиентах где будет использоваться это блочное устройство.

Создание кластера OCFS2

Проектирование

Исходя из офф.докуметации самого Oracle, мы должны сразу учитывать:

  • колличество клиентов
  • размер диска
  • колличество томов
  • наличе разделов

Так же существет два режима работы распространения данных синхронизации - local и global, которые так же следует учитывать при оценке масштабов кластера. Для больших кластеров, кластеров где ожидается наличие большого колличества томов, рекомендуется наличие как минимум трех нод, работающих в режиме “global”, чтобы в случае превышения тайм-аута получения данных синхронизации от большей части устройств иметь возможность удерживать кластер в консистентном состоянии.

Есть еще ряд нюансов, но для начала этого хватит.

Данный пример описывает использование кластера на двух нодах, по этому будет использоваться самый простой вариант - local.

Настройка кластера

Сначала установим необходимые пакеты:

1
sudo apt update && sudo apt install -y ocfs2-tools linux-image-generic
Примечание
Для работы кластера важно, чтобы клиентские системы реально резоливили имена хостов. Т.е. на самих клиентских хостах, в файле /etc/hostname и по DNS, имена должы соответствовать. Если использование DNS не подразумевается, то нужно будет прописать соответствия в файе /etc/hosts на всех узлах кластера файловой системы.

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

1
2
3
sudo o2cb add-cluster ocfs2test
sudo o2cb add-node ocfs2test server1 192.168.0.10
sudo o2cb add-node ocfs2test server2 192.168.0.11

В результате у нас должен получиться файл конфигурации /etc/ocfs2/cluster.conf, содержащий следющее:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
cluster:
	name = ocfs2test
	heartbeat_mode = local
	node_count = 2

node:
	cluster = ocfs2test
	number = 0
	ip_port = 7777
	ip_address = 192.168.0.10
	name = server1

node:
	cluster = ocfs2test
	number = 1
	ip_port = 7777
	ip_address = 192.168.0.11
	name = server2

Далее, полученный файл конфигурации нужно распространить на все ноды кластера.

После этого создаем файловую систему, исходя из ваших потребностей и размера файловой системы. В OCFS2 есть такой параметр как “Cluster Size” (ключ -C), размер которого определяется в зависимости от размера файловой системы.

Размер ФС Рекомендуемы минимальный размер кластера
1 ГБ - 10 ГБ 8K
10 ГБ - 100 ГБ 16K
100 ГБ - 1 ТБ 32K
1 ТБ - 10 ТБ 64K
10 TB - 16 TB 128K

Так же важным является параметр “Number of Slots” (ключ -N), который определяет максимальное колличество нод, которые могут быть одновременно подключены к тому. Для обеспечения лучшей производительности, рекомендуется устанавливать его значение равным минимум в два раза большим чем колличество нод. Так же говорится о том, что, если в будущем потребуется увеличить колличество слотов, то это может негативно сказаться на производительности, т.к. журнал файловой системы будет находится в разных частях диска.

Еще один важный параметр - “Journal Size” (ключ -J), который определяет размер журнала. Его значение может быть 64M, 128M или 256M, которое выбирается в зависимости от назначения диска. Т.е. если диск будет хранить файлы большого размера, то рекомендуется использовать размер 64M, если файлы смешанного размера - большие и маленькие, то 128M, если только маленькие, то 256M.

Опираясь на офф.документаию, создаем файловую систему:

1
 mkfs.ocfs2 -C 16K -J size=128M -N 4 --fs-feature-level=max-features --fs-features=norefcount /dev/rbd0

После этого необходимо настроить автоматический запуск кластера. Удобнее всего это делать с помощью команды:

1
sudo dpkg-reconfigure ocfs2-tools

Где все параметры можно оставить по умолчанию, кроме имени кластера, который мы указывали при создании, т.е. - ocfs2test.

Если вы захотите создаь кластер в режиме global, чего в рамках данного примера делать не нужно, то нужно будет переключить кластер в режим global:

1
o2cb heartbeat-mode ocfs2test global

Создать файловую систему, затем выполнить:

1
o2cb add-heartbeat ocfs2test /dev/rbd0

Тогда файл конфигурации кластера будет выглядеть так:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
cluster:
        name = ocfs2test
        heartbeat_mode = global
        node_count = 2

heartbeat:
        cluster = ocfs2test
        region = 534665E72FEC455F9147B31629B2C538

node:
        cluster = ocfs2test
        number = 0
        ip_port = 7777
        ip_address = 192.168.0.10
        name = server1

node:
        cluster = ocfs2test
        number = 1
        ip_port = 7777
        ip_address = 192.168.0.11
        name = server2

Где поле region, раздела heartbeat будет иметь значение UUID тома. Чтобы в этом убедиться, можно выполнить команду:

1
sudo tunefs.ocfs2 -Q "UUID = %U\nNumSlots =%N\n" /dev/rbd0

Вывод которой должен быть таким:

1
2
UUID = 534665E72FEC455F9147B31629B2C538
NumSlots =4

Чтобы убедиться, что все работает правильно выполняем:

1
journalctl -u o2cb.service -e

где в конце мы должны увидеть прмерно следующие сообщения:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Nov 24 17:37:02 server1 systemd[1]: Starting LSB: Load O2CB cluster services at system boot....
Nov 24 17:37:02 server1 o2cb[1314]: checking debugfs...
Nov 24 17:37:02 server1 o2cb[1314]: Loading stack plugin "o2cb": OK
Nov 24 17:37:02 server1 o2cb[1314]: Loading filesystem "ocfs2_dlmfs": OK
Nov 24 17:37:02 server1 o2cb[1314]: Mounting ocfs2_dlmfs filesystem at /dlm: OK
Nov 24 17:37:02 server1 o2cb[1314]: Setting cluster stack "o2cb": OK
Nov 24 17:37:02 server1 o2cb[1314]: Registering O2CB cluster "ocfs2test": OK
Nov 24 17:37:02 server1 o2cb[1314]: Setting O2CB cluster timeouts : OK
Nov 24 17:37:02 server1 o2hbmonitor[1368]: Starting
Nov 24 17:37:02 server1 systemd[1]: Started LSB: Load O2CB cluster services at system boot..

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

Псоле этого можно попробовать примонтировать наш диск:

1
2
mkdir /mnt/test
mount -t ocfs2 -o _netdev,defaults /dev/rbd0 /mnt/test

Так же можно добавить соответствующую запись в файле /etc/fstab, чтобы данный том монтировался автоматически. Запись будет выглядеть так:

1
/dev/rbd0 /mnt/test ocfs2 _netdev,defaults 0 0

Если в будующем вы захотите добавить дополнительную ноду, то нужно будет выполнить остановку сервиса o2cb.service на всех существующих нодах, после чего - добавить новую ноду, затем, распространить файл конфигурации на все ноды и запустить сервис обратно.

Если понадобится изменить настройки самой файловой системы, например, увеличить колличество слотов, то можно это сделать так:

1
tunefs.ocfs2 -N 8 /dev/rbd0