vitastor/README-ru.md

46 KiB
Raw Permalink Blame History

Vitastor

Read English version

Идея

Я всего лишь хочу сделать качественную блочную SDS!

Vitastor - распределённая блочная SDS, прямой аналог Ceph RBD и внутренних СХД популярных облачных провайдеров. Однако, в отличие от них, Vitastor быстрый и при этом простой. Только пока маленький :-).

Архитектурная схожесть с Ceph означает заложенную на уровне алгоритмов записи строгую консистентность, репликацию через первичный OSD, симметричную кластеризацию без единой точки отказа и автоматическое распределение данных по любому числу дисков любого размера с настраиваемыми схемами избыточности - репликацией или с произвольными кодами коррекции ошибок.

Возможности

Vitastor на данный момент находится в статусе предварительного выпуска, расширенные возможности пока отсутствуют, а в будущих версиях вероятны "ломающие" изменения.

Однако следующее уже реализовано:

0.5.x (стабильная версия):

  • Базовая часть - надёжное кластерное блочное хранилище без единой точки отказа
  • Производительность ;-D
  • Несколько схем отказоустойчивости: репликация, XOR n+1 (1 диск чётности), коды коррекции ошибок Рида-Соломона на основе библиотеки jerasure с любым числом дисков данных и чётности в группе
  • Конфигурация через простые человекочитаемые JSON-структуры в etcd
  • Автоматическое распределение данных по OSD, с поддержкой:
    • Математической оптимизации для лучшей равномерности распределения и минимизации перемещений данных
    • Нескольких пулов с разными схемами избыточности
    • Дерева распределения, выбора OSD по тегам / классам устройств (только SSD, только HDD) и по поддереву
    • Настраиваемых доменов отказа (диск/сервер/стойка и т.п.)
  • Восстановление деградированных блоков
  • Ребаланс, то есть перемещение данных между OSD (дисками)
  • Поддержка "ленивого" fsync (fsync не на каждую операцию)
  • Сбор статистики ввода/вывода в etcd
  • Клиентская библиотека режима пользователя для ввода/вывода
  • Драйвер диска для QEMU (собирается вне дерева исходников QEMU)
  • Драйвер диска для утилиты тестирования производительности fio (также собирается вне дерева исходников fio)
  • NBD-прокси для монтирования образов ядром ("блочное устройство в режиме пользователя")
  • Утилита удаления образов/инодов (vitastor-rm)
  • Пакеты для Debian и CentOS

0.6.x (master-ветка):

  • Статистика операций ввода/вывода и занятого места в разрезе инодов
  • Именование инодов через хранение их метаданных в etcd
  • Снапшоты и copy-on-write клоны
  • Сглаживание производительности случайной записи в SSD+HDD конфигурациях

Планы развития

  • Более корректные скрипты разметки дисков и автоматического запуска OSD
  • Другие инструменты администрирования
  • Плагины для OpenStack, Kubernetes, OpenNebula, Proxmox и других облачных систем
  • iSCSI-прокси
  • Более быстрое переключение при отказах
  • Фоновая проверка целостности без контрольных сумм (сверка реплик)
  • Контрольные суммы
  • Поддержка SSD-кэширования (tiered storage)
  • Поддержка RDMA и NVDIMM
  • Web-интерфейс
  • Возможно, сжатие
  • Возможно, поддержка кэширования данных через системный page cache

Архитектура

Так же, как и в Ceph, в Vitastor:

  • Есть пулы (pools), PG, OSD, мониторы, домены отказа, дерево распределения (аналог crush-дерева).
  • Образы делятся на блоки фиксированного размера (объекты), и эти объекты распределяются по OSD.
  • У OSD есть журнал и метаданные и они тоже могут размещаться на отдельных быстрых дисках.
  • Все операции записи тоже транзакционны. В Vitastor, правда, есть режим отложенного/ленивого fsync (коммита), в котором fsync не вызывается на каждую операцию записи, что делает его более пригодным для использования на "плохих" (десктопных) SSD. Однако все операции записи в любом случае атомарны.
  • Клиентская библиотека тоже старается ждать восстановления после любого отказа кластера, то есть, вы тоже можете перезагрузить хоть весь кластер разом, и клиенты только на время зависнут, но не отключатся.

