Pull to refresh

Выбор и настройка SDS Ceph

Reading time9 min
Views13K
Всем привет, Уважаемые читатели и практики!

Щупал я всякие разные и разнообразные Block/File Storage с SAN'ами и был в общем-то счастлив, пока не появилась задача понять — что же такое Object Storage? И при наличии уже многих решений на рынке выбрать тот самый…

Зачем же Object Storage?


Ну, во-первых — это система хранения, специально разработанная именно для хранения объектов. И это именно и прежде всего Storage.

Во-вторых — система элегантно превращается в WORM (write once read many) и обратно.
В-третьих — достигается разделение пулов с данными для разных пользователей, гибкая настройка квотирования по пользователям, размерам пулов, количеством объектов, количеством bucket в пулах. В общем, нормальный функционал администрирования системы хранения.
В-четвертых, в-пятых и т.д. Каждый, кто знает зачем ему это нужно, уверен найдет еще не одно преймущество. А может и недостатки.

Требования к выбору объектного хранилища:

— де факто стандарт ОС — CentOS;
— нужно объектное хранилище, резервированное между ЦОД;
— по возможности быть совсем бесплатным.
Совсем такие скудные и туманные требования.

Начал я процесс поиска с обзора имеющихся:

  • ScaleIO — круто, просто, но шаг в сторону — лицензия, а так хочется независимости. И с ходу не нашел возможности обеспечения отказоустойчивости конфигурации для ЦОДов;
  • OpenIO — видимо начинающий проект и я не нашел описания нужного мне функционала;
  • Ceph — что же, можно попробовать. Изначальным скудным требованиям удовлетворяет.

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

Первое, что было сделано — это выбор версии. Последнюю Luminous ставить не стал, только-только был релиз, а мы же серьезная компания. :) Про Hammer было много нареканий. Мне по душе пришелся Jewel в stable релизе. Создал репозиторий, зарсинкал его с ceph.com, поставил задания в крон и выпустил его через nginx. Еще нам нужен будет EPEL:

# Синхронизуем репозиторий Ceph-Jewel
/usr/bin/rsync -avz --delete --exclude='repo*' rsync://download.ceph.com/ceph/rpm-jewel/el7/SRPMS/ /var/www/html/repos/ceph/ceph-jewel/el7/SRPMS/
/usr/bin/rsync -avz --delete --exclude='repo*' rsync://download.ceph.com/ceph/rpm-jewel/el7/noarch/ /var/www/html/repos/ceph/ceph-jewel/el7/noarch/
/usr/bin/rsync -avz --delete --exclude='repo*' rsync://download.ceph.com/ceph/rpm-jewel/el7/x86_64/ /var/www/html/repos/ceph/ceph-jewel/el7/x86_64/
# Синхронизуем репозиторий EPEL7
/usr/bin/rsync -avz --delete --exclude='repo*' rsync://mirror.yandex.ru/fedora-epel/7/x86_64/ /var/www/html/repos/epel/7/x86_64/
/usr/bin/rsync -avz --delete --exclude='repo*' rsync://mirror.yandex.ru/fedora-epel/7/SRPMS/ /var/www/html/repos/epel/7/SRPMS/
# Обновляем репозиторий Ceph-Jewel
/usr/bin/createrepo --update /var/www/html/repos/ceph/ceph-jewel/el7/x86_64/
/usr/bin/createrepo --update /var/www/html/repos/ceph/ceph-jewel/el7/SRPMS/
/usr/bin/createrepo --update /var/www/html/repos/ceph/ceph-jewel/el7/noarch/
# Обновляем репозиторий EPEL7
/usr/bin/createrepo --update /var/www/html/repos/epel/7/x86_64/
/usr/bin/createrepo --update /var/www/html/repos/epel/7/SRPMS/


и приступил к дальнейшему планированию и установке.

Сначала необходимо нарисовать архитектуру решения, пусть даже и тестового, но которое может легко быть смаштабировано до прода, к которому мы будем стремиться. У меня получилось следующее:

