Привет, Хабр! Я — Игорь Шишкин, руководитель R&D-направления облачных сервисов Рег.ру в группе компаний Рунити. В Рунити мы прошли долгий путь от SSL-сертификатов, доменов и виртуального хостинга к VDS и VPS, а затем к собственной IaaS-платформе на базе OpenStack и Ceph. 

Сегодня я расскажу, как мы вообще выбирали SDS (Software Defined Storage), как устроена конфигурация в самом Ceph, приподниму завесу о наших процессах R&D, а также как мы тестируем решения на базе Ceph и как доставляем конфигурацию до production-окружений. Эта статья написана по мотивам моего доклада с HighLoad++ 2024, читайте подробности под катом.

Навигация по тексту:

Что нам было нужно

В процессе эволюции наших внутренних сервисов мы поняли, что работа с объектами стала для нас наиболее типичным и удобным паттерном работы с некоторыми видами данных. S3-протокол здесь оказался логичным выбором — он широко распространен, поддерживается подавляющим большинством приложений и в целом является самым частым вариантом имплементации объектного протокола. От будущего решения мы ожидали:

  • экономическую эффективность (низкий оверхед при хранении с высокой надежностью),

  • максимальный набор фич протокола S3 (включая политики доступа, ACL, Lifecycle policy),

  • динамическую расширяемость — мы же не можем «на берегу» рассчитать и поставить сервера на 10 лет вперед, мы будем их ставить по мере роста сервиса,

  • API для управления, чтобы обеспечить возможность интеграции с другими сервисами,

  • возможность георепликации и выстраивание топологий — так мы бы могли учитывать локальность данных и распределять данные между стойками, дата-центрами, серверами и управлять доменом отказа,

  • (хорошо бы) проверенное временем, чтобы не шашкой наголо бежать в изучение свежих, но, скорее всего, еще сырых решений.

Помимо объектного хранилища, мы также работаем с виртуальными машинами, а значит, нам нужны сетевые блочные устройства. И потребности были схожими:

  • Latency/IOPS/Bandwidth — нужно хотя бы понимание, какую производительность мы можем получить из дисков,

  • динамическая расширяемость — по аналогии с S3, а оборудование мы ставим планомерно,

  • возможность георепликации — было бы неплохо обеспечить возможность клиентам мигрировать в другой дата-центр моментально, да и реплика в другой локации для сохранности данных тоже полезна,

  • «джентльменский набор» фич блочных устройств: sparse-образы, snapshots, diff’s, связанные и развязанные образы, — это было бы полезно в части создания более высокоуровневых сервисов поверх SDS,

  • основной протокол — не iSCSI (но для legacy-решений хорошо, если есть его поддержка) — он тут не виноват, просто удобнее когда есть что-то SDS-ориентированное, а с iSCSI традиционно возникают вопросы по обеспечению связности и failover’а,

  • хорошо бы, если бы это решение было проверено временем — тут аналогично с S3, чтобы не быть первопроходцами.

Почему Ceph?

Если в целом посмотреть на перечень существующих open source решений для организации объектных хранилищ и сетевых блочных устройств, то получится, что большинство умеют либо чисто объектное хранение (например, MinIO или Swift), либо блочные устройства (ну или работу с файлами, в виде которых уже можно было положить вольюмы виртуальных машин). 

И есть Ceph, который умеет всё вместе: и блочные устройства, и объектное хранилище, и даже бонусом есть CephFS. Поэтому с точки зрения доступных решений на рынке очевидным выбор стало то, что наиболее универсально. 

Плюсы Ceph

  • Есть поддержка блочных устройств (RBD), S3 (RGW), POSIX-совместимой ФС (CephFS);

  • В S3 поддерживается солидная часть протокола, включая SNS, Lifecycle policy и др.;

  • Поддержка разных вариантов организации отказоустойчивости — репликация и EC;

  • Возможность создания георепликации и описания собственной топологии размещения железа;

  • Масштабирование — фактически от 1 диска, поддержка классов устройств хранения;

  • Есть набор API разных уровней;

  • Обширное сообщество и документация, разработка спонсируется крупными компаниями;

  • Как ни парадоксально, но Latency/IOPS/Bandwidth — тут речь не про производительность (с этим всё понятно), а скорее, про предсказуемость поведения;

  • Нативная поддержка в QEMU; 

  • Полноценная поддержка образов со всем «джентльменским набором»; 

  • Проверенное временем решение (опыт CERN и DigitalOcean и других вендоров).