Некоторые базовые термины для тех, кто не знаком с Ceph:

  • OSD (Object Storage Daemon) - процесс, который хранит данные на одном диске и обрабатывает запросы чтения/записи от клиентов.
  • Пул (Pool) - контейнер для данных, имеющих одну и ту же схему избыточности и правила распределения по OSD.
  • PG (Placement Group) - группа объектов, хранимых на одном и том же наборе реплик (OSD). Несколько PG могут храниться на одном и том же наборе реплик, но объекты одной PG в норме не хранятся на разных наборах OSD.
  • Монитор - демон, хранящий состояние кластера.
  • Домен отказа (Failure Domain) - группа OSD, которым вы разрешаете "упасть" всем вместе. Иными словами, это группа OSD, в которые СХД не помещает разные копии одного и того же блока данных. Например, если домен отказа - сервер, то на двух дисках одного сервера никогда не окажется 2 и более копий одного и того же блока данных, а значит, даже если в этом сервере откажут все диски, это будет равносильно потере только 1 копии любого блока данных.
  • Дерево распределения (Placement Tree / CRUSH Tree) - иерархическая группировка OSD в узлы, которые далее можно использовать как домены отказа. То есть, диск (OSD) входит в сервер, сервер входит в стойку, стойка входит в ряд, ряд в датацентр и т.п.

Чем Vitastor отличается от Ceph:

  • Vitastor в первую очередь сфокусирован на SSD. Также Vitastor, вероятно, должен неплохо работать с комбинацией SSD и HDD через bcache, а в будущем, возможно, будут добавлены и нативные способы оптимизации под SSD+HDD. Однако хранилище на основе одних лишь жёстких дисков, вообще без SSD, не в приоритете, поэтому оптимизации под этот кейс могут вообще не состояться.
  • OSD Vitastor однопоточный и всегда таким останется, так как это самый оптимальный способ работы. Если вам не хватает 1 ядра на 1 диск, просто делите диск на разделы и запускайте на нём несколько OSD. Но, скорее всего, вам хватит и 1 ядра - Vitastor не так прожорлив к ресурсам CPU, как Ceph.
  • Журнал и метаданные всегда размещаются в памяти, благодаря чему никогда не тратится лишнее время на чтение метаданных с диска. Размер метаданных линейно зависит от размера диска и блока данных, который задаётся в конфигурации кластера и по умолчанию составляет 128 КБ. С блоком 128 КБ метаданные занимают примерно 512 МБ памяти на 1 ТБ дискового пространства (и это всё равно меньше, чем нужно Ceph-у). Журнал вообще не должен быть большим, например, тесты производительности в данном документе проводились с журналом размером всего 16 МБ. Большой журнал, вероятно, даже вреден, т.к. "грязные" записи (записи, не сброшенные из журнала) тоже занимают память и могут немного замедлять работу.
  • В Vitastor нет внутреннего copy-on-write. Я считаю, что реализация CoW-хранилища гораздо сложнее, поэтому сложнее добиться устойчиво хороших результатов. Возможно, в один прекрасный день я придумаю красивый алгоритм для CoW-хранилища, но пока нет - внутреннего CoW в Vitastor не будет. Всё это не относится к "внешнему" CoW (снапшотам и клонам).
  • Базовый слой Vitastor - простое блочное хранилище с блоками фиксированного размера, а не сложное объектное хранилище с расширенными возможностями, как в Ceph (RADOS).
  • В Vitastor есть режим "ленивых fsync", в котором OSD группирует запросы записи перед сбросом их на диск, что позволяет получить лучшую производительность с дешёвыми настольными SSD без конденсаторов ("Advanced Power Loss Protection" / "Capacitor-Based Power Loss Protection"). Тем не менее, такой режим всё равно медленнее использования нормальных серверных SSD и мгновенного fsync, так как приводит к дополнительным операциям передачи данных по сети, поэтому рекомендуется всё-таки использовать хорошие серверные диски, тем более, стоят они почти так же, как десктопные.
  • PG эфемерны. Это означает, что они не хранятся на дисках и существуют только в памяти работающих OSD.
  • Процессы восстановления оперируют отдельными объектами, а не целыми PG.
  • PGLOG-ов нет.
  • "Мониторы" не хранят данные. Конфигурация и состояние кластера хранятся в etcd в простых человекочитаемых JSON-структурах. Мониторы Vitastor только следят за состоянием кластера и управляют перемещением данных. В этом смысле монитор Vitastor не является критичным компонентом системы и больше похож на Ceph-овский менеджер (MGR). Монитор Vitastor написан на node.js.
  • Распределение PG не основано на консистентных хешах. Вместо этого все маппинги PG хранятся прямо в etcd (ибо нет никакой проблемы сохранить несколько сотен-тысяч записей в памяти, а не считать каждый раз хеши). Перераспределение PG по OSD выполняется через математическую оптимизацию, а конкретно, сведение задачи к ЛП (задаче линейного программирования) и решение оной с помощью утилиты lp_solve. Такой подход позволяет обычно выравнивать распределение места почти идеально - равномерность обычно составляет 96-99%, в отличие от Ceph, где на голом CRUSH-е без балансировщика обычно выходит 80-90%. Также это позволяет минимизировать объём перемещения данных и случайность связей между OSD, а также менять распределение вручную, не боясь сломать логику перебалансировки. В таком подходе есть и потенциальный недостаток - есть предположение, что в очень большом кластере он может сломаться - однако вплоть до нескольких сотен OSD подход точно работает нормально. Ну и, собственно, при необходимости легко реализовать и консистентные хеши.
  • Отдельный слой, подобный слою "CRUSH-правил", отсутствует. Вы настраиваете схемы отказоустойчивости, домены отказа и правила выбора OSD напрямую в конфигурации пулов.

