Строим свое облачное и расширяемое хранилище на базе Ceph
Облачный и расширяемый open-source сервис хранения данных
Поскольку заниматься Ceph я начал недавно, возможны недочеты или же некоторые действия могут показаться лишними или неправильными.
Я действую из той информации, которая доступна и понятна мне. Список материалов будет представлен в конце статьи.
В качестве тестового стенда я взял ESXi сервер, на котором развернул виртуальные машины с необходимым мне количество виртуальных дисков, которые будут имитировать работу физических серверов.
Коротко о демонах
OSD (object storage daemon) — в каждой ноде кластера может быть несколько дисков и на каждый диск нужен отдельный демон OSD.
Демоны Ceph OSD сохраняют данные в виде объектов в плоском пространстве имён, то есть без иерархии в виде каталогов. Объекты обладают идентификаторами, бинарными данными и метаданными в виде ключ-значение, которые использует MDS сохраняя владельца файла, время создания, время модификации и так далее. Идентификатор объекта уникален в пределах кластера.
Демон OSD в составе кластера постоянно сообщает о своём статусе - up или down. Если по ряду причин OSD демон не сообщает о своём состоянии, демон монитора периодически сам проверяет статус OSD демонов и уполномочен обновлять кластерную карту и уведомлять других демонов мониторов о состоянии OSD демонов.
Metadata server (MDS) — вспомогательный демон для обеспечения синхронного состояния файлов в точках монтирования CephFS. В один момент времени работает только один MDS в пределах кластера, а другие находятся в режиме ожидания и кто-то станет активным, если текущий MDS упадёт.
Мониторы Ceph (Ceph Monitors) поддерживают главную копию (master copy) кластерной карты (cluster map), по которой клиенты Ceph могут определить расположение всех мониторов, OSD демонов и серверов Metadata (MDS). До того как клиенты начнут что-либо писать или читать у OSD или MDS, они должны впервую очередь связаться с монитором Ceph.
С текущей кластерной картой и алгоритмом CRUSH, клиенты могут вычислить расположение любого объекта. Эта способность позволяет клиентам напрямую общаться с OSD, что является важным аспектом в архитектуре Ceph и его способности к высокой доступности и производительности.
Главная задача мониторов - поддерживать главную копию кластерной карты. Помимо этого мониторы занимаются аутентификацией и журналированием.
Кластерная карта - это комплексная карта. Она состоит из карты мониторов (monitor map), карты OSD (OSD map), карты плейсмент-группы (placement group map) и карты MDS (metadata server map).
Приступим.
Выполняем установку ОС на сервера и базовую настройку сети, также отключаем IPv6 и SElinux.
Установку системы производим на один диск, загрузчик ставим туда же, никаких RAID не собираем (тоже самое касается аппаратного RAID - только RAID 0 (JBOD)).
- Ceph-node-admin [192.168.2.67]
- Ceph-node-mon [192.168.2.68]
- Ceph-node-00 [192.168.2.69]
- Ceph-node-01 [192.168.2.70]
- Ceph-node-02 [192.168.2.71]
Для удобства будем работать по каноническим именам, если нет своего личного DNS-сервера, то не забываем внести соответствующие настройки в файл /etc/hosts
на каждом сервере.
1 | 192.168.2.67 Ceph-node-admin |
Настройка NTP
Выполняем настройку NTP сервера на каждой ноде.
Это очень важный шаг, поскольку большинство проблем может возникнуть именно из-за некорректной настройки времени.
Установим NTP
1 | sudo yum install ntp ntpdate |
Вносим изменения в конфигурационный файл /etc/ntp.conf
.
1 | server ntp2.stratum2.ru |
Выполним настройку временной зоны, если это не было сделано при установке системы.
Создаем нового пользователя
Поскольку данный пункт я выполнил на стадии установки, то я сразу перейду к следующему шагу.
Изменим файл /etc/sudoers
на каждом сервере и добавим в него следующую строчку, что позволит выполнять sudo
команды без запроса пароля. Либо создадим в папке /etc/sudoers.d/
файл с именем пользователя, в который добавим тоже самое.
1 | echo "{USERNAME} ALL = (root) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/ceph && sudo chmod 0440 /etc/sudoers.d/ceph |
Мы создали пользователя ceph
на каждой ноде, теперь создадим ключ авторизации, без указания кодовой фразы, для беспарольного доступа между серверами.
1 | ssh-keygen |
Теперь скопируем его на все используемые сервера.
1 | ssh-copy-id {ceph user}@{hostname} |
Например:
1 | ssh-copy-id ceph@ceph-node-admin |
Настройка ядра системы
При наличии большого количества OSD, возможно создание огромного количества тредов (threads), особенно в процессе восстановления или же при повторной балансировке. Изменим в Linux значение по умолчанию на необходимое нам.
kernel.pid_max
служит для поддержки большего значения тредов (threads). В теории, максимум это - 4,194,303
.
Внесем изменения в файл /etc/sysctl.conf
, добавив строчку:
1 | kernel.pid_max = 4194303 |
Применяем параметры “на лету”:
1 | sudo sysctl -p |
Настроим правила на файрволле
Для Firewalld
1 | sudo firewall-cmd --zone=public --add-port=6789/tcp --permanent |
Для Iptables
1 | sudo iptables -A INPUT -i {iface} -p tcp -s {ip-address}/{netmask} --dport 6789 -j ACCEPT |
Также установим пакет yum-plugin-priorities
, чтобы менеджер пакетов устанавливал предпочтительные пакеты.
1 | sudo yum install yum-plugin-priorities |
Установка Ceph Storage Cluster с помощью ceph-deploy
Начнем пожалуй с простого. Сделаем кластер с двумя OSD демонами и одним монитором. После достижения статуса active+clean
добавим третий OSD демон в уже работающий кластер, а также резервный MDS и несколько мониторов.
Выполним установку ceph-deploy
Установим необходимые пакеты и репозитории:
1 | sudo yum install -y yum-utils && sudo yum-config-manager --add-repo https://dl.fedoraproject.org/pub/epel/7/x86_64/ && sudo yum install --nogpgcheck -y epel-release && sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 && sudo rm /etc/yum.repos.d/dl.fedoraproject.org* |
Подключим репозиторий Ceph /etc/yum.repos.d/ceph.repo
:
1 | [ceph-noarch] |
Заменим {distro}
на наш дистрибутив, в данном случае el7
.
Заменим {ceph-release}
на стабильную версию Ceph.
На момент написания статьи это infernalis
.
После всех этих действий установим пакет ceph-deploy
:
1 | sudo yum update && sudo yum install ceph-deploy |
Создадим рабочую директорию на административной ноде для генерации конфигурационных файлов и ключей, дальнейшие действия необходимо выполнять находясь в ней.
1 | mkdir ceph-admin |
Очень важно!
Не выполняйте команду ceph-deploy
с sudo
или же от root
, если авторизованы под другим пользователем.
На некоторых дистрибутивах, в частности CentOS, при выполнении команды ceph-deploy
возможны ошибки, для этого измените параметр Defaults requiretty
с помощью sudo visudo
в /etc/sudoers.d/ceph
на Defaults:ceph !requiretty
для того, чтобы ceph-deploy
мог подключаться с помощью пользователя ceph
и выполнять команды с sudo
.
Далее при установке, если на каком-то из пунктов получили неисправимую ошибку, то можно затереть данные и откатиться, используя следующие команды:
1 | ceph-deploy purgedata {ceph-node} [{ceph-node}] |
Для удаления пакетов:
1 | ceph-deploy purge {ceph-node} [{ceph-node}] |
Если выполнялась команда purge
, то необходимо переустановить пакеты Ceph.
Создаем кластер Ceph Storage Cluster
С админской ноды из директории, которую мы создали для хранения конфигурационных файлов, выполняем команду для создания кластера:
1 | ceph-deploy new {initial-monitor-node(s)} |
Например:
1 | ceph-deploy new ceph-node-mon |
После этого в папке появится конфигурационный файл и ключ монитора. Убедитесь в этом.
По умолчанию имя кластера будет ceph. Если вы хотите на одном и том же оборудовании использовать несколько кластеров, то для каждого из них нужно задавать имя, используя ceph-deploy –cluster {cluster-name} new …
Изменим значение по умолчанию для количества реплик в Ceph. По умолчанию значение равно 3
, изменим его на 2
, чтобы Ceph мог достичь статуса Active+Clean
с помощью двух OSD. Добавим следующую строку в директиву [global]
файла ceph.conf
.
1 | osd_pool_default_size = 3 |
Зададим значения для плейсмент групп (Placement Groups) и плейсмент групп для размещения (Placement Groups for Placement) в директиве [global]
. Для небольших кластеров (менее 5 OSDs) рекомендуется 128 плейсмент группы.
1 | osd_pool_default_pg_num = <n> |
- менее 5 OSD - значение
pg_num
иpgp_num
ставим 128; - от 5 до 10 OSD - значение
pg_num
иpgp_num
ставим 512; - от 10 до 50 OSD - значение
pg_num
иpgp_num
ставим 4096; - от 50 OSD и выше параметры
pg_num
иpgp_num
рассчитываем по следующей формуле:
1 | (OSDs * 100) |
osd_pool_default_size
значение, которое мы устанавливали на предыдущем шаге.
Установим максимальное количество плейсмент груп на OSD. По умолчанию это значение равно 300. Несколько пулов могут использовать один и тот же набор правил CRUSH. Когда OSD имеют слишком много плейсмент групп это может сказаться на производительности.
1 | mon_pg_warn_max_per_osd |
Установка типа CRUSH для отказоустойчивости. По умолчанию это значение равно 1. Если мы хотим сделать как минимум для 3-х объектов реплики, то необходимо изменить параметр на 3.
1 | osd_crush_chooseleaf_type = 3 |
- Тип 0 - osd
- Тип 1 - host
- Тип 2 - chassis
- Тип 3 - rack
- Тип 4 - row
- Тип 5 - pdu
- Тип 6 - pod
- Тип 7 - room
- Тип 8 - datacenter
- Тип 9 - region
- Тип 10 - root
Установим max_open_files
для того чтобы задать максимальное значение открытых дескрипторов файлов на уровне ОС:
1 | max_open_files = 131072 |
XATTR параметры используются с файловой системой ext4
для улучшения производительности.
1 | filestore_xattr_use_omap = true |
Как уже и говорилось в начале статьи, рекомендуется правильная настройка времени на сервере.
1 | mon_clock_drift_allowed = .15 |
Установим full_ratio
и near_full_ratio
на приемлемые значения. Полную мощность на 95% и почти заполненную на 85%.
1 | mon_osd_full_ratio = .75 |
Пример ceph.conf
1 | [global] |
Если на сервере имеется и используется больше одного сетевого интерфейса, то добавим public_network
в секцию [global]
конфигурационного файла Ceph. ( Подробнее о сетевой конфигурации )
Установим Ceph:
1 | ceph-deploy install {ceph-node}[{ceph-node} ...] |
Например:
1 | ceph-deploy install ceph-node-admin ceph-node-mon ceph-node-00 ceph-node-01 |
В процессе установки может появиться следующая ошибка:
1 | [ceph-node-admin][WARNIN] warning: /etc/yum.repos.d/ceph.repo created as /etc/yum.repos.d/ceph.repo.rpmnew |
Устраняем проблему командой:
1 | sudo mv /etc/yum.repos.d/ceph.repo /etc/yum.repos.d/ceph-deploy.repo |
Настройка CRUSH карты с SSD кэшированием
В файле конфигурации ceph запрещаем обновлять карту автоматически:
1 | osd_crush_update_on_start = false |
Сохраним текущую карту и переведем её в текстовый формат:
1 | ceph osd getcrushmap -o map.running |
1 | # begin crush map |
Обратите внимание на то, что я создал два root для SSD и HDD, а также два правила ruleset.
Скомпилируем обратно и запустим CRUSH-карту
1 | crushtool -c map.decompile -o map.new |
Добавим первоначальные мониторы и соберем ключи
Для обеспечения высокой доступности необходимо запустить Ceph как минимум с 3-мя мониторами. Ceph использует алгоритм, который требует консенсуса среди большинства мониторов в кворуме.
Подсчет мониторов осуществляется приблизительно следующим образом: 1:1
, 2:3
, 3:4
, 3:5
, 4:6
, etc. Необязательно, но желательно, чтобы количество мониторов в кластере было нечётным числом для улучшения работы алгоритма Paxos при сохранении кворума.
В идеале, разработчики Ceph советуют ноды-мониторы не совмещать с нодами OSD, так как мониторы активно используют fsync()
и это пагубно влияет на производительность OSD.
1 | ceph-deploy mon create-initial |
После выполнения данного процесса в локальной директории ceph-admin
проверим наличие всех ключей:
1 | {cluster-name}.client.admin.keyring |
Например:
1 | [ceph@ceph-node-admin ceph-admin]$ ls -lah |
Добавление OSD
Первоначальный вариант предусматривает OSD в виде директорий на диске, я же буду использовать диски полностью.
Добавление и удаление OSD демонов в кластер может занимать несколько шагов, особенно если используется запись на диск и в журнал.
Для листинга дисков ноды используем следующую команду:
1 | ceph-deploy disk list {node-name [node-name]...} |
Например:
1 | [ceph@ceph-node-admin ceph-admin]$ ceph-deploy disk list ceph-node-00 |
Затираем диски
Определившись с дисками затираем все данные на них (в т.ч. таблицу разделов) и подготовим для использования Ceph.
1 | ceph-deploy disk zap {osd-server-name}:{disk-name} |
Например:
1 | ceph-deploy disk zap ceph-node-00:sdb ceph-node-00:sdc ceph-node-01:sdb ceph-node-01:sdc |
Подготовим диски
Разработчики Ceph рекомендуют использовать файловую систему XFS. ( см. Ceph Docs ), поэтому позаботьтесь о том, чтобы пакет xfsprogs
был установлен на всех нодах кластера.
При подготовке дисков ceph-deploy
автоматически форматирует диски в XFS. Если установка производится на разделы, то отформатировать его можно командой sudo mkfs.xfs -i size=512 /dev/sdX
.
1 | ceph-deploy osd prepare {node-name}:{data-disk}[:{journal-disk}] |
1 | ceph-deploy osd prepare ceph-node-00:sdb ceph-node-00:sdc ceph-node-01:sdb ceph-node-01:sdc |
После создания кластера и установки Ceph пакетов, а также создания ключей, можем выполнить подготовку OSD и развернуть их на OSD нодах. Команда prepare
только подготовит OSD!
Активация OSD
После успешной подготовки дисков активируем OSD. (Обратите внимание, что необходимо указать разделы диска.)
1 | ceph-deploy osd activate {node-name}:{data-disk-partition}[:{journal-disk-partition}] |
Например:
1 | ceph-deploy osd activate ceph-node-00:sdb1:/dev/sdb2 ceph-node-00:sdc1:/dev/sdc2 ceph-node-01:sdb1:/dev/sdb2 ceph-node-01:sdc1:/dev/sdc2 |
Для того чтобы подготовить, развернуть и активировать OSD можно воспользоваться одной командой create
:
1 | ceph-deploy osd create ceph-node-00:sdb1:/dev/sdb2 ceph-node-00:sdc1:/dev/sdc2 ceph-node-01:sdb1:/dev/sdb2 ceph-node-01:sdc1:/dev/sdc2 |
Скопируем ключи и конфигурационный файл на ноды:
1 | ceph-deploy admin {admin-node} {ceph-node} |
Например:
1 | ceph-deploy admin ceph-node-admin ceph-node-mon ceph-node-00 ceph-node-01 |
Убедимся в корректных привилегиях ceph.client.admin.keyring
:
1 | sudo chmod +r /etc/ceph/ceph.client.admin.keyring |
Проверяем состояние:
1 | ceph status |
Получаем статус Ceph:
1 | [ceph@ceph-node-admin ceph-admin]$ ceph status |
При получении предупреждения, например:
1 | [ceph@ceph-node-admin ceph-admin]$ ceph status |
Ищем решение Ceph Troubleshooting.
Создание OSD с SSD кэшированием
1 | ceph osd pool create ssd-cache 128 |
1 | ceph osd pool set ssd-cache crush_ruleset 0 |
1 | ceph osd tier add one ssd-cache |
1 | # Включаем фильтр bloom |
1 | # Сколько байтов должно заполниться прежде чем включится механизм очистки кэша |
К сожалению OSD автоматически в конфигурационный файл не запишутся. Кроме того даже после записи в конфигурацию автоматическое монтирование этих точек тоже не работает.
Чтобы поднять OSD демон при загрузке необходим файл ключ, который лежит на не примонтированном разделе. Поэтому дополняем конфигурационный файл ceph.conf
:
1 | ... |
Кроме этого смотрим на каждом узле где есть osd:
1 | mount | grep ceph |
Добавляем записи в /etc/fstab
для надежности:
1 | /dev/sdb1 /var/lib/ceph/osd/ceph-1 rw,noatime,attr2,inode64,noquota |
Перезаписываем конфигурацию:
1 | ceph-deploy --overwrite-conf admin ceph-node-admin ceph-node-mon ceph-node-00 ceph-node-01 |
На текущем моменте у нас есть кластер с единственным и пока не настроенным пулом.
1 | ceph osd lspools |
Получаем:
1 | 0 rbd, |
RBD можно считать некоторым аналогом жесткого диска на котором необходимо будет нарезать разделы.
Например для Opennebula потребуется три пула: files
, system
и images
.
1 | ceph osd pool create images 64 64 |
Цифра в конце команды - количество PG и PGP для пула. Можно считать, что PG это минимальный реплицирующийся кусок пространства, в которое мы можем запихнуть обьект (файл) или кусок от него. PGP - максимальное количество PG групп для пула.
По мануалам есть формула общего количество PG (указано выше): ((количество OSD)100)/(osd pool default size). То есть 3100/2 = 150. полученное число ещё необходимо округлить вверх до степени двойки - то есть у нас получается 256. Делим это число на количество пулов, округляем вверх до степени 2 - получаем искомую настройку. 256/2 (system,rbd)=128.
Получаем информацию о плейсмент группах:
1 | ceph osd pool get rbd pg_num |
Задаем значения PG вручную:
1 | ceph osd pool set rbd pg_num 512 |
Ceph находится в зависимости от Ceph клиентов и Ceph OSD демонов, будучи осведомленных о кластерной топологии, которые включают в себя 5 отдельных карт, коллективно называемых как “Cluster Map”:
Монитор: Содержит FSID кластера, положение, адреса и порт каждого монитора. Он так же указывает на текущую версию сервера монитора, когда карта была создана и когда в последний раз изменялась. Чтобы просмотреть карту монитора необходимо выполнить команду:
ceph mon dump
OSD: Содержит FSID кластера, когда карта была создана и последние изменения, список пулов, размер репликаций, количество PGs, список OSD и их текущее состояние. Для просмотра OSD карты необходимо выполнить команду:
ceph osd dump
PG: Содержит версию PG, его метки времени, последнию версию OSD, полные соотношения и подробную информацию о каждой группе размещения, такие как PG ID, состояние PG (например
active+clean
) и т.д. Для просмотра PG карты необходимо выполнить команду:ceph pg dump
CRUSH: Содержит список устройств хранения, отказоустойчивую иерархию домена (device,host,rack,row,room,datacenter) и правила для иерархий при хранений данных. Для просмотра структуры CRUSH алгоритма необходимо выполнить команду:
ceph osd tree
MDS: Содержит текущую MDS версию карты, когда карта была создана и когда в последний момент изменялась. Так же содержится pool для хранения метаданных, список серверов метаданных и какие сервера включены и выключены. Для просмотра MDS карты, необходимо выполнить
ceph mds dump
Терминология
Metadata server (MDS) — вспомогательный демон для обеспечения синхронного состояния файлов в точках монтирования CephFS. Работает по схеме активная копия + резервы, причем активная копия в пределах кластера только одна.
Mon (Monitor) — элемент инфраструктуры Ceph, который обеспечивает адресацию данных внутри кластера и хранит информацию о топологии, состоянии и распределении данных внутри хранилища. Клиент, желающий обратиться к блочному устройству rbd или к файлу на примонтированной cephfs, получает от монитора имя и положение rbd header — специального объекта, описывающего положение прочих объектов, относящихся к запрошенной абстракции (блочное устройство или файл) и далее общается со всеми OSD, участвующими в хранении файла.
Объект (Object) — блок данных фиксированного размера (по умолчанию 4 Мб). Вся информация, хранимая в Ceph, квантуется такими блоками. Чтобы избежать путаницы подчеркнем — это не пользовательские объекты из Object Storage, а объекты, используемые для внутреннего представления данных в Ceph.
OSD (object storage daemon) — сущность, которая отвечает за хранение данных, основной строительный элемент кластера Ceph. На одном физическом сервере может размещаться несколько OSD, каждая из которых имеет под собой отдельное физическое хранилище данных.
Карта OSD (OSD Map) — карта, ассоциирующая каждой плейсмент-группе набор из одной Primary OSD и одной или нескольких Replica OSD. Распределение placement groups (PG) по нодам хранилища OSD описывается срезом карты osdmap, в которой указаны положения всех PG и их реплик. Каждое изменение расположения PG в кластере сопровождается выпуском новой карты OSD, которая распространяется среди всех участников.
Плейсмент-группа (Placement Group, PG) — логическая группа, объединяющая множество объектов, предназначенная для упрощения адресации и синхронизации объектов. Каждый объект состоит лишь в одной плейсмент группе. Количество объектов, участвующих в плейсмент-группе, не регламентировано и может меняться.
Primary OSD — OSD, выбранная в качестве Primary для данной плейсмент-группы. Клиентское IO всегда обслуживается той OSD, которая является Primary для плейсмент группы, в которой находится интересующий клиента блок данных (объект). rimary OSD в асинхронном режиме реплицирует все данные на Replica OSD.
RADOS Gateway (RGW) — вспомогательный демон, исполняющий роль прокси для поддерживаемых API объектных хранилищ. Поддерживает географически разнесенные инсталляции (для разных пулов, или, в представлении Swift, регионов) и режим active-backup в пределах одного пула.
Replica OSD (Secondary) — OSD, которая не является Primary для данной плейсмент-группы и используется для репликации. Клиент никогда не общается с ними напрямую.
Фактор репликации (RF) — избыточность хранения данных. Фактор репликации является целым числом и показывает, сколько копий одного и того же объекта хранит кластер.