## Vitastor [Read English version](README.md) ## Идея Я всего лишь хочу сделать качественную блочную SDS! Vitastor - распределённая блочная SDS, прямой аналог Ceph RBD и внутренних СХД популярных облачных провайдеров. Однако, в отличие от них, Vitastor быстрый и при этом простой. Только пока маленький :-). Архитектурная схожесть с Ceph означает заложенную на уровне алгоритмов записи строгую консистентность, репликацию через первичный OSD, симметричную кластеризацию без единой точки отказа и автоматическое распределение данных по любому числу дисков любого размера с настраиваемыми схемами избыточности - репликацией или с произвольными кодами коррекции ошибок. ## Возможности Vitastor на данный момент находится в статусе предварительного выпуска, расширенные возможности пока отсутствуют, а в будущих версиях вероятны "ломающие" изменения. Однако следующее уже реализовано: - Базовая часть - надёжное кластерное блочное хранилище без единой точки отказа - Производительность ;-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 - Статистика операций ввода/вывода и занятого места в разрезе инодов - Именование инодов через хранение их метаданных в etcd - Снапшоты и copy-on-write клоны ## Планы разработки - Более корректные скрипты разметки дисков и автоматического запуска OSD - Другие инструменты администрирования - Плагины для OpenStack, Kubernetes, OpenNebula, Proxmox и других облачных систем - iSCSI-прокси - Таймауты операций и более быстрое выявление отказов - Фоновая проверка целостности без контрольных сумм (сверка реплик) - Контрольные суммы - Оптимизации для гибридных SSD+HDD хранилищ - Поддержка 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](https://github.com/etcd-io/etcd/pull/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 или новее, возьмите исходные коды установленного пакета, начните его пересборку, через некоторое время остановите её и скопируйте следующие заголовки: - `/include` → `/qemu/include` - Debian: * Берите qemu из основного репозитория * `/b/qemu/config-host.h` → `/qemu/b/qemu/config-host.h` * `/b/qemu/qapi` → `/qemu/b/qemu/qapi` - CentOS 8: * Берите qemu из репозитория Advanced-Virtualization. Чтобы включить его, запустите `yum install centos-release-advanced-virtualization.noarch` и далее `yum install qemu` * `/config-host.h` → `/qemu/b/qemu/config-host.h` * Для QEMU 3.0+: `/qapi` → `/qemu/b/qemu/qapi` * Для QEMU 2.0+: `/qapi-types.h` → `/qemu/b/qemu/qapi-types.h` - `config-host.h` и `qapi` нужны, т.к. в них содержатся автогенерируемые заголовки - Установите fio 3.7 или новее, возьмите исходники пакета и сделайте на них симлинк с `/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](VNPL-1.1.txt), а GPL 2.0 в файле [GPL-2.0.txt](GPL-2.0.txt).