Понимание сути производительности систем хранения

Вкратце: для быстрой хранилки задержки важнее, чем пиковые iops-ы.

Лучшая возможная задержка достигается при тестировании в 1 поток с глубиной очереди 1, что приблизительно означает минимально нагруженное состояние кластера. В данном случае IOPS = 1/задержка. Ни числом серверов, ни дисков, ни серверных процессов/потоков задержка не масштабируется... Она зависит только от того, насколько быстро один серверный процесс (и клиент) обрабатывают одну операцию.

Почему задержки важны? Потому, что некоторые приложения не могут использовать глубину очереди больше 1, ибо их задача не параллелизуется. Важный пример - это все СУБД с поддержкой консистентности (ACID), потому что все они обеспечивают её через журналирование, а журналы пишутся последовательно и с fsync() после каждой операции.

fsync, кстати - это ещё одна очень важная вещь, про которую почти всегда забывают в тестах. Смысл в том, что все современные диски имеют кэши/буферы записи и не гарантируют, что данные реально физически записываются на носитель до того, как вы делаете fsync(), который транслируется в команду сброса кэша операционной системой.

Дешёвые SSD для настольных ПК и ноутбуков очень быстрые без fsync - NVMe диски, например, могут обработать порядка 80000 операций записи в секунду с глубиной очереди 1 без fsync. Однако с fsync, когда они реально вынуждены писать каждый блок данных во флеш-память, они выжимают лишь 1000-2000 операций записи в секунду (число практически постоянное для всех моделей SSD).

Серверные SSD часто имеют суперконденсаторы, работающие как встроенный источник бесперебойного питания и дающие дискам успеть сбросить их DRAM-кэш в постоянную флеш-память при отключении питания. Благодаря этому диски с чистой совестью игнорируют fsync, так как точно знают, что данные из кэша доедут до постоянной памяти.

Все наиболее известные программные СХД, например, Ceph и внутренние СХД, используемые такими облачными провайдерами, как Amazon, Google, Яндекс, медленные в смысле задержки. В лучшем случае они дают задержки от 0.3мс на чтение и 0.6мс на запись 4 КБ блоками даже при условии использования наилучшего возможного железа.