Минусы Ceph

Конечно, у Ceph есть и свои недостатки. 

Во-первых, это не самая быстрая SDS «на Диком Западе». Все это прекрасно понимают и никогда не позиционируют Ceph как что-то очень быстрое.

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

В-третьих, стоимость минимальной жизнеспособной конфигурации. С экономической точки зрения Erasure Coding открывает отличные возможности для сокращения оверхеда по фактически используемому месту (хоть и ценой увеличения количества read-операций). Но чтобы обеспечить надежность хранения «по уму» — для действительно эффективных конфигураций вроде EC10+2, EC15+2 — нужно существенное количество оборудования. А если делать совсем «по уму» — то и стоек в дата-центрах, чтобы они стали доменом отказа. 

В-четвертых, конфигурацию ЕС-пулов нельзя менять на лету. Это заставляет сразу выбирать необходимые параметры. В целом существует способ с онлайн-миграцией данных между пулами через Cache Tiering, но он долгий, неудобный и относительно сложный, так что его трудно назвать продакшн-решением. Кроме того, всё равно будет «момент переключения», для подготовки к которому потребуется обеспечить отсутствие операций записи. 

В-пятых, конфигурирование Ceph разрозненно: ceph.conf, ceph config, настройки OSD, настройки S3 — у каждой части конфигурации свое собственное API для применения. Где-то это может быть IPC через CLI, где-то есть REST API, а где-то это просто файлик. 

В-шестых, документация. Хотя и объемная, но не всегда отвечает на все вопросы относительно последствий изменения каких-то параметров или деталей реализации процедуры, из-за чего иногда приходится лезть в код. 

Наконец, поскольку Ceph в основном на C++, не каждый инженер такому рад, потому что детали имплементации многих фич читать порой достаточно сложно и больно неподготовленному инженеру.

Cloud-native подход и конфигурация в Ceph

Итак, давайте немного отвлечемся. Как выглядят процессы в Cloud-native окружениях?

В классическом варианте исполнения мы описываем все конфигурации декларативно, храним их в системе контроля версий, пропускаем через CI для базовой проверки, затем делаем ревью и выкатку в несколько этапов: сначала тестируем dev-окружение, потом идем на stage, и наконец — в production (а потом — следующий production, следующий и т.д.). Этот подход позволяет обкатать изменения прежде, чем они дойдут до production. Таким образом, чем больше раз оно было применено, тем выше вероятность отсутствия проблем на финальных этапах.

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

И чтобы снизить риск человеческого фактора, и упростить процедуру конфигурации кластеров Ceph, мы сделали свой инструмент — cephctl, который позволяет описывать конфигурацию в формате YAML, сравнивать ее между разными кластерами и применять.

В этом месте, по идее, должен встать вопрос: «А почему не взять Rook? Он вроде работает с Kubernetes, позволяет развернуть Ceph…». Тут все весьма просто: прежде всего, Rook — это оператор Ceph для Kubernetes, соответственно, нужно поддерживать еще и Kubernetes, и обладать экспертизой в нем, чтобы эксплуатировать Ceph через Rook. Rook всегда применяет конфигурацию полностью, то есть не пытается построить diff между старой и новой конфигурацией, применить только нужное и в нужные места. 

Ну и, пожалуй, самое важное — Rook’ом очень удобно управлять с помощью его собственных ресурсов, которые, в свою очередь, позволяют управлять ресурсами в Ceph (бакетами, вольюмами и т.д.). И это удобно делать вместе с деплойментом приложений, но такой подход не выявил плюсов для внешнего потребителя.

Специфика S3

S3-протокол базируется на HTTP, и каждый запрос является stateless. Таким образом Object Storage Gateway (или RADOS Gateway — как он раньше назывался) является stateless-proxy. Это, в свою очередь, означает, что мы можем применить немного облачной магии и применять современные методы балансировки, например, ECMP поверх анонсируемого по BGP-адреса. Для этих целей появился anycastd — сервис, позволяющий проверять работоспособность сервиса, анонсировать его по BGP, ну и в, случае отказа, — автоматически снимать анонс. 

