Запустив наше облако, мы стали предоставлять сервис хранения, аналогичный S3 Амазона (с совместимым API, чтобы российские заказчики могли использовать стандартные клиенты для работы с S3, изменив только endpoint для подключения). Основная задача сервиса — хранение снапшотов виртуальных машин и различных файлов клиентов. Амазон был взят за образец, куда надо развиваться, и в начале 2014 года стало понятно, что имеющееся файловое хранилище устарело, заказчики требовали современных фичей, недоступных у нас и так нравящихся им у AWS. Но доработка существующего решения светила огромными трудозатратами, поэтому было принято решение построить новое S3-совместимое хранилище с нуля.
Дальше — долгий процесс поиска и сравнений имеющихся решений, потом тесты на производительность и отказоустойчивость решения, написание кипы бумаг, затем — несколько неудачных тестовых миграций, исправления багов в архитектуре, работа над полученными ошибками и итоговая фоновая онлайн-миграция всех данных через два месяца работы.
Это было чертовски долго, но всё прошло спокойно.
Что хотелось
Итак, на момент начала работ задачи были такие:
- Под хранилищем лежала платная файловая система, хорошая на момент раннего развития облака, но уже неоптимальная в текущей стадии роста и развития.
- На носу были большие проекты, требовавшие принципиально других подходов по объёму хранимых данных. Нужно было быстро и гибко масштабироваться. Имеющееся решение было сложно в настройке и требовало немалых человеческих ресурсов для конфигурирования репликации и слежения за здоровьем кластера.
- Старая файловая система не позволяла делать фоновую ребалансировку данных при добавлении новых серверов с дисками, а это порядка 24 Тб сырого пространства на сервер. А если всё же и запускали активную задачу, то мы получали колоссальную просадку в производительности.
- Мониторинг старого хранилища был проблематичным и затратным. Для этого дежурной смене дата-центра раз в день ставилась задача ручной проверки состояния и доступности дисков в файловом хранилище. Все попытки автоматизировать мониторинг приводили к существенной дополнительной нагрузке на ФС. Для нового решения потребовалось написать всего несколько плагинов для существующей системы мониторинга, чтобы полностью видеть состояние кластера, не создавая при этом практически никакой дополнительной нагрузки.
- Нужны были новые плюшки, в частности multipart upload. Надо было делить большие файлы на чанки и поддерживать докачку файлов при внезапном разрыве соединения — это история и про оптимизацию канала для далёкой нефтяной компании, и про доставку данных чемоданами прямо в ЦОД.
- Создание снапшотов также нуждалось в модернизации, их закачка на старое хранилище осуществлялась по 1Gb/s каналу — новая сеть Infiniband должна была дать подходящий канал для быстрого снятия онлайн-снапшотов.
- Хотелось оптимизировать сетевую инфраструктуру, и новое решение позволило доутилизировать существующую Infiniband-фабрику, которую мы используем для виртуальных сетей между ВМ и доставкой LUN с флеш-массивов к гипервизорам.
Как шли работы
В сентябре-октябре 2014-го рассматривали два решения: Swift + Swift3, Ceph + Rados Gateway. Сравнивали совместимость с API Amazon S3, изучали общую информацию о решениях, документированность, roadmap продуктов, оценивали качество саппорта и поддержку opensource-сообщества, сложность интеграции с облаком, простоту обслуживания и масштабирования. API Amazon S3 имеет около 300 методов, наличие которых мы проверяли у наших претендентов. При тестировании первого решения (Swift + Swift3) получили 136 проваленных тестов, Ceph + Rados Gateway провалил около 50.
Ceph, как и ожидалось, победил по причине большего соответствия вышеописанным критериям.
Архитектура кластера ещё не была придумана, знали только, что будет всего три компонента (OSD, MON, RGW), поэтому что и где будет крутиться, оставалось загадкой. В ноябре начали доскональное изучение документации Ceph и написание своей по развёртке. На базе этих документов разработчики смогли понять, как устроен и как работает кластер.
Параллельно шло проектирование архитектуры кластера (тестового и продакшена). Одна схема выше, вот ещё одна:
В декабре мы вышли на первый тестовый стенд. Это была уменьшенная копия боевого кластера, всего по три сервера в каждом дата-центре. Он также был растянут географически (на два дата-центра). Вот схема тестового кластера:
Немногие open-source продукты могут похвастаться такой подробной и качественной документацией, как у Ceph, поэтому никаких сюрпризов и недокументированных багов мы не нашли. Полностью поняв, что такое Ceph и с чем его едят, мы потрогали и родную утилиту деплоя. Она оказалась хороша для кластеров с простой архитектурой и сетевой топологией, которые зачастую разворачиваются обособленно от клиентов. Но нам требовалась более гибкая и удобная утилита деплоя для развёртки непосредственно в облаке. Мы написали программу, которая анализировала конфигурационный файл и собирала по кусочкам кластер либо в последовательном, либо в параллельном режиме. Теперь в конфиге указываем хосты, компоненты на них, а наше ПО определяет количество дата-центров, на которые растянуто решение, тип репликации данных, какую сеть использовать для передачи данных. Особенно это актуально для тестовых стендов облака, которые могут перезаливаться несколько раз за день.
Это фрагмент конфигурационного файла:
CEPH = {
"S3": {
"options": {
"suffix": "f",
"allow-deployment" : False,
"journal-dir": "/CEPH_JOURNAL"
},
"hosts": {
"ru-msk-vol51": [
{ "host": "XX087", "role": "rgw", "id": "a" },
{ "host": "XX088", "role": "rgw", "id": "b" },
{ "host": "XX088", "role": "mon", "id": "a" },
{ "host": "XX089", "role": "mon", "id": "b" },
{ "host": "XX090", "role": "mon", "id": "c" },
{ "host": "XX087", "role":"osd", "id":"0", "disk":"sdb"},
{ "host": "XX087", "role":"osd", "id":"1", "disk":"sdc"},
{ "host": "XX087", "role":"osd", "id":"2", "disk":"sdd"},
{ "host": "XX087", "role":"osd", "id":"3", "disk":"sde"},
{ "host": "XX087", "role":"osd", "id":"4", "disk":"sdf"},
{ "host": "XX087", "role":"osd", "id":"5", "disk":"sdg"},
.....
{ "host": "XX086", "role":"osd", "id":"114", "disk":"sdl"},
{ "host": "XX086", "role":"osd", "id":"115", "disk":"sdm"},
{ "host": "XX086", "role":"osd", "id":"116", "disk":"sdh"},
{ "host": "XX086", "role":"osd", "id":"117", "disk":"sdg"},
{ "host": "XX086", "role":"osd", "id":"118", "disk":"sdk"},
{ "host": "XX086", "role":"osd", "id":"119", "disk":"sdj"}
],
"ru-msk-comp1p": [
{ "host": "YY016", "role": "rgw", "id": "c" },
{ "host": "YY049", "role": "rgw", "id": "d" },
{ "host": "YY056", "role": "mon", "id": "d" },
{ "host": "YY068", "role": "mon", "id": "e" },
{ "host": "YY016", "role":"osd", "id":"48", "disk":"sdb"},
{ "host": "YY016", "role":"osd", "id":"49", "disk":"sdc"},
{ "host": "YY016", "role":"osd", "id":"50", "disk":"sdd"},
{ "host": "YY016", "role":"osd", "id":"51", "disk":"sde"},
{ "host": "YY016", "role":"osd", "id":"52", "disk":"sdf"},
{ "host": "YY016", "role":"osd", "id":"53", "disk":"sdg"},
.....
{ "host": "YY032", "role":"osd", "id":"102", "disk":"sdj"},
{ "host": "YY032", "role":"osd", "id":"103", "disk":"sdk"},
{ "host": "YY032", "role":"osd", "id":"104", "disk":"sdl"},
{ "host": "YY032", "role":"osd", "id":"105", "disk":"sdm"},
{ "host": "YY032", "role":"osd", "id":"106", "disk":"sdn"},
{ "host": "YY032", "role":"osd", "id":"107", "disk":"sdi"}
]
}
}
}
До февраля мы играли на devel-стенде с тестированием ПО для развёртки кластера. Описывали в файлах различные конфигурации кластера и запускали деплой. Как и ожидалось, он взрывался. Это был итеративный процесс усовершенствований и доработок. За время проектирования и внедрения вышла новая версия Ceph, в которой были немного изменены деплой и настройка компонентов кластера, и наш продукт пришлось в очередной раз дописывать.
В феврале началась разработка плагинов для существующей системы мониторинга. Мы ставили цель покрыть все компоненты решения и получить детальную статистику с кластера, что позволило нам быстро находить конкретные точки сбоев и решать мелкие проблемы в считанные минуты. К концу марта был готов код облака для работы с новым S3-кластером, который научил облако работать с API RadosGW. Где-то в это же время мы поняли, что кое-что забыли… А именно — про static website, с помощью которого пользователи могут размещать статические web-сайты у себя в bucket. Оказалось, что RGW не поддерживает этот функционал из коробки, и нам пришлось написать небольшое дополнение к нашему решению, чтобы исправить это упущение.
До конца мая писали ПО для миграции со старого кластера на новый. Утилита последовательно брала файл, записывала в базу данных имя, размер, владельца, права и так далее, файлу присваивался статус «несмигрирован», далее делались попытки миграции. После успешной миграции ему выставлялся статус «смигрирован», при неудачной попытке миграции выставлялся статус «ошибка» и этот файл должен был мигрироваться вторично при следующем запуске скрипта.
В мае же было выполнено перепроектирование и изменение существующей Infiniband-фабрики для кластера CEPH. В фабрику было добавлено десять серверов для Ceph-кластера и выделен отдельный partition key, c помощью которого трафик кластера был отделён от остального трафика в Infiniband-сети. Также в каждый дата-центр было установлено по 2 коммутатора SX1012 c VPI лицензиями, которые выполняют роль proxy между Ethernet и Infiniband сетями кластера, таким образом серверы в разных дата-центрах оказались в одном L2 сегменте. Коммутаторы были объединены в логический кластер и работали как одна железка, балансируя трафик и добавляя решению ещё больше отказоустойчивости. С точки зрения сети, наверное, это самая интересная часть. О том, что именно коллеги делали на физическом уровне, можно чуть подробнее прочитать вот здесь.
В июне разворачивали продуктив. Всё шло штатно и по регламентам инженеров. Серверы под кластер уже были в наличии, пришлось перевести несколько серверов из одного дата-центра в другой. Далее, как и положено, началось тестирование серверов, проверяли память, диски. С дисками было интереснее всего: каждый диск тестировался dd и fio и полностью заполнялся нулями по несколько раз. Около 20% всех дисков сразу уехало обратно к вендору на замену. Все работы были выполнены в течение 1–2 недель.
До июля правили минорные баги и дописывали мелкие вещи. Из серьёзного было два изменения в архитектуре кластера:
- Журналы Ceph перенесены на флеш-диски. Было интенсивное обращение к журналам, и обычные SATA-диски, которые используются в нашем решении, не справлялись с задачей: производительность кластера проседала и постоянно сыпались ошибки slow requests, после чего кластер переходил в состояние WARN. Думали, думали и придумали. Каждый диск под журналы был презентован с двух разных флеш-СХД по Infiniband-сети, на хосте собирались multipath устройства и объединялись в софтовый рэйд. Мы считали, что это отличное отказоустойчивое решение, но на практике при какой-либо проблеме с одной из СХД или IB сети или multipath софтовый рэйд разваливался, и приходилось его собирать руками. Поэтому в конечном итоге было принято решение отказаться от презентованных дисков и перейти на локальные SSD.
- Отказались от Ethernet management сети в пользу Infiniband. Первоначально в кластере использовались две сети, одна для управления — 1Gb/s, вторая для передачи данных между хостами кластера — 56Gb/s. И когда начали тестировать производительность кластера и закачивать файлы в него, то обнаружили, что скорость закачки не превышает 1Gb/s. Долго думали и гадали, в итоге посмотрели загрузку интерфейсов и поняли, в чём наша проблема: RGW обращался к мониторам кластера по сети управления и затем по этой же сети начинал загружать данные. Мы отказались от сети управления на Ethernet и перенесли всё в Infiniband, после чего тесты показали уже совсем другие результаты.
На этой же стадии железячники издевались над кластером, как могли: вынимали диски «на горячую», вырубали серверы и вообще всячески пытались вызвать нарушение целостности данных. Так сказать, определяли границы возможного. Система показала себя очень хорошо, и полностью сломать кластер так и не получилось.
После началась полная миграция в тестовом режиме, в частности, для проверки шейпинга при работе с огромным объёмом данных. Пришлось вспомнить всеми нелюбимый tc, несколько раз прочитывали документацию и наконец-то написали несколько магических правил, которые будут ограничивать скорость. Миграция шла медленно, канал связи дико шейпили, чтобы заказчики не почувствовали проседания производительности на старом кластере. Полная копия была создана только в августе — через две недели после начала. И запустили проверку целостности — сравнивали MD5-суммы файлов. Также имелся отдельный тестовый API endpoint для нового кластера, через который были проверены тестовые аккаунты и доступ к файлам в них (все стандартные действия, которые можно выполнять в S3).
В сентябре мы ещё раз всё проверили и решили переключаться. Написали инструкцию для переключения со старого кластера на новый, перевели старый кластер в режим обслуживания и смогли домигрировать последние гигабайты. Все работы заняли пару часов, сюрпризов не было.
В итоге мы вышли на скорость ребаланса, которую до этого не могли получить: 1 диск в 2 Тб ребалансится за 3–4 часа (без потери скорости для заказчиков, которые постоянно используют файловое хранилище).
Будут вопросы по работе с Сeph в высоконагруженных облачных средах — пишите здесь в комментариях или на почту: SButkeev@croc.ru
Автор: КРОК