И это в эпоху SSD, когда вы можете пойти на рынок и купить там SSD, задержка которого на чтение будет 0.1мс, а на запись - 0.04мс, за 100$ или даже дешевле.

Когда мне нужно быстро протестировать производительность дисковой подсистемы, я использую следующие 6 команд, с небольшими вариациями:

  • Линейная запись: fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4M -iodepth=32 -rw=write -runtime=60 -filename=/dev/sdX
  • Линейное чтение: fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4M -iodepth=32 -rw=read -runtime=60 -filename=/dev/sdX
  • Запись в 1 поток (T1Q1): fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=1 -fsync=1 -rw=randwrite -runtime=60 -filename=/dev/sdX
  • Чтение в 1 поток (T1Q1): fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=1 -rw=randread -runtime=60 -filename=/dev/sdX
  • Параллельная запись (numjobs используется, когда 1 ядро CPU не может насытить диск): fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=128 [-numjobs=4 -group_reporting] -rw=randwrite -runtime=60 -filename=/dev/sdX
  • Параллельное чтение (numjobs - аналогично): fio -ioengine=libaio -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=128 [-numjobs=4 -group_reporting] -rw=randread -runtime=60 -filename=/dev/sdX

Теоретическая максимальная производительность Vitastor

При использовании репликации:

  • Задержка чтения в 1 поток (T1Q1): 1 сетевой RTT + 1 чтение с диска.
  • Запись+fsync в 1 поток:
    • С мгновенным сбросом: 2 RTT + 1 запись.
    • С отложенным ("ленивым") сбросом: 4 RTT + 1 запись + 1 fsync.
  • Параллельное чтение: сумма IOPS всех дисков либо производительность сети, если в сеть упрётся раньше.
  • Параллельная запись: сумма IOPS всех дисков / число реплик / WA либо производительность сети, если в сеть упрётся раньше.

При использовании кодов коррекции ошибок (EC):

  • Задержка чтения в 1 поток (T1Q1): 1.5 RTT + 1 чтение.
  • Запись+fsync в 1 поток:
    • С мгновенным сбросом: 3.5 RTT + 1 чтение + 2 записи.
    • С отложенным ("ленивым") сбросом: 5.5 RTT + 1 чтение + 2 записи + 2 fsync.
  • Под 0.5 на самом деле подразумевается (k-1)/k, где k - число дисков данных, что означает, что дополнительное обращение по сети не нужно, когда операция чтения обслуживается локально.
  • Параллельное чтение: сумма IOPS всех дисков либо производительность сети, если в сеть упрётся раньше.
  • Параллельная запись: сумма IOPS всех дисков / общее число дисков данных и чётности / WA либо производительность сети, если в сеть упрётся раньше. Примечание: IOPS дисков в данном случае надо брать в смешанном режиме чтения/записи в пропорции, аналогичной формулам выше.

WA (мультипликатор записи) для 4 КБ блоков в Vitastor обычно составляет 3-5:

  1. Запись метаданных в журнал
  2. Запись блока данных в журнал
  3. Запись метаданных в БД
  4. Ещё одна запись метаданных в журнал при использовании EC
  5. Запись блока данных на диск данных

Если вы найдёте SSD, хорошо работающий с 512-байтными блоками данных (Optane?), то 1, 3 и 4 можно снизить до 512 байт (1/8 от размера данных) и получить WA всего 2.375.

Кроме того, WA снижается при использовании отложенного/ленивого сброса при параллельной нагрузке, т.к. блоки журнала записываются на диск только когда они заполняются или явным образом запрашивается fsync.

Пример сравнения с Ceph

Железо - 4 сервера, в каждом:

  • 6x SATA SSD Intel D3-4510 3.84 TB
  • 2x Xeon Gold 6242 (16 cores @ 2.8 GHz)
  • 384 GB RAM
  • 1x 25 GbE сетевая карта (Mellanox ConnectX-4 LX), подключённая к свитчу Juniper QFX5200

Экономия энергии CPU отключена. В тестах и Vitastor, и Ceph развёрнуто по 2 OSD на 1 SSD.