— по три OSD ноды в каждом ЦОД;
— три MON ноды на трех площадках (по одной на каждой), которые будут обеспечивать большинство для кластера Ceph; (ноды-мониторы можно поднимать совместно с другими ролями, но я предпочел их сделать виртуальными и вынести вообще на VMWare)
— две ноды RGW (по одной в каждом ЦОД), которые обеспечат доступ по API к Object Storage по протоколу S3 или Swift; (ноды-RadosGW можно поднимать совместно с другими ролями, но я предпочел их сделать виртуальными и тоже вынести на VMWare)
— нода для деплоя и централизованного управления; (виртуальный сервер, который катается между ЦОД'ами в среде VMWare)
— нода мониторинга кластера и текущего/исторического перфоманса. (та же история, что и с нодой деплоя)

Спланировать сети — я же использовал одну сеть для «экосистемы» Ceph кластера. Для доступа к нодам деплоя, мониторинга и RGW нодам было проброшено две сети:

— сеть Ceph кластера, для доступа к ресурсам;
— сеть «public», для доступа «из-вне» к этим нодам.
Официальная документация рекомендует внутри кластера использовать разные сети для heartbeat и движения данных между OSD нодами, хотя та же документация гласит, что использование одной сети уменьшает latency… Я выбрал одну сеть для всего кластера.

Установка кластера начинается с базовой процедуры: подготовка серверов-нод с ОС CentOS.
— настраиваем репозитории, если они локальные. (например, как у меня) Еще нам потребуется EPEL-репозиторий;
— на всех нодах в /etc/hosts вносим информацию о всех нодах кластера. Если в инфраструктуре используется DHCP, то лучше сделать bind для адресов и все-равно заполнить /etc/hosts;
— настраиваем ntp и синхронизуем время, это критично, для корректной работы Ceph;
— создаем пользователя для управления кластером Ceph, любое имя, главное не одноименное — ceph.

Например так:

sudo useradd -d /home/cephadmin -m cephadmin
sudo passwd cephadmin
echo "cephadmin ALL = (root) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/cephadmin
chmod 0440 /etc/sudoers.d/cephadmin


— устанавливаем ssh-сервер на ноде деплоя, генерируем ключи для созданного пользователя, копируем ключи на все ноды кластера, прописываем в sudo с опцией NOPASSWD. Нам нужно будет получить для пользователя беспарольный вход с деплой-ноды на все ноды кластера;
— у созданного пользователя в каталоге .ssh создаем файлик config, описываем все ноды и ставим права 600 на этот файл;

[cephadmin@ceph-deploy .ssh]$ cat config
Host ceph-cod1-osd-n1
Hostname ceph-cod1-osd-n1
User cephadmin
...................
Host ceph-cod2-osd-n3
Hostname ceph-cod2-osd-n3
User cephadmin


— открываем порты 6789/tcp и 6800-7100/tcp в firewalld, если вы его решили оставить;
— отключаем SELinux; (хотя с версии ceph — Jewel с установкой накатываются нормальные SE-политики)
— на ноде управления кластером выполняем yum install ceph-deploy.

Вроде все готово! Переходим к установке и настройке самого кластера


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

Создаем первую MON ноду в нашем будущем кластере: ceph-deploy new #имя_нашей_MON_ноды. В созданной ранее директории появился файл ceph.conf, в который теперь будет вноситься описание кластера и применяться его содержимое на нужных нам нодах.

Устанавливаем сам Ceph-Jewel на всех нодах: ceph-deploy install --release=jewel --no-adjust-repos #нода1 #нода2… #нодаN. Ключ --no-adjust-repos необходимо использовать, если репозиторий для установки локальный и чтобы установочный скрипт искал путь в существующих /etc/yum.repos.d/*.repo, а не пытался прописать свой репозиторий. С версии Jewel по умолчанию ставится stable версия, если явно не указано обратное.

После успешной установки инициализируем кластер ceph-deploy mon create-initial

По завершении инициализации кластера, в файл ceph.conf записывается первоначальная конфигурация, в том числе и fsid. Если этот fsid в последствии будет изменен или потерян кластером — это приведет к его «развалу» и, как следствие, потери информации! Итак, после наличия первоначальной конфигурации в ceph.conf мы его смело открываем (сделав backup) и начинаем править и вносить те значения, которые нам нужны. При проливке по нужным нам нодам обязательно указываем опцию --overwrite-conf. Ну и примерное содержание нашего конфига:

[root@ceph-deploy ceph-cluster]# cat /home/cephadmin/ceph-cluster/ceph.conf
[global]
fsid = #что-то_там
mon_initial_members = ceph-cod1-mon-n1, ceph-cod1-mon-n2, ceph-cod2-mon-n1
mon_host = ip-adress1,ip-adress2,ip-adress3
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx

#Choose reasonable numbers for number of replicas and placement groups.
osd pool default size = 2 # Write an object 2 times
osd pool default min size = 1 # Allow writing 1 copy in a degraded state
osd pool default pg num = 256
osd pool default pgp num = 256

#Choose a reasonable crush leaf type
#0 for a 1-node cluster.
#1 for a multi node cluster in a single rack
#2 for a multi node, multi chassis cluster with multiple hosts in a chassis
#3 for a multi node cluster with hosts across racks, etc.
osd crush chooseleaf type = 1

[client.rgw.ceph-cod1-rgw-n1]
host = ceph-cod1-rgw-n1
keyring = /var/lib/ceph/radosgw/ceph-rgw.ceph-cod1-rgw-n1/keyring
rgw socket path = /var/run/ceph/ceph.radosgw.ceph-cod1-rgw-n1.fastcgi.sock
log file = /var/log/ceph/client.radosgw.ceph-cod1-rgw-n1.log
rgw dns name = ceph-cod1-rgw-n1.**.*****.ru
rgw print continue = false
rgw frontends = «civetweb port=8888»

[client.rgw.ceph-cod2-rgw-n1]
host = ceph-cod2-rgw-n1
keyring = /var/lib/ceph/radosgw/ceph-rgw.ceph-cod2-rgw-n1/keyring
rgw socket path = /var/run/ceph/ceph.radosgw.ceph-cod2-rgw-n1.fastcgi.sock
log file = /var/log/ceph/client.radosgw.ceph-cod2-rgw-n1.log
rgw dns name = ceph-cod2-rgw-n1.**.*****.ru
rgw print continue = false
rgw frontends = «civetweb port=8888»


Также есть пара замечаний:

— если сервис ceph-radosgw.* не стартует, то у меня была проблема с созданием файла логов. Решил это просто создав файл руками и поставив на него маску 0666;
— можно выбирать провайдера API к кластеру между civetweb, fastcgi и apache, вот что глаголит официальная дока:
As of firefly (v0.80), Ceph Object Gateway is running on Civetweb (embedded into the ceph-radosgw daemon) instead of Apache and FastCGI. Using Civetweb simplifies the Ceph Object Gateway installation and configuration.

Если вкратце, то в нашем файле я прописал глобальные переменные, правила репликации и правило «выживания» кластера, а также RGW ноды, допущенные к кластеру. Что касается параметров osd pool default pg num и osd pool default pgp num была найдена интересная заметка:
And for example a count of 64 total PGs. Honestly, protection group calculations is something that still does not convince me totally, I don’t get the reason why it should be left to the Ceph admin to be manually configured, and then often complain that is wrong. Anyway, as long as it cannot be configured automatically, the rule of thumb I’ve find out to get rid of the error is that Ceph seems to be expecting between 20 and 32 PGs per OSD. A value below 20 gives you this error, and a value above 32 gives another error.
So, since in my case there are 9 OSDs, the minimum value would be 9*20=180, and the maximum value 9*32=288. I chose 256 and configured it dinamically.

И вот эта:
PG (Placement Groups) — группа размещения или логическая коллекция объектов в Ceph, которые реплицируются в OSD. Одна группа может сохранять данные на несколько OSD, в зависимости уровня сложности системы. Формула для вычисления групп размещения для Ceph следующая:

Кол-во PG = (кол-во OSD * 100) / кол-во реплик

При этом результат должен быть округлён до ближайшей степени двойки (например, по формуле = 700, после округления = 512).
PGP (Placement Group for Placement purpose) — группы размещения для целей расположения. Количество должно быть равным общему числу групп размещения.

И на всех нодах, где есть ключ, меняем права: sudo chmod +r /etc/ceph/ceph.client.admin.keyring

До того, как OSD устройства вводить в кластер, на OSD нодах необходимо выполнить подготовительные работы:

Разбиваем диск для использования под журнал. Это должен быть SSD (но не обязательно, достаточно просто выделенного диска) и быть разделен не более чем на 4 равные партиции, т.к. партиции должны быть primary:

parted /dev/SSD
mkpart journal-1 1 15G
mkpart journal-2 15 30G
mkpart journal-3 31G 45G
mkpart journal-4 45G 60G


И форматируем в xfs. Меняем права на диски на OSD нодах, которые предназначены для журналов и которые будут управляться Ceph:

chown ceph:ceph /dev/sdb1
chown ceph:ceph /dev/sdb2
chown ceph:ceph /dev/sdb3


И обязательно меняем GUID для этих партиций, чтобы корректно отрабатывал udev и приезжали правильные права на устройства после перезагрузки. Я наступил на эти грабли, когда после перезагрузки OSD нода поднялась, но сервисы были в состоянии failed. Т.к. правильно отработавший udev назначил владельца и группу по умолчанию root:root. Как говорится результат превзошел ожидания… Чтобы этого не случилось делаем так:

sgdisk -t 1:45B0969E-9B03-4F30-B4C6-B4B80CEFF106 /dev/sdb
GUID должен быть именно такой


После с нашей деплой ноды выполняем ceph-deploy disk zap и ceph-deploy osd create. На этом базовая инсталляция кластера закончена и можно посмотреть его состояние командами ceph -w и ceph osd tree.

А как же нам обеспечить отказоустойчивость по ЦОД'ам?

Как оказалось в Ceph есть очень сильный инструмент — работа с crushmap
В этой карте можно вводить несколько уровней абстракции и я сделал до примитивного просто — я ввел понятие rack и в каждый rack разложил ноды по признаку ЦОД'а. С этого момента у меня данные были перераспределены таким образом, что, записанные в один rack имели обязательную реплику в другом rack. Т.к. алгоритм Ceph считает хранение двух реплик в одной «стойке» ненадежным. :) Вот собственно и все, причем, выключение всех нод одного ЦОД'а действительно оставило данные доступными.

[cephadmin@ceph-deploy ceph-cluster]$ ceph osd tree
ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 1.17200 root default
-8 0.58600 rack ceph-cod1
-2 0.19499 host ceph-cod1-osd-n1
0 0.04900 osd.0 up 1.00000 1.00000
1 0.04900 osd.1 up 1.00000 1.00000
2 0.04900 osd.2 up 1.00000 1.00000
3 0.04900 osd.3 up 1.00000 1.00000
-3 0.19499 host ceph-cod1-osd-n2
4 0.04900 osd.4 up 1.00000 1.00000
5 0.04900 osd.5 up 1.00000 1.00000
6 0.04900 osd.6 up 1.00000 1.00000
7 0.04900 osd.7 up 1.00000 1.00000
-4 0.19499 host ceph-cod1-osd-n3
8 0.04900 osd.8 up 1.00000 1.00000
9 0.04900 osd.9 up 1.00000 1.00000
10 0.04900 osd.10 up 1.00000 1.00000
11 0.04900 osd.11 up 1.00000 1.00000
-9 0.58600 rack ceph-cod2
-5 0.19499 host ceph-cod2-osd-n1
12 0.04900 osd.12 up 1.00000 1.00000
13 0.04900 osd.13 up 1.00000 1.00000
14 0.04900 osd.14 up 1.00000 1.00000
15 0.04900 osd.15 up 1.00000 1.00000
-6 0.19499 host ceph-cod2-osd-n2
16 0.04900 osd.16 up 1.00000 1.00000
17 0.04900 osd.17 up 1.00000 1.00000
18 0.04900 osd.18 up 1.00000 1.00000
19 0.04900 osd.19 up 1.00000 1.00000
-7 0.19499 host ceph-cod2-osd-n3
20 0.04900 osd.20 up 1.00000 1.00000
21 0.04900 osd.21 up 1.00000 1.00000
22 0.04900 osd.22 up 1.00000 1.00000
23 0.04900 osd.23 up 1.00000 1.00000


P.S. Что же хочется сказать?

В принципе Ceph оправдал мои ожидания. Как объектного хранилища. Конечно есть особенности его настройки и организация пулов для такого вида хранения не совсем «книжная» — типа вот есть пул с датой, а это пул с метадатой. Об этом я еще постараюсь рассказать.

Также пробовал поиграться с блочным хранением. К сожалению «выбрасывать» блочные устройства через FC Ceph не умеет, или я не нашел как. Что до iSCSI — по мне это не true и happy way. Хотя это работает, даже с MPIO.

Три источника, которые мне показались наиболее полезными:
официальный
неофициальный
шпаргалка
Tags:
Hubs:
Total votes 7: ↑4 and ↓3+1
Comments22

Articles