Базовая настройка кластера Ceph на простом примере
Будет рассмотрена работа с блочными устройствами (RBD) и распределенной файловой системой (CephFS).
Конфиг кластера:
- Ноды кластера: 2 штуки с CentOS 7
- HDD: 1 для os + 2 для кластера
- Сеть: 172.22.12.0/24
Подготовка
Устанавливаем на все ноды кластера ntp
и импортируем ssh ключи для без парольного доступа пользователю root
:
[root@ceph1 ~]# ssh-keygen [root@ceph1 ~]# ssh-copy-id ceph2
Добавляем необходимые репы на ноду с которой будем запускать ceph-deploy
:
[root@ceph1 ~]# yum install -y yum-utils [root@ceph1 ~]# yum-config-manager --add-repo https://dl.fedoraproject.org/pub/epel/7/x86_64/ [root@ceph1 ~]# yum install --nogpgcheck -y epel-release [root@ceph1 ~]# rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 [root@ceph1 ~]# rm /etc/yum.repos.d/dl.fedoraproject.org*
Создаем репу Ceph релиз jewel для CentOS 7
[root@ceph1 ~]# vim /etc/yum.repos.d/ceph.repo [ceph-noarch] name=Ceph noarch packages baseurl=http://download.ceph.com/rpm-jewel/el7/noarch enabled=1 gpgcheck=1 type=rpm-md gpgkey=https://download.ceph.com/keys/release.asc
Устанавливаем ceph-deploy
[root@ceph1 ~]# yum update [root@ceph1 ~]# yum install ceph-deploy
Создаем директорию для размещегия конфигов кластера при деплое
[root@ceph1 ~]# mkdir mycluster [root@ceph1 ~]# cd mycluster
Создаем непосредственно кластер ceph
[root@ceph1 mycluster]# ceph-deploy new ceph1
Добавляем в файл ceph.conf
в директории mycluster
следующие строки:
public network = 172.22.12.0/24 osd pool default size = 2 osd_crush_update_on_start = false
У вас должно получится что-то вроде этого:
[root@ceph1 mycluster]# cat ceph.conf [global] fsid = 11d81bd3-fd49-4169-b38c-bfaa475ab1b5 mon_initial_members = ceph1 mon_host = 172.22.12.31 auth_cluster_required = cephx auth_service_required = cephx auth_client_required = cephx public network = 172.22.12.0/24 osd pool default size = 2 osd_crush_update_on_start = false
Остановимся на том беспределе, что мы внесли в конфиг. Строка public network = 172.22.12.0/24
указывает кластеру менеджмент сеть. По ней так же будет осуществляться и репликация данных между нодами. В боевых системах стоит разделять эти вещи в разные сети и вешать на разные сетевые интерфейсы. Строка osd pool default size = 2
говорит о том, что мы будем использовать репликацию с коэффициентом 2, по умолчанию ceph использует реплику 3, но так как у нас всего две ноды и реплика будет идти между ними, то выбор очевиден. Последняя запись osd_crush_update_on_start = false
запрещает ceph управлять CRUSH картой кластера. Ее мы будем править руками и импортировать в кластер.
Так как я запускаю ceph-deploy
с ноды кластера, то нужно закоментить репу ceph, чтобы при установке основных пакетов скрипт правильно отработал. Если вы запускаете деплой со своего ноута или PC, тогда этот шаг можно пропустить.
[root@ceph1 mycluster]# mv /etc/yum.repos.d/ceph.repo /etc/yum.repos.d/ceph.repo.old
Инсталим ceph на ноды ceph1 и ceph2 явно указывая версию кластера --release jewel
[root@ceph1 mycluster]# ceph-deploy install --release jewel ceph{1,2}
Если все прошло успешно — инсталим монитор mon
и создаем ключи для ceph. Монитор в нашем случае один, так как для создания кворума нужно нечетное число мониторов, а нод у нас всего две. Но для тестов пойдет. Главное, когда будете ломать кластер не убивайте ноду с монитором или не останавливайте сервис ceph.mon
. Или добавте еще одну ноду без дисков и разместите на ней монитор и на второй ноде с дисками. Итого у вас будет их три, тогда и ломайте.
[root@ceph1 mycluster]# ceph-deploy mon create-initial
Создаем osd
, т.е. включаем наши диски, выделенные для данных на нодах в кластер. В моем случае я использую диски vdb и vdc на обеих нодах. Журналы osd
у меня будут хранится на тех же дисках, ceph автоматом создаст под них партиции. Можно конечно скормить и директории в системе в роли дисков, но для удобства, я рекомендую под osd
отдавать непосредственно сам диск или на крайний случай lvm.
[root@ceph1 mycluster]# ceph-deploy osd create --zap-disk ceph{1,2}:vd{b,c}
Данная команда сотрет все данные с дисков и отформатирует их в xfs.
Копируем конфиг ceph который мы заполняли в самом начале в файлике ceph.conf
на все наши ноды кластера командой:
[root@ceph1 mycluster]# ceph-deploy admin ceph{1,2}
Тепрь займемся созданием CRUSH карты. Вытягиваем текущую карту кластера командой:
[root@ceph1 mycluster]# ceph osd getcrushmap -o map.current
Декомпилируем ее в человеческий формат:
[root@ceph1 mycluster]# crushtool -d map.current -o map.decompile
И приводим ее к такому виду:
[root@ceph1 mycluster]# cat map.decompile # begin crush map tunable choose_local_tries 0 tunable choose_local_fallback_tries 0 tunable choose_total_tries 50 tunable chooseleaf_descend_once 1 tunable chooseleaf_vary_r 1 tunable straw_calc_version 1 # devices device 0 osd.0 device 1 osd.1 device 2 osd.2 device 3 osd.3 # types type 0 osd type 1 host type 2 chassis type 3 rack type 4 row type 5 pdu type 6 pod type 7 room type 8 datacenter type 9 region type 10 root # buckets host ceph1 { id -1 alg straw hash 0 # rjenkins1 item osd.0 weight 0.010 item osd.1 weight 0.010 } host ceph2 { id -2 alg straw hash 0 # rjenkins1 item osd.2 weight 0.010 item osd.3 weight 0.010 } root default { id -3 # do not change unnecessarily # weight 0.000 alg straw hash 0 # rjenkins1 item ceph1 weight 0.020 item ceph2 weight 0.020 } # rules rule replicated_ruleset { ruleset 0 type replicated min_size 1 max_size 10 step take default step chooseleaf firstn 0 type host step emit } # end crush map
Компилируем ее обратно и скармливаем ceph:
[root@ceph1 mycluster]# crushtool -c map.decompile -o map.new [root@ceph1 mycluster]# ceph osd setcrushmap -i map.new
Проверяем состояние кластера командой ceph -s
. Через какое то время он перестроит pg
и вывод будет примерно таким:
[root@ceph1 mycluster]# ceph -s cluster 11d81bd3-fd49-4169-b38c-bfaa475ab1b5 health HEALTH_OK monmap e1: 1 mons at {ceph1=172.22.12.31:6789/0} election epoch 3, quorum 0 ceph1 osdmap e11: 4 osds: 4 up, 4 in flags sortbitwise pgmap v42: 64 pgs, 1 pools, 0 bytes data, 0 objects 131 MB used, 20304 MB / 20435 MB avail 64 active+clean
Чтобы проверить карту osd сделаем так:
[root@ceph1 mycluster]# ceph osd tree ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY -3 0.03998 root default -1 0.01999 host ceph1 0 0.00999 osd.0 up 1.00000 1.00000 1 0.00999 osd.1 up 1.00000 1.00000 -2 0.01999 host ceph2 2 0.00999 osd.2 up 1.00000 1.00000 3 0.00999 osd.3 up 1.00000 1.00000
Здесь мы видим что все osd, они же диски имеют статус UP и относятся нужным нодам, согласно нашей crush карте. На этом создание кластера закончено. Далее будем создавать пулы RBD и CephFS.
Создание CephFS
Для функционирование распределенной файловой системы служат серверы mds
. на них хранятся метаданные. В нашем случае мы создадим два сервера метаданных на обеих нодах в режиме standby_replay (главный и запасной). В случае отказа основного mds его роль подхватит второй. Важное замечание: в нашей тестовой схеме только один сервер мониторов mon
, поэтому важно обеспечить его доступность. В продакшене у вас должно быть три и более монитора. Еще одно замечание: если у вас вдруг будут недоступны сервера mds, то файловые операции просто застопорятся. При восстановлении работы сервера метаданных — система продолжит работу.
Создадим сервера MDS на ceph1
и ceph2
:
[root@ceph1 mycluster]# ceph-deploy mds create ceph{1,2}
Создадим пулы для данных и метаданных в кластере для нашей файловой системы:
[root@ceph1 mycluster]# ceph osd pool create cephfs_data 64 pool 'cephfs_data' created [root@ceph1 mycluster]# ceph osd pool create cephfs_metadata 64 pool 'cephfs_metadata' created
Если посмотреть состояние кластера после создание пулов, то будем иметь следующую картину:
[root@ceph1 mycluster]# ceph -s cluster 11d81bd3-fd49-4169-b38c-bfaa475ab1b5 health HEALTH_ERR 64 pgs are stuck inactive for more than 300 seconds 17 pgs peering 64 pgs stuck inactive monmap e1: 1 mons at {ceph1=172.22.12.31:6789/0} election epoch 3, quorum 0 ceph1 osdmap e15: 4 osds: 4 up, 4 in flags sortbitwise pgmap v119: 192 pgs, 3 pools, 0 bytes data, 0 objects 133 MB used, 20302 MB / 20435 MB avail 128 active+clean 47 creating+activating 17 creating+peering
В данный момент кластер занят ребалансировкой и созданием pg. Через несколько секунд снова проверяем статус и видим что все ок:
[root@ceph1 mycluster]# ceph -s cluster 11d81bd3-fd49-4169-b38c-bfaa475ab1b5 health HEALTH_OK
Установим пулам cephfs_data и cephfs_metadata режим реплики size 2
, обеспечим работу кластера в режиме деградации пока доступна хотя бы одна копия данных в пуле min_size 1
и укажем правило репликации pg crush_ruleset 0
согласно нашей crush карте, что значит реплицировать пул между хостами кластера.
[root@ceph1 mycluster]# ceph osd pool set cephfs_data size 2 set pool 1 size to 2 [root@ceph1 mycluster]# ceph osd pool set cephfs_data min_size 1 set pool 1 min_size to 1 [root@ceph1 mycluster]# ceph osd pool set cephfs_data crush_ruleset 0 set pool 1 crush_ruleset to 0 [root@ceph1 mycluster]# ceph osd pool set cephfs_metadata size 2 set pool 2 size to 2 [root@ceph1 mycluster]# ceph osd pool set cephfs_metadata min_size 1 set pool 2 min_size to 1 [root@ceph1 mycluster]# ceph osd pool set cephfs_metadata crush_ruleset 0 set pool 2 crush_ruleset to 0
Создаем нашу фаловую систему:
root@ceph1 mycluster]# ceph fs new cephfs cephfs_metadata cephfs_data
Посмотрим на состояние кластера и увидим, что файловая система создалась
[root@ceph1 mycluster]# ceph -s cluster 11d81bd3-fd49-4169-b38c-bfaa475ab1b5 health HEALTH_OK monmap e1: 1 mons at {ceph1=172.22.12.31:6789/0} election epoch 3, quorum 0 ceph1 fsmap e6: 1/1/1 up {0=ceph2=up:active}, 1 up:standby osdmap e22: 4 osds: 4 up, 4 in flags sortbitwise pgmap v179: 192 pgs, 3 pools, 2068 bytes data, 20 objects 135 MB used, 20300 MB / 20435 MB avail 192 active+clean
Проверим статус наших серверов метаданных:
[root@ceph1 mycluster]# ceph mds stat e6: 1/1/1 up {0=ceph2=up:active}, 1 up:standby
Нам сообщают, что в данный момент активен mds на ноде ceph2 и второй (ceph1) в режиме standby. Если погасить сервис mds на ноде ceph2, то активным станет mds на ceph1.
[root@ceph1 mycluster]# ceph mds stat e11: 1/1/1 up {0=ceph1=up:active}
Перейдем к созданию пользователя для аунтификации при монтировании файловой системы на клиентах, так как делать это от админа не очень хорошо в целях безопасности. Дадим пользователю cephfs права на чтение из mon и mds и полные права на пулы cephfs_data
и cephfs_metadata
[root@ceph1 mycluster]# ceph auth get-or-create client.cephfs mon 'allow r' mds 'allow r' osd 'allow rwx pool=cephfs_metadata,allow rwx pool=cephfs_data' -o /etc/ceph/client.cephfs.keyring
У вас должен был создаться новый пользователь в кластере:
[root@ceph1 mycluster]# ceph auth list client.cephfs key: AQBdX0NXobyACBAArLIkcDRrAHYEDc3izToMnA== caps: [mds] allow r caps: [mon] allow r caps: [osd] allow rwx pool=cephfs_metadata,allow rwx pool=cephfs_data
Монтирование файловой системы на клиенте
Монтировать будем через модуль ядра. Для этого нам нужно установить недостающие пакеты на клиенте:
root@client ~ # yum update root@client ~ # yum install ceph-fs-common
Создадим файл ключа пользователя cephfs для монтирования FS на клиенте и директорию для монтирования /mnt/cephfs
:
root@client ~ # mkdir -p /etc/ceph root@client ~ # echo "AQBdX0NXobyACBAArLIkcDRrAHYEDc3izToMnA==" > /etc/ceph/cephfskey root@client ~ # sudo mkdir /mnt/cephfs
В отличии от glusterfs в cephfs можно монтировать сразу директории из корневой fs. В нашем случае у нас их пока нет, поэтому понтируем корень. Команда имеет следующий формат mount -t ceph [mon_ip_or_fqdn]:[mon_port]:/ /mnt/cephfs/ -o name=cephfs,secretfile=[path_secretfile]. Порт монитора можно опустить, так как он стандартный:
mount -t ceph 172.22.12.31:/ /mnt/cephfs/ -o name=cephfs,secretfile=/etc/ceph/cephfskey
Смотрим вывод dh -h и видим, что cephfs примонтирована и ее текущий размер 20GB. Это полезный объем данных, сырой объем в кластере 20GB (4 osd по 10GB реплика 2):
Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 6.7G 1.4G 5.4G 21% / devtmpfs 235M 0 235M 0% /dev tmpfs 245M 0 245M 0% /dev/shm tmpfs 245M 4.4M 241M 2% /run tmpfs 245M 0 245M 0% /sys/fs/cgroup /dev/vda1 497M 165M 332M 34% /boot tmpfs 49M 0 49M 0% /run/user/0 172.22.12.31:/ 20G 132M 20G 1% /mnt/cephfs
Собственно можно пользоваться и проводить тесты.
Работа с блочными устройствами RBD и взаимодействие с libvirt
При создании кластера ceph по умолчанию создается пул rbd. С ним мы и будем работать. Вы можете создать отдельный пул или несколько для работы с libvirt, все зависит от ваших нужд. К примеру пул для gold image и пул для vm image. В пулах мы будем размещать блочные устройства и отдавать виртуалкам в виде дисков и получить кучу плюсов. Помимо надёжности и производительности RBD также предоставляет функциональность корпоративного уровня подобную полным и инкрементальным снимкам, динамичному выделению (thin provisioning), клонированию копированием при записи (copy on write), динамическое изменение размеров и тому подобное. RBD также поддерживает кэширование в памяти.
Вернемся на любую из нод кластера и посмотрим статистику занятого места по пулам:
[root@ceph1 mycluster]# ceph df GLOBAL: SIZE AVAIL RAW USED %RAW USED 20435M 20300M 135M 0.66 POOLS: NAME ID USED %USED MAX AVAIL OBJECTS rbd 0 0 0 10150M 0 cephfs_data 1 0 0 10150M 0 cephfs_metadata 2 2378 0 10150M 20
Мы видим три пула: rbd, cephfs_data, cephfs_metadata которые имеют одинаковую емкость. Это обусловлено тем, что каждому пулу изначально доступно все место в кластере. Расширяя объем кластера — вы автоматически расширяете все пулы. Хорошо это или плохо — решать вам.
Теперь перейдем к созданию пользователя libvirt в ceph. Тут все аналогично как и с cephfs, только мы не указываем права на mds, так как для работы блочных устройств сервер метаданных не нужен. Даем права на чтение из mon и полные права на пул rbd. прошу обратить внимание, что пулы которые мы создали для cephfs не будут доступны пользователю libvirt. Это хорошо и правильно.
root@ceph1 mycluster]# ceph auth get-or-create client.libvirt mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool=rbd' [client.libvirt] key = AQCsY0NXYEbzFhAAS/JicyexWrrcnVm0XUFEeA==
Создадим блочное устройство в пуле rbd размером 10G:
[root@ceph1 mycluster]# rbd create rbd/vm-test.img --size 10G [root@ceph1 mycluster]# rbd ls -p rbd vm-test.img
Если посмотреть информацию по vm-test.img
то увидим, что оно не занимает место на диске. Это дополнительная плюшка ceph, которая и реализует thin provisioning
[root@ceph1 mycluster]# rbd info vm-test.img -p rbd rbd image 'vm-test.img': size 10240 MB in 2560 objects order 22 (4096 kB objects) block_name_prefix: rbd_data.10502ae8944a format: 2 features: layering, exclusive-lock, object-map, fast-diff, deep-flatten flags: [root@ceph1 mycluster]# rbd du vm-test.img -p rbd NAME PROVISIONED USED vm-test.img 10240M 0
Идем на гипервизор и создаем файл секрета для доступа libvirt к ceph rbd:
cat > secret.xml <<EOF <secret ephemeral='no' private='no'> <usage type='ceph'> <name>client.libvirt secret</name> </usage> </secret> EOF
Импортируем файл через virsh
:
[root@ceph1 mycluster]# virsh secret-define --file secret.xml Secret 36607386-41fe-4730-9c13-624081e5d21a created
Устанавливаем ключ пользователя libvirt из ceph который мы получили выше:
[root@ceph1 mycluster]# sudo virsh secret-set-value --secret 36607386-41fe-4730-9c13-624081e5d21a --base64 AQCsY0NXYEbzFhAAS/JicyexWrrcnVm0XUFEeA== Secret value set [root@ceph1 mycluster]# sudo virsh secret-list UUID Usage -------------------------------------------------------------------------------- 36607386-41fe-4730-9c13-624081e5d21a ceph client.libvirt secret
Правим конфиг виртуалки через virsh edit vm-test
, которой хотим отдать блочное устройство из ceph
<disk type='network' device='disk'> <source protocol='rbd' name='rbd/vm-test.img'> <host name='172.22.12.31' port='6789'/> </source> <auth username='libvirt'> <secret type='ceph' uuid='36607386-41fe-4730-9c13-624081e5d21a'/≶ </auth> <target dev='vda' bus='virtio'/> </disk>
Небольшое пояснение: <source protocol='rbd' name='rbd/vm-test.img'>
сообщает, что мы будем использовать блочное устройство с именем vm-test.img которое находится в пуле rbd. Пул и rbd диск должен существовать (и то и другое было создано выше). Указываем наш монитор <host name='172.22.12.31' port='6789'/>
. Их должно быть столько же, сколько у нас мониторов. Реализуется просто добавлением аналогичных строк в секции <source></source>
. Тут мы передаем указатель на секрет, созданный выше <secret type='ceph' uuid='36607386-41fe-4730-9c13-624081e5d21a'/>
.
Если у вас гипервизор находится на ноде, которая не входит в кластер ceph, то придется установить пакеты ceph для обеспечения работы. Нормальной практикой считается совмещение ролей compute и storage на одной ноде с целью уплотнения потребления ресурсов, энергии и места в стойке.
На этом все, спасибо за внимание и всем кто дошел до конца статьи. Понадобилось много терпения чтобы дописать ее до конца.