Все результаты ниже относятся к случайной нагрузке 4 КБ блоками (если явно не указано обратное).

Производительность голых дисков:

  • T1Q1 запись ~27000 iops (задержка ~0.037ms)
  • T1Q1 чтение ~9800 iops (задержка ~0.101ms)
  • T1Q32 запись ~60000 iops
  • T1Q32 чтение ~81700 iops

Ceph 15.2.4 (Bluestore):

  • T1Q1 запись ~1000 iops (задержка ~1ms)
  • T1Q1 чтение ~1750 iops (задержка ~0.57ms)
  • T8Q64 запись ~100000 iops, потребление CPU процессами OSD около 40 ядер на каждом сервере
  • T8Q64 чтение ~480000 iops, потребление CPU процессами OSD около 40 ядер на каждом сервере

Тесты в 8 потоков проводились на 8 400GB RBD образах со всех хостов (с каждого хоста запускалось 2 процесса fio). Это нужно потому, что в Ceph несколько RBD-клиентов, пишущих в 1 образ, очень сильно замедляются.

Настройки RocksDB и Bluestore в Ceph не менялись, единственным изменением было отключение cephx_sign_messages.

На самом деле, результаты теста не такие уж и плохие для Ceph (могло быть хуже). Собственно говоря, эти серверы как раз хорошо сбалансированы для Ceph - 6 SATA SSD как раз утилизируют 25-гигабитную сеть, а без 2 мощных процессоров Ceph-у бы не хватило ядер, чтобы выдать пристойный результат. Собственно, что и показывает жор 40 ядер в процессе параллельного теста.

Vitastor:

  • T1Q1 запись: 7087 iops (задержка 0.14ms)
  • T1Q1 чтение: 6838 iops (задержка 0.145ms)
  • T2Q64 запись: 162000 iops, потребление CPU - 3 ядра на каждом сервере
  • T8Q64 чтение: 895000 iops, потребление CPU - 4 ядра на каждом сервере
  • Линейная запись (4M T1Q32): 2800 МБ/с
  • Линейное чтение (4M T1Q32): 1500 МБ/с

Тест на чтение в 8 потоков проводился на 1 большом образе (3.2 ТБ) со всех хостов (опять же, по 2 fio с каждого). В Vitastor никакой разницы между 1 образом и 8-ю нет. Естественно, примерно 1/4 запросов чтения в такой конфигурации, как и в тестах Ceph выше, обслуживалась с локальной машины. Если проводить тест так, чтобы все операции всегда обращались к первичным OSD по сети - тест сильнее упирался в сеть и результат составлял примерно 689000 iops.

Настройки Vitastor: --disable_data_fsync true --immediate_commit all --flusher_count 8 --disk_alignment 4096 --journal_block_size 4096 --meta_block_size 4096 --journal_no_same_sector_overwrites true --journal_sector_buffer_count 1024 --journal_size 16777216.

EC/XOR 2+1

Vitastor:

  • T1Q1 запись: 2808 iops (задержка ~0.355ms)
  • T1Q1 чтение: 6190 iops (задержка ~0.16ms)
  • T2Q64 запись: 85500 iops, потребление CPU - 3.4 ядра на каждом сервере
  • T8Q64 чтение: 812000 iops, потребление CPU - 4.7 ядра на каждом сервере
  • Линейная запись (4M T1Q32): 3200 МБ/с
  • Линейное чтение (4M T1Q32): 1800 МБ/с

Ceph:

  • T1Q1 запись: 730 iops (задержка ~1.37ms latency)
  • T1Q1 чтение: 1500 iops с холодным кэшем метаданных (задержка ~0.66ms), 2300 iops через 2 минуты прогрева (задержка ~0.435ms)
  • T4Q128 запись (4 RBD images): 45300 iops, потребление CPU - 30 ядер на каждом сервере
  • T8Q64 чтение (4 RBD images): 278600 iops, потребление CPU - 40 ядер на каждом сервере
  • Линейная запись (4M T1Q32): 1950 МБ/с в пустой образ, 2500 МБ/с в заполненный образ
  • Линейное чтение (4M T1Q32): 2400 МБ/с

