Переход к хранилищу Ceph нового поколения в OVHcloud с LXD
Вступление
Меня зовут Филип Дорош. Я работаю в OVHcloud с 2017 года инженером DevOps. Сегодня я хочу рассказать вам историю о том, как мы развернули Ceph следующего поколения в OVHcloud. Но сначала несколько слов о Ceph: Ceph — это программно определяемое решение для хранения данных, которое поддерживает дополнительные тома публичного облака OVHcloud, а также наш продукт Cloud Disk Array. Но я не буду утомлять вас маркетинговыми вещами — давайте начнем!
Похоже, это интересная задача ...
Полтора года назад мы начали очень знакомый спринт. Помимо обычных вещей, с которыми нам приходится иметь дело, была одна задача, которая выглядела немного интереснее. Заголовок гласил: « Оцените, можем ли мы запускать новые версии Ceph на нашем текущем программном обеспечении ». Нам нужны были более новые версии Ceph и Bluestore для создания решения Ceph следующего поколения со всеми флеш-хранилищами.
Наше программное решение (которое мы называем устаревшим решением) основано на Docker. Звучит действительно круто, но мы запускаем Docker немного иначе, чем по назначению. Наши контейнеры очень сохраняют состояние. Мы запускаем полноценную систему инициализации внутри контейнера в качестве точки входа в докер. Затем эта система инициализации запускает все необходимое программное обеспечение внутри контейнера, включая Puppet, который мы используем для управления «вещами». Похоже, мы используем контейнеры Docker так же, как контейнеры LXC, не так ли?…
Вскоре выяснилось, что невозможно запускать более новые выпуски Ceph в нашем внутреннем решении, потому что новые версии Ceph используют systemd, а в нашем текущем решении мы вообще не запускаем systemd — ни внутри контейнеров, ни на хозяева, которые их принимают.
Началась охота за решениями. Одна из возможностей заключалась в том, чтобы упаковать Ceph самостоятельно и избавиться от systemd, но это большой объем работы с небольшой добавленной стоимостью. Сообщество Ceph предоставляет проверенные пакеты, которые необходимо использовать, так что этот вариант не рассматривался.
Второй вариант — запустить Ceph с супервизором внутри контейнера Docker. Хотя это звучит как план, даже в документации supervisord четко указано, что supervisord «не предназначен для запуска вместо init как« process id 1 ».». Так что это тоже явно не вариант.
Нам нужен был systemd!
На этом этапе стало ясно, что нам нужно решение, позволяющее запускать systemd как внутри контейнера, так и на хосте. Похоже, настало идеальное время для перехода на совершенно новое решение — решение, которое было разработано для запуска полной ОС внутри контейнера. Поскольку наш Docker использовал бэкэнд LXC, это было естественным выбором для оценки LXC. В нем были все необходимые функции, но с LXC нам пришлось бы самостоятельно кодировать всю автоматизацию, связанную с контейнерами. Но можно ли избежать всей этой дополнительной работы? Оказывается, может…
Поскольку я использовал LXD в своем предыдущем проекте, я знал, что он способен управлять образами, сетями, блочными устройствами и всеми хорошими функциями, которые необходимы для настройки полнофункционального кластера Ceph.
Поэтому я переустановил свои серверы разработчиков с выпуском Ubuntu Server LTS и установил на них LXD.
LXD имеет все необходимое для создания полнофункциональных кластеров Ceph:
- он поддерживает «толстые» контейнеры с отслеживанием состояния,
- он поддерживает systemd внутри контейнера,
- он поддерживает образы контейнеров, поэтому мы можем подготовить индивидуальные изображения и без проблем использовать их,
- передача целых блочных устройств в контейнеры,
- передача обычных каталогов в контейнеры,
- поддержка простого запуска, остановки, перезапуска контейнера,
- REST API, который будет рассмотрен в следующих частях статьи,
- поддержка нескольких сетевых интерфейсов в контейнерах с использованием macvlan.
После нескольких часов ручной работы у меня был кластер Ceph, на котором запущен выпуск Mimic внутри контейнеров LXD. Я набрал ceph health и получил «HEALTH_OK». Приятно! Это сработало отлично.
Как нам это индустриализировать?
Чтобы индустриализировать его и подключить к нашей плоскости управления, нам нужен был модуль Puppet для LXD, чтобы Puppet мог управлять всеми элементами, связанными с контейнером, на хосте. Такого модуля, который предоставлял бы необходимую нам функциональность, не существовало, поэтому нам пришлось его кодировать самостоятельно.
Демон LXD предоставляет удобный REST API, который мы использовали для создания нашего модуля Puppet. Вы можете общаться с API локально через сокет unix и через сеть, если вы настроили его раскрытие. Для использования в модуле было действительно удобно использовать команду запроса lxc, которая работает, отправляя необработанные запросы в LXD через сокет unix. Модуль теперь имеет открытый исходный код на GitHub, поэтому вы можете скачать его и поиграть с ним. Он позволяет настраивать основные параметры LXD, а также создавать контейнеры, профили, пулы хранения и т. Д.
Модуль позволяет создавать, а также управлять состоянием ресурсов. Просто измените свои манифесты, запустите марионеточный агент, и он сделает все остальное.
Модуль LXD Puppet на момент написания этого документа предоставляет следующие определения:
- lxd :: profile
- lxd :: изображение
- lxd :: хранилище
- lxd :: container
Для получения полной справки посетите его страницу GitHub — github.com/ovh/lxd-puppet-module.
Ручная установка VS Автоматическая установка с Puppet
Я покажу вам простой пример того, как создать точно такую же настройку вручную, а затем снова автоматически с помощью Puppet. Для целей этой статьи я создал новый экземпляр Public Cloud с Ubuntu 18.04, один дополнительный диск и уже настроенное мостовое устройство br0. Предположим, есть также DHCP-сервер, прослушивающий интерфейс br0.
Стоит отметить, что обычно вам не нужно создавать собственное изображение, вы можете просто использовать вышестоящие со встроенными командами. Но для целей этой статьи давайте создадим собственный образ, который будет в точности похож на исходный. Чтобы создать такой образ, вам просто нужно ввести несколько команд, чтобы перепаковать исходный образ в Unified Tarball.
root @ ubuntu: ~ # wget https://cloud-images.ubuntu.com/bionic/current/bionic-server-cloudimg-amd64-root.tar.xz
root @ ubuntu: ~ # wget https: // cloud-images .ubuntu.com / bionic / current / bionic-server-cloudimg-amd64-lxd.tar.xz
root @ ubuntu: ~ # mkdir -p ubuntu1804 / rootfs
root @ ubuntu: ~ # tar -xf bionic-server-cloudimg-amd64 -lxd.tar.xz -C ubuntu1804 /
root @ ubuntu: ~ # tar -xf bionic-server-cloudimg-amd64-root.tar.xz -C ubuntu1804 / rootfs /
root @ ubuntu: ~ # cd ubuntu1804 /
root @ ubuntu : ~ / ubuntu1804 # tar -czf ../ubuntu1804.tar.gz *
В конце вы получите образ ubuntu1804.tar.gz, который можно использовать с LXD. Для целей этой статьи я поместил это изображение в каталог, доступный через HTTP, например: example.net/lxd-image/
Ручная настройка
Первым делом давайте установим LXD.
root @ ubuntu: ~ # apt install lxd
Во время установки пакета вы увидите сообщение: «Чтобы пройти начальную конфигурацию LXD, запустите: lxd init», но мы просто сделаем все шаги вручную.
Следующим шагом будет добавление нового пула хранения.
root @ ubuntu: ~ # lxc storage create default dir source = / var / lib / lxd / storage-pools /
default Создание пула хранения по умолчанию
Затем создайте собственный профиль, который будет иметь: переменную окружения http_proxy, установленную на ”, ограничение памяти 2 ГБ, крыши в пуле хранения по умолчанию и eth0, который будет частью моста br0.
root@ubuntu:~# lxc profile create customprofile
Profile customprofile created
root@ubuntu:~# lxc profile device add customprofile root disk path=/ pool=default
Device root added to customprofile
root@ubuntu:~# lxc profile device add customprofile eth0 nic nictype=bridged parent=br0
Device eth0 added to customprofile
root@ubuntu:~# lxc profile set customprofile limits.memory 2GB
Распечатываем весь профиль, чтобы проверить, все ли в порядке:
root@ubuntu:~# lxc profile show customprofile
config:
environment.http_proxy: ""
limits.memory: 2GB
description: ""
devices:
eth0:
nictype: bridged
parent: br0
type: nic
root:
path: /
pool: default
type: disk
name: customprofile
used_by: []
Затем давайте загрузим изображение LXD в формате Unified Tarball:
root@ubuntu:~# wget -O /tmp/ubuntu1804.tar.gz http://example.net/lxd-images/ubuntu1804.tar.gz
И импортируйте его:
root@ubuntu:~# lxc image import /tmp/ubuntu1804.tar.gz --alias ubuntu1804
Image imported with fingerprint: dc6f4c678e68cfd4d166afbaddf5287b65d2327659a6d51264ee05774c819e70
Когда все будет готово, давайте создадим наш первый контейнер:
root@ubuntu:~# lxc init ubuntu1804 container01 --profile customprofile
Creating container01
Теперь давайте добавим несколько каталогов хоста в контейнер:
обратите внимание, что вы должны установить правильного владельца каталога на хосте!
root@ubuntu:~# mkdir /srv/log01
root@ubuntu:~# lxc config device add container01 log disk source=/srv/log01 path=/var/log/
И в качестве последнего штриха добавьте в контейнер раздел хоста:
root@ubuntu:~# lxc config device add container01 bluestore unix-block source=/dev/sdb1 path=/dev/bluestore
/ dev / sdb1 будет доступен внутри контейнера. Мы используем его для передачи устройств для Ceph's Bluestore в контейнер.
Контейнер готов к запуску.
root@ubuntu:~# lxc start container01
Вуаля! Контейнер запущен и работает. Мы настраиваем наши контейнеры так же, как указано выше.
Хотя это было довольно просто настроить вручную. Для массового развертывания вам необходимо автоматизировать вещи. Итак, теперь давайте сделаем это, используя наш модуль LXD Puppet.
Автоматическая установка с Puppet
Чтобы использовать модуль, загрузите его на свой марионеточный сервер и поместите в путь к модулю.
Затем создайте новый класс или добавьте его к одному из существующих классов; все, что вам подходит.
Я подключил его к своему марионеточному серверу. Обратите внимание, что я использую мостовое устройство br0, которое было подготовлено ранее другими модулями, и что изображения LXD размещаются на веб-сервере example.net/lxd-images/ в виде унифицированных тарболов.
Полный пример модуля, использующего модуль LXD Puppet:
class mymodule {
class {':: lxd':}
lxd :: storage {'default':
driver => 'dir',
config => {
'source' => '/ var / lib / lxd / storage-pools / default '
}
}
lxd :: profile {' exampleprofile ': sure
=>' present ',
config => {
' environment.http_proxy '=>' ',
' limits.memory '=>' 2GB ',
},
devices => {
'root' => {
'path' => '/',
'pool' => 'default',
'type' => 'disk',
},
'eth0' => {
'nictype' => 'bridged',
'parent' => 'br0',
'type' => 'nic',
}
}
}
lxd :: image {'ubuntu1804': sure
=> 'present',
repo_url => ' http://example.net/lxd-images/ ',
image_file =>' ubuntu1804.tar.gz ',
image_alias =>' ubuntu1804 ',
}
lxd :: container {' container01 ':
state =>' start ',
config => {
'user.somecustomconfig' => 'Моя потрясающая пользовательская переменная env',
},
profiles => ['exampleprofile'],
image => 'ubuntu1804',
устройства => {
'log' => {
'path' => '/ var / log /',
'source' => '/ srv / log01',
'type' => 'disk',
},
'bluestore' = > {
'путь' => '/ dev / bluestore',
'source' => '/ dev / sdb1',
'type' => 'unix-block',
}
}
}
}
Теперь осталось только запустить марионеточный агент на машине. Он применит желаемое состояние:
root@ubuntu:~# puppet agent -t
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Retrieving locales
Info: Loading facts
Info: Caching catalog for ubuntu.openstacklocal
Info: Applying configuration version '1588767214'
Notice: /Stage[main]/Lxd::Install/Package[lxd]/ensure: created
Notice: /Stage[main]/Lxd::Config/Lxd_config[global_images.auto_update_interval]/ensure: created
Notice: /Stage[main]/Mymodule/Lxd::Storage[default]/Lxd_storage[default]/ensure: created
Notice: /Stage[main]/Mymodule/Lxd::Profile[exampleprofile]/Lxd_profile[exampleprofile]/ensure: created
Notice: /Stage[main]/Mymodule/Lxd::Image[ubuntu1804]/Exec[lxd image present http://example.net/lxd-images//ubuntu1804.tar.gz]/returns: executed successfully
Notice: /Stage[main]/Mymodule/Lxd::Container[container01]/Lxd_container[container01]/ensure: created
Notice: Applied catalog in 37.56 seconds
В конце концов, у вас будет запущен новый контейнер:
root@ubuntu:~# lxc ls
+-------------+---------+--------------------+------+------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+-------------+---------+--------------------+------+------------+-----------+
| container01 | RUNNING | 192.168.0.5 (eth0) | | PERSISTENT | 0 |
+-------------+---------+--------------------+------+------------+-----------+
Поскольку вы можете выставлять пользовательские переменные среды в контейнере, это открывает множество возможностей для настройки новых контейнеров.
Как это хорошо !?
Я призываю всех внести свой вклад в модуль или поставить ему звезду на GitHub, если вы сочтете его полезным.
Планы на будущее
После всестороннего тестирования мы уверены, что все работает, как задумано, и были уверены, что сможем приступить к разработке нового решения с хранилищем Ceph на всех флеш-хранилищах, без жестких дисков.
В будущем мы планируем перенести всю нашу устаревшую инфраструктуру на новое решение на основе LXD. Это будет гигантский проект для миграции: более 50 ПБ размещается на более чем 2000 выделенных серверах, но это уже история для другого раза.