Когда данных становится больше, чем влезает на один диск, самое время задуматься о RAID. В детстве часто слышал от старших: «однажды RAID уйдут в прошлое, объектные хранилища заполонят мир, а ты даже не знаешь, что такое CEPH»,- поэтому первым делом в самостоятельной жизни стало создание своего кластера. Целью эксперимента было ознакомиться с внутренним устройством ceph и понять рамки его применения. Насколько оправдано внедрение ceph в средний бизнес, а в малый? После нескольких лет эксплуатации и пары необратимых потерь данных возникло понимание тонкостей, что не всё так однозначно. Особенности CEPH создают препятствия его широкому распространению, и из-за них эксперименты зашли в тупик. Ниже приводится описание всех пройденных шагов, полученный результат и сделанные выводы. Если знающие люди поделятся опытом и пояснят некоторые моменты — буду благодарен.
Примечание: комментаторы указали на серьёзные ошибки в некоторых допущениях, требующие пересмотра всей статьи.
Стратегия CEPH
Кластер CEPH объединяет произвольное количество K дисков произвольного размера и хранит данные на них, дублируя каждый кусочек (4 МБ по умолчанию) заданное число N раз.
Рассмотрим простейший случай с двумя одинаковыми дисками. Из них можно либо собрать RAID 1, либо кластер с N=2 — результат получится один и тот же. Если дисков три, и они разного размера, то собрать кластер с N=2 легко: часть данных будут на дисках 1 и 2, часть — на 1 и 3, а часть — на 2 и 3, тогда как RAID — нет (можно собрать такой RAID, но это будет извращением). Если дисков ещё больше, то возможно создание RAID 5, у CEPH есть аналог — erasure_code, который противоречит ранним концепциям разработчиков, и поэтому не рассматривается. RAID 5 предполагает, что имеется небольшое количество дисков, и все они в хорошем состоянии. При отказе одного, остальные должны продержаться до момента, пока не заменят диск и не будут восстановлены на него данные. CEPH же, при N>=3, поощряет использование старых дисков, в частности, если держать несколько хороших дисков для хранения одной копии данных, а оставшиеся две-три копии хранить на большом количестве старых дисков, то информация будет в сохранности, так как пока живы новые диски — проблем нет, а если один из них сломается, то одновременный отказ трёх дисков со сроком службы более пяти лет, желательно, из разных серверов — событие крайне маловероятное.
В распределении копий есть тонкость. По умолчанию подразумевается, что данные делятся на больше количество (~по 100 на диск) групп распределения PG, каждая из которых дублируется на каких-то дисках. Допустим, K=6, N=2, тогда при выходе из строя двух любых дисков, гарантированно теряются данные, так как по теории вероятности, найдётся хотя бы одна PG, которая расположится именно на этих двух дисках. А потеря одной группы делает недоступными все данные в пуле. Если же диски разбить на три пары и разрешить хранить данные только на дисках внутри одной пары, то такое распределение также устойчиво к отказу одного любого диска, зато при отказе двух вероятность потери данных не 100%, а всего 3/15, и даже при отказе трёх дисков — только 12/20. Отсюда, энтропия в распределении данных не способствует отказоустойчивости. Также заметим, что для файлового сервера свободная оперативная память значительно увеличивает скорость отклика. Чем больше памяти в каждом узле, и чем больше памяти во всех узлах — тем будет быстрее. Это несомненно преимущество кластера перед одиночным сервером и, тем более, аппаратным NAS-ом, куда встраивают очень малый объём памяти.
Отсюда следует, что CEPH — хороший способ с минимальными вложениями из устаревшего оборудования создать надёжную систему хранения данных на десятки ТБ с возможностью масштабирования (тут, конечно, потребуются затраты, но небольшие по сравнению с коммерческими СХД).
Реализация кластера
Для эксперимента возьмём списанный компьютер Intel DQ57TM + Intel core i3 540 + 16 ГБ ОЗУ. Четыре диска по 2 ТБ организуем в подобие RAID10, после успешного испытания добавим второй узел и ещё столько же дисков.
Устанавливаем Linux. От дистрибутива требуется возможность кастомизации и стабильность. Под требования подходят Debian и Suse. У Suse более гибкий установщик, позволяющий отключить любой пакет; к сожалению, я не смог понять, какие можно выкинуть без ущерба для системы. Ставим Debian через debootstrap buster. Опция min-base устанавливает нерабочую систему, в которой не хватает драйверов. Разница в размере по сравнению с полной версией не так велика, чтобы заморачиваться. Поскольку работа ведётся на физической машине, хочется делать снапшоты, как на виртуалках. Такую возможность предоставляет либо LVM, либо btrfs (или xfs, или zfs — разница не велика). У LVM снапшоты — не сильная сторона. Ставим btrfs. И загрузчик — в MBR. Нет смысла засорять диск 50 МБ разделом с FAT, когда можно затолкать его в 1 МБ область таблицы разделов и всё пространство выделить под систему. Заняло на диске 700 МБ. Сколько у базовой установки SUSE — не запомнил, кажется, около 1.1 или 1.4 ГБ.
Устанавливаем CEPH. Игнорируем версию 12 в репозитории debian и подключаем прямо с сайта 15.2.3. Следуем инструкции из раздела «устанавливаем CEPH вручную» со следующими оговорками:
- Перед подключение репозитория необходимо установить gnupg wget ca-certificates
- После подключения репозитория, но перед установкой кластера опущена установка пакетов: apt -y —no-install-recommends install ceph-common ceph-mon ceph-osd ceph-mds ceph-mgr
- В момент установки CEPH по непонятным причинам будет пытаться установиться lvm2. В принципе, не жалко, но установка завершается сбоем, поэтому CEPH тоже не установится.
Помог этот патч:
cat << EOF >> /var/lib/dpkg/status Package: lvm2 Status: install ok installed Priority: important Section: admin Installed-Size: 0 Maintainer: Debian Adduser Developers <[email protected]> Architecture: all Multi-Arch: foreign Version: 113.118 Description: No-install EOF
Обзор кластера
ceph-osd — отвечает за хранение данных на диске. Для каждого диска запускается сетевая служба, которая принимает и исполняет запросы на чтение или запись в объекты. На диске создаётся два раздела. Один из них содержит информацию о кластере, номере диска, а также ключи от кластера. Эта информация объёмом 1КБ один раз создаётся при добавлении диска и больше никогда не замечал, чтобы менялась. На втором разделе нет файловой системы и хранятся двоичные данные CEPH. Автоматическая установка в предыдущих версиях создавала xfs раздел размером 100МБ для служебной информации. Я сконвертировал диск в MBR и выделил всего на 16МБ — служба не жалуется. Думаю, без проблем xfs можно было бы заменить и на ext. Этот раздел монтируется в /var/lib/…, где служба считывает информацию об OSD, а также находит ссылку на блочное устройство, где хранятся двоичные данные. Теоретически, можно сразу вспомогательные расположить в /var/lib/…, а диск целиком выделить под данные. При создании OSD через ceph-deploy автоматически создаётся правило для монтирования раздела в /var/lib/…, а также назначаются права пользователю ceph на чтение нужного блочного устройства. При ручной установке это необходимо сделать самому, в документации об этом не сказано. Также желательно указать параметр osd memory target, чтобы хватило физической памяти.
ceph-mds. На низком уровне CEPH — объектное хранилище. Возможность блочного хранения сводится к сохранению каждого блока 4МБ в виде объекта. По тому же принципу работает и файловое хранение. Создаётся два пула: один для метаданных, другой — для данных. Они объединяются в файловую систему. В этот момент создаётся какая-то запись, поэтому если удалить файловую систему, но сохранить оба пула, то восстановить её не получится. Есть процедура по извлечению файлов по блокам, не тестировал. За доступ к файловой системе отвечает служба ceph-mds. Для каждой файловой системы необходим отдельный экземпляр службы. Есть опция «индекс», которая позволяет создать подобие нескольких файловых систем в одной — тоже не тестировалось.
сeph-mon — эта служба хранит карту кластера. В неё входит информация обо всех OSD, алгоритм распределения PG в OSD и, самое главное, информация обо всех объектах (детали этого механизма мне непонятны: есть каталог /var/lib/ceph/mon/…/store.db, в нём лежит большой файл — 26МБ, а в кластере 105К объектов, получается чуть более 256 байт на объект,- я думаю, что монитор хранит список всех объектов и PG, в которых они лежат). Повреждение этого каталога приводит к потере всех данных в кластере. Отсюда и сделан вывод, что CRUSH показывает как PG расположены по OSD, а как объекты расположены по PG — централизованно хранятся внутри базы данных, как бы разработчики не избегали этого слова. Как следствие, во-первых, мы не можем установить систему на флешку в режиме RO, так как в базу данных ведётся постоянная запись, необходим дополнительный диск под эти (вряд ли более 1 ГБ), во-вторых, необходимо в реальном времени иметь копию этой базы. Если мониторов несколько, то отказоустойчивость обеспечивается автоматически, но в нашем случае монитор один, максимум — два. Есть теоретическая процедура восстановления монитора на основе данных OSD, трижды прибегал к ней по разным причинам, и трижды никаких сообщений об ошибках, как и данных тоже. К сожалению, этот механизм не работает. Либо мы эксплуатируем миниатюрный раздел на OSD и собираем RAID для хранения базы данных, что наверняка очень плохо скажется на производительности, либо выделяем хотя бы два надёжных физических носителя, желательно, USB, чтобы порты не занимать.
rados-gw — экспортирует объектное хранилище по протоколу S3 и подобные. Создаёт множество пулов, непонятно зачем. Особо не экспериментировал.
ceph-mgr — при установке этой службы запускаются несколько модулей. Один из них — не отключаемый autoscale. Он стремится поддерживать правильное количество PG/OSD. При желании управлять соотношением вручную, можно запретить масштабирование для каждого пула, но в таком случае модуль падает с делением на 0, и статус кластера становится ERROR. Модуль написан на питоне, и если закомментировать в нём нужную строчку, это приводит к его отключению. Детали лень вспоминать.
Список использованных источников:
Листинги скриптов:
Установка системы через debootstrap
blkdev=sdb1
mkfs.btrfs -f /dev/$blkdev
mount /dev/$blkdev /mnt
cd /mnt
for i in {@,@var,@home}; do btrfs subvolume create $i; done
mkdir snapshot @/{var,home}
for i in {var,home}; do mount -o bind @${i} @/$i; done
debootstrap buster @ http://deb.debian.org/debian; echo $?
for i in {dev,proc,sys}; do mount -o bind /$i @/$i; done
cp /etc/bash.bashrc @/etc/
chroot /mnt/@ /bin/bash
echo rbd1 > /etc/hostname
passwd
uuid=`blkid | grep $blkdev | cut -d """ -f 2`
cat << EOF > /etc/fstab
UUID=$uuid / btrfs noatime,nodiratime,subvol=@ 0 1
UUID=$uuid /var btrfs noatime,nodiratime,subvol=@var 0 2
UUID=$uuid /home btrfs noatime,nodiratime,subvol=@home 0 2
EOF
cat << EOF >> /var/lib/dpkg/status
Package: lvm2
Status: install ok installed
Priority: important
Section: admin
Installed-Size: 0
Maintainer: Debian Adduser Developers <[email protected]>
Architecture: all
Multi-Arch: foreign
Version: 113.118
Description: No-install
Package: sudo
Status: install ok installed
Priority: important
Section: admin
Installed-Size: 0
Maintainer: Debian Adduser Developers <[email protected]>
Architecture: all
Multi-Arch: foreign
Version: 113.118
Description: No-install
EOF
exit
grub-install --boot-directory=@/boot/ /dev/$blkdev
init 6
apt -yq install --no-install-recommends linux-image-amd64 bash-completion ed btrfs-progs grub-pc iproute2 ssh smartmontools ntfs-3g net-tools man
exit
grub-install --boot-directory=@/boot/ /dev/$blkdev
init 6
Создание кластера
apt -yq install --no-install-recommends gnupg wget ca-certificates
echo 'deb https://download.ceph.com/debian-octopus/ buster main' >> /etc/apt/sources.list
wget -q -O- 'https://download.ceph.com/keys/release.asc' | apt-key add -
apt update
apt -yq install --no-install-recommends ceph-common ceph-mon
echo 192.168.11.11 rbd1 >> /etc/hosts
uuid=`cat /proc/sys/kernel/random/uuid`
cat << EOF > /etc/ceph/ceph.conf
[global]
fsid = $uuid
auth cluster required = cephx
auth service required = cephx
auth client required = cephx
mon allow pool delete = true
mon host = 192.168.11.11
mon initial members = rbd1
mon max pg per osd = 385
osd crush update on start = false
#osd memory target = 2147483648
osd memory target = 1610612736
osd scrub chunk min = 1
osd scrub chunk max = 2
osd scrub sleep = .2
osd pool default pg autoscale mode = off
osd pool default size = 1
osd pool default min size = 1
osd pool default pg num = 1
osd pool default pgp num = 1
[mon]
mgr initial modules = dashboard
EOF
ceph-authtool --create-keyring ceph.mon.keyring --gen-key -n mon. --cap mon 'allow *'
ceph-authtool --create-keyring ceph.client.admin.keyring --gen-key -n client.admin --cap mon 'allow *' --cap osd 'allow *' --cap mds 'allow *' --cap mgr 'allow *'
cp ceph.client.admin.keyring /etc/ceph/
ceph-authtool --create-keyring bootstrap-osd.ceph.keyring --gen-key -n client.bootstrap-osd --cap mon 'profile bootstrap-osd' --cap mgr 'allow r'
cp bootstrap-osd.ceph.keyring /var/lib/ceph/bootstrap-osd/ceph.keyring
ceph-authtool ceph.mon.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring
ceph-authtool ceph.mon.keyring --import-keyring /var/lib/ceph/bootstrap-osd/ceph.keyring
monmaptool --create --add rbd1 192.168.11.11 --fsid $uuid monmap
rm -R /var/lib/ceph/mon/ceph-rbd1/*
ceph-mon --mkfs -i rbd1 --monmap monmap --keyring ceph.mon.keyring
chown ceph:ceph -R /var/lib/ceph
systemctl enable ceph-mon@rbd1
systemctl start ceph-mon@rbd1
ceph mon enable-msgr2
ceph status
# dashboard
apt -yq install --no-install-recommends ceph-mgr ceph-mgr-dashboard python3-distutils python3-yaml
mkdir /var/lib/ceph/mgr/ceph-rbd1
ceph auth get-or-create mgr.rbd1 mon 'allow profile mgr' osd 'allow *' mds 'allow *' > /var/lib/ceph/mgr/ceph-rbd1/keyring
systemctl enable ceph-mgr@rbd1
systemctl start ceph-mgr@rbd1
ceph config set mgr mgr/dashboard/ssl false
ceph config set mgr mgr/dashboard/server_port 7000
ceph dashboard ac-user-create root 1111115 administrator
systemctl stop ceph-mgr@rbd1
systemctl start ceph-mgr@rbd1
Добавление OSD (часть)
apt install ceph-osd
osdnum=`ceph osd create`
mkdir -p /var/lib/ceph/osd/ceph-$osdnum
mkfs -t xfs /dev/sda1
mount -t xfs /dev/sda1 /var/lib/ceph/osd/ceph-$osdnum
cd /var/lib/ceph/osd/ceph-$osdnum
ceph auth get-or-create osd.0 mon 'profile osd' mgr 'profile osd' osd 'allow *' > /var/lib/ceph/osd/ceph-$osdnum/keyring
ln -s /dev/disk/by-partuuid/d8cc3da6-02 block
ceph-osd -i $osdnum --mkfs
#chown ceph:ceph /dev/sd?2
chown ceph:ceph -R /var/lib/ceph
systemctl enable ceph-osd@$osdnum
systemctl start ceph-osd@$osdnum
Резюме
Главное маркетинговое преимущество CEPH — это CRUSH — алгоритм вычисления расположения данных. Мониторы распространяют клиентам этот алгоритм, после чего клиенты напрямую запрашивают нужный узел и нужный OSD. CRUSH обеспечивает отсутствие централизации. Он представляет собой маленький файл, который можно хоть распечатать и повесить на стену. Практика показала, что CRUSH не является исчерпывающей картой. Если уничтожить и заново создать мониторы, сохранив все OSD и CRUSH, то этого недостаточно для восстановления кластера. Отсюда сделан вывод, что на каждом мониторе хранятся некоторые метаданные обо всём кластере. Незначительный объём этих метаданных не накладывает ограничений на размер кластера, но требует обеспечить их сохранность, что исключает экономию диска за счёт установки системы на флешку и исключает кластеры с менее, чем тремя узлами. Агрессивная политика разработчика в отношении опциональных фич. Далеко до минимализма. Документация на уровне: «за то, что есть, — уже спасибо, но очень, очень скудно». Возможность взаимодействия со службами на низком уровне предусмотрена, но документация слишком поверхностно касается этой темы, поэтому скорее нет, чем да. Практически никакие шансы на восстановление данных из внештатной ситуации.
Варианты дальнейших действий: отказаться от CEPH и воспользоваться банальным много-дисковым btrfs (или xfs, zfs), узнать новую информацию о CEPH, которая позволит эксплуатировать его в указанных условиях, попробовать в качестве повышения квалификации написать собственное хранилище.
Источник: habr.com