NBD

NBD - на данный момент единственный способ монтировать Vitastor ядром Linux, но он приводит к дополнительным копированиям данных, поэтому немного ухудшает производительность, правда, в основном - линейную, а случайная затрагивается слабо.

NBD расшифровывается как "сетевое блочное устройство", но на самом деле оно также работает просто как аналог FUSE для блочных устройств, то есть, представляет собой "блочное устройство в пространстве пользователя".

Vitastor с однопоточной NBD прокси на том же стенде:

  • T1Q1 запись: 6000 iops (задержка 0.166ms)
  • T1Q1 чтение: 5518 iops (задержка 0.18ms)
  • T1Q128 запись: 94400 iops
  • T1Q128 чтение: 103000 iops
  • Линейная запись (4M T1Q128): 1266 МБ/с (в сравнении с 2800 МБ/с через fio)
  • Линейное чтение (4M T1Q128): 975 МБ/с (в сравнении с 1500 МБ/с через fio)

Установка

Debian

  • Добавьте ключ репозитория Vitastor: wget -q -O - https://vitastor.io/debian/pubkey | sudo apt-key add -
  • Добавьте репозиторий Vitastor в /etc/apt/sources.list:
    • Debian 11 (Bullseye/Sid): deb https://vitastor.io/debian bullseye main
    • Debian 10 (Buster): deb https://vitastor.io/debian buster main
  • Для Debian 10 (Buster) также включите репозиторий backports: deb http://deb.debian.org/debian buster-backports main
  • Установите пакеты: apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu

CentOS

  • Добавьте в систему репозиторий Vitastor:
    • CentOS 7: yum install https://vitastor.io/rpms/centos/7/vitastor-release-1.0-1.el7.noarch.rpm
    • CentOS 8: dnf install https://vitastor.io/rpms/centos/8/vitastor-release-1.0-1.el8.noarch.rpm
  • Включите EPEL: yum/dnf install epel-release
  • Включите дополнительные репозитории CentOS:
    • CentOS 7: yum install centos-release-scl
    • CentOS 8: dnf install centos-release-advanced-virtualization
  • Включите elrepo-kernel:
    • CentOS 7: yum install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
    • CentOS 8: dnf install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm
  • Установите пакеты: yum/dnf install vitastor lpsolve etcd kernel-ml qemu-kvm

Установка из исходников

  • Установите ядро 5.4 или более новое, для поддержки io_uring. Желательно 5.8 или даже новее, так как в 5.4 есть как минимум 1 известный баг, ведущий к зависанию с io_uring и контроллером HP SmartArray.
  • Установите liburing 0.4 или более новый и его заголовки.
  • Установите lp_solve.
  • Установите etcd, версии не ниже 3.4.15. Более ранние версии работать не будут из-за различных багов, например #12402. Также вы можете взять версию 3.4.13 с этим конкретным исправлением из ветки release-3.4 репозитория https://github.com/vitalif/etcd/.
  • Установите node.js 10 или новее.
  • Установите gcc и g++ 8.x или новее.
  • Склонируйте данный репозиторий с подмодулями: git clone https://yourcmc.ru/git/vitalif/vitastor/.
  • Желательно пересобрать QEMU с патчем, который делает необязательным запуск через LD_PRELOAD. См qemu-*.*-vitastor.patch - выберите версию, наиболее близкую вашей версии QEMU.
  • Установите QEMU 3.0 или новее, возьмите исходные коды установленного пакета, начните его пересборку, через некоторое время остановите её и скопируйте следующие заголовки:
    • <qemu>/include<vitastor>/qemu/include
    • Debian:
      • Берите qemu из основного репозитория
      • <qemu>/b/qemu/config-host.h<vitastor>/qemu/b/qemu/config-host.h
      • <qemu>/b/qemu/qapi<vitastor>/qemu/b/qemu/qapi
    • CentOS 8:
      • Берите qemu из репозитория Advanced-Virtualization. Чтобы включить его, запустите yum install centos-release-advanced-virtualization.noarch и далее yum install qemu
      • <qemu>/config-host.h<vitastor>/qemu/b/qemu/config-host.h
      • Для QEMU 3.0+: <qemu>/qapi<vitastor>/qemu/b/qemu/qapi
      • Для QEMU 2.0+: <qemu>/qapi-types.h<vitastor>/qemu/b/qemu/qapi-types.h
    • config-host.h и qapi нужны, т.к. в них содержатся автогенерируемые заголовки
  • Установите fio 3.7 или новее, возьмите исходники пакета и сделайте на них симлинк с <vitastor>/fio.
  • Соберите и установите Vitastor командой mkdir build && cd build && cmake .. && make -j8 && make install. Обратите внимание на переменную cmake QEMU_PLUGINDIR - под RHEL её нужно установить равной qemu-kvm.