Можно даже сходить в конкретный бакет, убедиться, что объект доступен, и только после этого включить сервер в балансировку. Тут наверное возникает вопрос, а почему не ExaBGP или BIRD? Всё просто:

  • BIRD’ом в целом не очень удобно программно управлять: это нужно написать какой-то скрипт или приложение, делать им проверки, а потом ходить в его управляющий сокет и уже командовать, что ему делать,

  • ExaBGP позволяет на Python описать логику формирования маршрутов для анонса, но тогда этот код каждый раз нужно было бы тестировать. И в целом достаточно легко ошибиться, особенно если это логика по какой-то причине будет отличаться между серверами.

А anycastd лишен этих недостатков, позволяя описать декларативно необходимые проверки. Сам код проверок при этом протестирован заранее. Кроме того, anycastd позволяет собирать метрики, в том числе, например, по времени работы проверки — это позволяет нам отслеживать в целом работоспособность сервисов.

Обновления и удобство эксплуатации

Обновление Ceph через штатный оркестратор происходит просто и предсказуемо, через выполнение команды наподобие такой:

новая версия Ceph:

# ceph orch upgrade start--ceph-version v18.2.4

а вот пример для обновления cephctl:

# ceph orch upgrade start--ceph-version v18.2.4

или (если это downgrade или нужна конкретная не последняя версия):

# ceph orch upgrade start--ceph-version v18.2.4-20241031194318

cephctl собирается на базе стандартного образа Ceph, таким образом его обновление не отличается от обновления самого Ceph. Образы тегируются как по версиям, так и по CalVer, что позволяет выбрать нужный образ с нужной версией cephctl и Ceph. А также точно знать, что мы выносим в прод, и при необходимости — быстро откатиться. Кроме этого, сам cephctl позволяет сравнивать конфигурации кластеров и явно показывает, какие параметры и где поменялись. Это дает инженерам возможность еще раз точно удостовериться, что то, что они намереваются применить к кластеру, соответствует тому, что они хотят к нему применить.

Все это укладывается в привычный DevOps-пайплайн, создавая предсказуемую и управляемую систему.

Заключение

Наш путь к SDS и Ceph показал: даже очень сложное решение можно вписать в удобный, гибкий и предсказуемый процесс управления. Ceph дал нам нужную функциональность, а дополнительные инструменты — cephctl и anycastd — сделали процесс конфигурирования и балансировки трафика S3 удобным и прозрачным. 

Сегодня мы продолжаем внедрять новые фичи для нашего публичного облака, поддерживаем уже введенные инструменты и обязательно вернемся к вам с новыми интересными историями. Совсем недавно мы запустили S3 в облачной платформе Рег.ру и скоро расскажем об опыте работы с объектным хранилищем в наших новых статьях. Stay tuned.

Комментарии (2)


  1. ITsheff
    13.12.2024 10:41

    Спасибо за отличную статью. Давно посматриваем на ceph, но боимся)
    Как верно подмечено ceph не самая быстра sds, но тогда такой вопрос, а что сейчас работает быстрее в режиме файловой системы (fs)? чтобы как smb но только на linux. Только NFS?


    1. t3ran
      13.12.2024 10:41

      Вообще нельзя сравнивать SMB/NFS и Ceph напрямую - это крайне разные вещи. Ceph - SDS, а SMB и NFS - протоколы доступа к данным.

      Есть, кстати, официальная реализация NFS поверх Ceph (CephFS либо RadosGW (S3) в качестве бекенда на выбор), аналогичное по архитектуре можно провернуть и с SMB, в целом.

      Ну а про производительность - это весьма сложная тема. Во-первых, потому что в какой-то мере производительность - цена безопасности (safety) и доступности, во-вторых потому что на нее влияет множество факторов, ну и в третьих раз мы говорим про сетевой доступ, то к сложности производительности IO добавляется сложность производительности сети.

      Но если нам не нужно все и мы хотим условно "apt-get install nfs" и с этим запускаться, то в базовом варианте NFS в большинстве случаев (есть исключения) будет быстрее по IO чем CephFS, запущенная на этой же одной ноде с этим же количеством дисков.

      Но одновременно с этим, NFS нельзя будет масштабировать ни по (общей) производительности ни по объему, поставив рядом еще один/два/три/пять серверов. Ну и само-собой отказоусточивость и доступность нужно как-то самостоятельно гарантировать.