Запуск

Внимание: процедура пока что достаточно нетривиальная, задавать конфигурацию и смещения на диске нужно почти вручную. Это будет исправлено в ближайшем будущем.

  • Желательны SATA SSD или NVMe диски с конденсаторами (серверные SSD). Можно использовать и десктопные SSD, включив режим отложенного fsync, но производительность однопоточной записи в этом случае пострадает.
  • Быстрая сеть, минимум 10 гбит/с
  • Для наилучшей производительности нужно отключить энергосбережение CPU: cpupower idle-set -D 0 && cpupower frequency-set -g performance.
  • Пропишите нужные вам значения вверху файлов /usr/lib/vitastor/mon/make-units.sh и /usr/lib/vitastor/mon/make-osd.sh.
  • Создайте юниты systemd для etcd и мониторов: /usr/lib/vitastor/mon/make-units.sh
  • Создайте юниты для OSD: /usr/lib/vitastor/mon/make-osd.sh /dev/disk/by-partuuid/XXX [/dev/disk/by-partuuid/YYY ...]
  • Вы можете поменять параметры OSD в юнитах systemd. Смысл некоторых параметров:
    • disable_data_fsync 1 - отключает fsync, используется с SSD с конденсаторами.
    • immediate_commit all - используется с SSD с конденсаторами.
    • disable_device_lock 1 - отключает блокировку файла устройства, нужно, только если вы запускаете несколько OSD на одном блочном устройстве.
    • flusher_count 256 - "flusher" - микропоток, удаляющий старые данные из журнала. Не волнуйтесь об этой настройке, 256 теперь достаточно практически всегда.
    • disk_alignment, journal_block_size, meta_block_size следует установить равными размеру внутреннего блока SSD. Это почти всегда 4096.
    • journal_no_same_sector_overwrites true запрещает перезапись одного и того же сектора журнала подряд много раз в процессе записи. Большинство (99%) SSD не нуждаются в данной опции. Однако выяснилось, что диски, используемые на одном из тестовых стендов - Intel D3-S4510 - очень сильно не любят такую перезапись, и для них была добавлена эта опция. Когда данный режим включён, также нужно поднимать значение journal_sector_buffer_count, так как иначе Vitastor не хватит буферов для записи в журнал.
  • Запустите все etcd: systemctl start etcd
  • Создайте глобальную конфигурацию в etcd: etcdctl --endpoints=... put /vitastor/config/global '{"immediate_commit":"all"}' (если все ваши диски - серверные с конденсаторами).
  • Создайте пулы: etcdctl --endpoints=... put /vitastor/config/pools '{"1":{"name":"testpool","scheme":"replicated","pg_size":2,"pg_minsize":1,"pg_count":256,"failure_domain":"host"}}'. Для jerasure EC-пулов конфигурация должна выглядеть так: 2:{"name":"ecpool","scheme":"jerasure","pg_size":4,"parity_chunks":2,"pg_minsize":2,"pg_count":256,"failure_domain":"host"}.
  • Запустите все OSD: systemctl start vitastor.target
  • Ваш кластер должен быть готов - один из мониторов должен уже сконфигурировать PG, а OSD должны запустить их.
  • Вы можете проверить состояние PG прямо в etcd: etcdctl --endpoints=... get --prefix /vitastor/pg/state. Все PG должны быть 'active'.
  • Пример команды для запуска тестов: fio -thread -ioengine=libfio_vitastor.so -name=test -bs=4M -direct=1 -iodepth=16 -rw=write -etcd=10.115.0.10:2379/v3 -pool=1 -inode=1 -size=400G.
  • Пример команды для заливки образа ВМ в vitastor через qemu-img:
    qemu-img convert -f qcow2 debian10.qcow2 -p -O raw 'vitastor:etcd_host=10.115.0.10\:2379/v3:pool=1:inode=1:size=2147483648'
    
    Если вы используете немодифицированный QEMU, данной команде потребуется переменная окружения LD_PRELOAD=/usr/lib/x86_64-linux-gnu/qemu/block-vitastor.so.
  • Пример команды запуска QEMU:
    qemu-system-x86_64 -enable-kvm -m 1024
      -drive 'file=vitastor:etcd_host=10.115.0.10\:2379/v3:pool=1:inode=1:size=2147483648',format=raw,if=none,id=drive-virtio-disk0,cache=none
      -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=1,write-cache=off,physical_block_size=4096,logical_block_size=512
      -vnc 0.0.0.0:0
    
  • Пример команды удаления образа (инода) из Vitastor:
    vitastor-rm --etcd_address 10.115.0.10:2379/v3 --pool 1 --inode 1 --parallel_osds 16 --iodepth 32
    

Известные проблемы

  • Запросы удаления объектов могут в данный момент приводить к "неполным" объектам в EC-пулах, если в процессе удаления произойдут отказы OSD или серверов, потому что правильная обработка запросов удаления в кластере должна быть "трёхфазной", а это пока не реализовано. Если вы столкнётесь с такой ситуацией, просто повторите запрос удаления.

Принципы реализации

  • Я люблю архитектурно простые решения. Vitastor проектируется именно так и я намерен и далее следовать данному принципу.
  • Если вы пришли сюда за идеальным кодом на C++, вы, вероятно, не по адресу. "Общепринятые" практики написания C++ кода меня не очень волнуют, так как зачастую, опять-таки, ведут к излишним усложнениям и код получается красивый... но медленный.
  • По той же причине в коде иногда можно встретить велосипеды типа собственного упрощённого HTTP-клиента для работы с etcd. Зато эти велосипеды маленькие и компактные и не требуют использования десятка внешних библиотек.
  • node.js для монитора - не случайный выбор. Он очень быстрый, имеет встроенную событийную машину, приятный нейтральный C-подобный язык программирования и развитую инфраструктуру.

Автор и лицензия

Автор: Виталий Филиппов (vitalif [at] yourcmc.ru), 2019+

Заходите в Telegram-чат Vitastor: https://t.me/vitastor

Лицензия: VNPL 1.1 на серверный код и двойная VNPL 1.1 + GPL 2.0+ на клиентский.

VNPL - "сетевой копилефт", собственная свободная копилефт-лицензия Vitastor Network Public License 1.1, основанная на GNU GPL 3.0 с дополнительным условием "Сетевого взаимодействия", требующим распространять все программы, специально разработанные для использования вместе с Vitastor и взаимодействующие с ним по сети, под лицензией VNPL или под любой другой свободной лицензией.

Идея VNPL - расширение действия копилефта не только на модули, явным образом связываемые с кодом Vitastor, но также на модули, оформленные в виде микросервисов и взаимодействующие с ним по сети.

Таким образом, если вы хотите построить на основе Vitastor сервис, содержаший компоненты с закрытым кодом, взаимодействующие с Vitastor, вам нужна коммерческая лицензия от автора 😀.

На Windows и любое другое ПО, не разработанное специально для использования вместе с Vitastor, никакие ограничения не накладываются.

Клиентские библиотеки распространяются на условиях двойной лицензии VNPL 1.0 и также на условиях GNU GPL 2.0 или более поздней версии. Так сделано в целях совместимости с таким ПО, как QEMU и fio.

Вы можете найти полный текст VNPL 1.1 в файле VNPL-1.1.txt, а GPL 2.0 в файле GPL-2.0.txt.