13 634
правки
Изменения
Нет описания правки
[[en:Ceph performance]][[File:Ceph-funnel.svg|500px|right]]Ceph — это SDS (по-русски — программная СХД), которая по некоторым параметрам является уникальной в своём роде, и в целом, умеет очень многое — S3, диски виртуалок, кластерную FS + огромный багаж дополнительных фич. И всё было бы хорошо — бери, ставь, запускай своё облако и руби бабло — если бы не один маленький нюанс: ПРОИЗВОДИТЕЛЬНОСТЬ. Терять 95 % производительности в Production-е разумным людям обычно жалко. «Облакам» типа AWS, GCP, Яндекса, по-видимому, не жалко — у них тоже собственные крафтовые SDS и они тоже тормозят примерно так же :-) но этот вопрос оставим — кто мы такие, чтобы их судить. В данной статье описано, каких показателей производительности можно добиться от цефа и как. Если вкратце, то примерным ориентиром служит доклад Nick Fisk «Low-Latency Ceph», в его исполнении Low Latency это 0.7 мс (на запись). Лучший результат с Ceph-ом получить практически невозможно (худший — легко). При этом 0.7 мс — это всего лишь примерно ~1500 iops в 1 поток. На чтение в идеальной ситуации можно получить где-то раза в 2 больше, то есть где-то до 3000 iops в 1 поток. Для сравнения: любой самый дешёвый серверный SSD-диск раз в 10 быстрее, средний порядок задержки SSD на запись — 0.01-0.04 мс, на чтение — 0.1 мс. '''UPDATE: Догнать (почти догнать) SDS-кой локальной диск можно, я это сделал в своём собственном проекте — Vitastor: https://vitastor.io :-) это блочная SDS с архитектурой, похожей на Ceph, но при этом БЫСТРАЯ — в тесте на SATA SSD кластере задержка и чтения, и записи составила 0.14 мс. На том же кластере задержка записи у Ceph была 1 мс, а чтения — 0.57 мс. Детали в [https://yourcmc.ru/git/vitalif/vitastor/src/branch/master/README.md README] — смотрите по ссылке.'''
== Бенчмаркинг ==
Задержки обычно важнее простой пиковой производительности случайного чтения/записи, так как далеко не каждое приложение может загрузить диск при большом параллелизме / глубокой очереди (32-128 запросов).
=== Тестирование дисков ===
* Задержка случайной записи: {{Cmd|1=fio -ioengine=libaio -sync=1 -direct=1 -invalidate=1 -name=test -bs=4k -iodepth=1 -rw=randwrite -runtime=60 -filename=/dev/sdX}}
«А почему так мало…» — см.нижесагу про конденсаторы.
[[Файл:Warning icon.svg|32px|link=]] Когда разворачиваете Ceph OSD на SSD — очень разумно не отдавать её под Ceph целиком, а оставить небольшой раздел (10-20 гб) пустым для будущего использования под бенчмаркинг. Ибо Ибо SSD имеют свойство со временем (или при забивании данными под 80%) начинать тормозить. Очень удобно иметь возможность гонять fio на пустом никем не используемом разделе. ==== Лирическое отступление ==== Почему нужно тестировать именно так? Ведь в целом производительность диска зависит от многих параметров:* Размер блока* Режим — чтение, запись или смешанный режим чтение+запись в разных пропорциях* Параллелизм — размер очереди и число потоков, то есть, в целом число одновременно запрашиваемых у диска операций* Длительность теста* Исходное состояние — пуст, заполнен линейной записью, заполнен случайной записью, заполнен случайной записью на протяжении какого-то времени и т. п.* Распределение данных — например, 10% горячих данных и 90% холодных — или, например, определённое расположение горячих данных (в начале диска)* Другие смешанные режимы тестов, например, тестирование одновременно с разными размерами блоков Также и результаты можно интерпретировать с разной степенью детализации — вместо простого среднего числа операций или мегабайт в секунду можно также приводить графики, гистограммы, перцентили и так далее — это, естественно, даст больше информации о поведении тестируемого образца. Есть и философская сторона тестов — например, производители серверных SSD иногда заявляют о необходимости подготовки диска к тестам путём 2-х кратной полной случайной перезаписи, чтобы нагрузить слой трансляции адресов диска, а я считаю, что это на самом деле ставит SSD в неправдоподобно плохие по сравнению с реальной нагрузкой условия; есть сторонники рисования графиков формата «задержка в зависимости от числа операций в секунду», что я считаю немного странным, но тоже возможным подходом — в нём, по сути, строится график F1(q) в зависимости от F2(q) и график обычно получается достаточно замысловатый — но для каких-то применений, может быть, и тоже разумный. В общем, бенчмаркингом заниматься можно бесконечно, и уж несколько дней, чтобы предоставить полную информацию, точно уйдёт. Этим обычно и занимаются ресурсы типа 3dnews в своих обзорах SSD. А мы не хотим сидеть несколько дней. Мы хотим обозначить набор тестов, которые можно провести быстро и сразу составить примерное представление о производительности. Посему общая идея — выделить несколько наиболее «крайних» режимов, протестировать диск в них и представить, что остальная часть «амплитудно-скоростной характеристики» диска является некоторой гладкой функцией в пределах изменения параметров между крайними точками. Тем более, что каждому из крайних режимов соответствует и реальное применение в своей категории приложений:# Использующих в основном линейный или крупноблочный доступ. Для таких приложений наиболее важная характеристика — производительность линейного доступа в мегабайтах в секунду. Отсюда режим тестирования линейным доступом 4 МБ блоком со средней очередью — 16-32 операции. Результаты — только в МБ/с.# Использующих случайный доступ мелким блоком и при этом способных к распараллеливанию. Отсюда — режимы тестирования случайным доступом 4 КБ блоком (стандартный блок для большинства ФС и, плюс-минус, СУБД) с большой очередью — 128 операций или, если диск не удаётся нагрузить одним потоком CPU с глубиной очереди 128 — тогда в несколько (2-4-8 или больше) потоков по 128 операций. Результаты — только в iops. Задержку (latency) указывать не нужно, так как в данном тесте её можно произвольно увеличить, просто подняв размер очереди — задержка жёстко связана с iops формулой latency=queue/iops.# Использующих случайный доступ мелким блоком и при этом НЕспособных к распараллеливанию. Таких приложений больше, чем вы могли подумать — например, в части записи сюда относятся все транзакционные СУБД. Отсюда вытекают режимы тестирования случайным доступом 4 КБ блоком с очередью 1 и, для записи, с fsync после каждой операции, чтобы диск/СХД не могли нас обмануть и положить запись во внутренний кэш. Результаты — iops или latency, по желанию — но выберите что-то одно, так как числа, опять же, жёстко связанные.
=== Тестирование кластера Ceph ===
Как тестировать Ceph после сборки. ==== RBD ==== fio -ioengine=rbd. Нужно сделать следующее:# fio -ioengine=rbd -direct=1 -name=test -bs=4M -iodepth=16 -rw=write -pool=rpool_hdd -runtime=60 -rbdname=testimg# fio -ioengine=rbd -direct=1 -name=test -bs=4k -iodepth=1 -rw=randwrite -pool=rpool_hdd -runtime=60 -rbdname=testimg# fio -ioengine=rbd -direct=1 -name=test -bs=4k -iodepth=128 -rw=randwrite -pool=rpool_hdd -runtime=60 -rbdname=testimg# ...и потом то же самое для read/randread. Смысл в том, чтобы протестировать а) задержку в идеальных условиях б) линейную пропускную способность в) случайные iops-ы. Перед тестами чтения образ сначала нужно заполнить линейной записью, так как чтение из пустого образа очень быстрое :) Запускать нужно оттуда, где будут реальные пользователи RBD. В целом, с другого узла результаты обычно лучше. Также всё то же самое можно повторить изнутри виртуалки или через krbd:# fio -ioengine=libaio -direct=1 -name=test -bs=4M -iodepth=16 -rw=write -runtime=60 -filename=/dev/rbdX# fio -ioengine=libaio -direct=1 -sync=1 -name=test -bs=4k -iodepth=1 -rw=randwrite -runtime=60 -filename=/dev/rbdX# fio -ioengine=libaio -direct=1 -name=test -bs=4k -iodepth=128 -rw=randwrite -runtime=60 -filename=/dev/rbdX Заметьте, что при тестировании задержки через libaio добавилась опция -sync=1. Это не случайно, а соответствует режиму работы СУБД (транзакционная запись в 1 поток). В ioengine=rbd понятие sync отсутствует, там всё всегда «sync». ==== Отдельные OSD ==== ceph-gobench: https://github.com/rumanzo/ceph-gobench/ Либо https://github.com/vitalif/ceph-bench, что примерно то же самое. Родоначальник идеи — @socketpair Марк Коренберг ([https://github.com/socketpair/ceph-bench оригинал]). Бенчилка тестирует ''отдельные OSD'', что очень помогает понять, кто же из них тупит-то. Перед запуском надо создать пул без репликации {{Cmd|ceph osd pool create bench 128 replicated; ceph osd pool set bench size 1; ceph osd pool set bench min_size 1}} и с числом PG, достаточным, чтобы при случайном выборе туда попали все OSD (ну или прибить их вручную к каждому OSD upmap-ами). ==== CephFS ==== «Нормальных» инструментов для тестирования ФС, сцуко, нет!!! «Нормальный» инструмент — это такой инструмент, который вёл бы себя, как файловый сервер: случайно открывал, создавал/писал/читал и закрывал маленькие файлы среди большого общего количества, разбитые по набору каталогов Всё, что есть, какое-то кривожопое: bonnie++, например, зачем-то тестирует запись по 1 байту. iometer, fs_mark не обновлялись лет по 10, но и паттерн файл сервера не умеют. Лучшее, что умеют — это тест создания файлов. Пришлось написать свой ioengine для fio: https://github.com/vitalif/libfio_fileserver :) ==== S3 (rgw) ==== Предпочтительный вариант: [https://github.com/vitalif/hsbench hsbench] — ссылка дана на исправленную версию (!). Максимально простой, консольное Golang приложение. Оригинальная версия пока что имеет 2 неприятных бага: во-первых, вместо чтения объектов целиком читает только первые 64 КБ, во-вторых, производит последовательное, а не случайное, чтение. Что, например, с minio приводит к слишком оптимистичным результатам тестов. В моей данные баги исправлены. [https://github.com/intel-cloud/cosbench cosbench] — очень толстый, Java с Web-интерфейсом, XML-настройки. [https://github.com/minio/warp minio warp] — тестов чуть больше, чем в hsbench, но зато тестирует только 1 бакет и при каждом тесте загружает данные заново. ==== Что использовать не надо ==== * dd и hdparm для бенчмаркинга не использовать вообще никогда!!!* rados bench использовать тоже не надо, так как он создаёт для тестирования очень мало объектов (в 1 поток всего 2, в 128 — несколько сотен). «Случайная» запись в такое число объектов не очень-то и случайная.* rbd bench лучше тоже не использовать. В принципе, он адекватен, но fio всё равно лучше.* Не надо удивляться, если Ceph не может загрузить диски на 100 % при случайной записи. Он тормоз :)
=== Тестирование сети ===
sockperf. На одной ноде запускаем сервер: <tt>sockperf sr -i IP --tcp</tt>. На другой клиент в режиме ping-pong: <tt>sockperf pp -i SERVER_IP --tcp -m 4096</tt>. Нормальная средняя цифра ВНИМАНИЕ: В выводе фигурирует '''половина''' задержки (задержка в районе 0одну сторону).05мс (50usТаким образом, плюсдля получения RTT её стоит умножить на 2. Нормальный средний RTT -минус 20usв районе 30-50 микросекунд (0.05ms).
<s>Также qperf. На одной ноде просто <tt>qperf</tt>. На второй <tt>qperf -vvs -m 4096 SERVER_IP tcp_lat</tt>.</s>
== О транзакционности записи ==
[[Файл:Warning icon.svg|32px|link=]] Плохая новость!
Важная особенность Ceph — ''вся запись, даже та, для которой никто этого явно не просит, ведётся транзакционно''. То есть, никакая операция записи не завершается, пока она не записана в журналы всех OSD и не сделан fsync() диска. Так сделано, чтобы предотвращать [[#RAID WRITE HOLE]]-подобные ситуации рассинхронизации данных между репликами при отключении питания, потере сети и т.п…
== Конденсаторы ==
Нас спасёт такое чудо инженерной мысли, как '''SSD с конденсаторами''' (точнее, обычно или с суперконденсаторами — ионисторами). Которые на M.2 SSD, кстати, прекрасно видны невооружённым глазом(только тут это не ионисторы :)):
[[File:Micron 5100 sata m2.jpg]]
=== Про размер block.db ===
Дефолтные настройки цефа:
* 1 Гб WAL = 4x256 Мб
* max_bytes_for_level_base и max_bytes_for_level_multiplier не изменены, поэтому равны 256 Мб и 10 соответственно
* соответственно , L1 = 256 Мб
* L2 = 2560 Мб
* L3 = 25600 Мби т. д.
…Соответственно!
Rocksdb положит L2 на block.db, только если раздел имеет размер хотя бы 2560+256+1000 Мб (Мб — округлим вверх до '''4 Гб)ГБ'''. А L3 она положит на block.db, только если block.db размером хотя бы 25600+2560+256+1000 МБ = около '''30 ГБ'''. А L4, соответственно, если ещё +256 ГБ, то есть итого '''286 ГБ'''.
== Снапшоты ==
В моём примере на NVMe-шках — write iops с репликацией Q=1 примерно 1500, а с EC — примерно 500. Q=128 — примерно 25000 с репликацией и 10000 с EC.
=== Про вероятность потери данных ===
Смотрите мой калькулятор вероятности потери данных в кластере: https://yourcmc.ru/afr-calc/
== Контроллеры ==
* Отключить оффлоады: ethtool -K enp3s0f0 gro off gso off tso off lro off sg off
* Отключить объединение прерываний: ethtool -C enp3s0f0 rx-usecs 0
* Самый дешёвый 10G свитч с Ebay: Quanta LB6M / Brocade TurboIron 24X24X — но говно старое унылое и жрёт под 200 ватт, и греется и жужжит соответственно* UPD Самый дешёвый свитч с Aliexpress: [https://aliexpress.ru/item/1005004429524441.html TP-LINK TL-ST5008F]. На чипе [https://www.realtek.com/en/products/communications-network-ics/item/rtl9303-cg Realtek RTL9303-CG] Если совсем задолбала латенси, как отключить ВСЕ оффлоады? <pre>for i in rx tx tso ufo gso gro lro tx nocache copy sg txvlan rxvlan; do /sbin/ethtool -K eth3 $i off 2>&1 > /dev/null;done</pre>
== Настройка виртуалок и ФС ==
* virtio — самый быстрый, но до QEMU 4.0 не умел TRIM. Юзать надо его.
* virtio-scsi — достаточно быстрый. На самом деле, умеет multiqueue и поэтому на быстром хранилище (например, при прямом доступе к локальной NVMe) должен быть быстрее virtio — но в случае с Ceph это не так, так как цеф не настолько быстрый, чтобы multiqueue играл роль
* nvme — тоже достаточно быстрый, но немного медленнее virtio. Принцип работы похожий — и там, и там кольцевые буферы. Можно использовать для тех образцов ПО, которые не умеют virtio, потому что не уметь nvme сейчас совершенно точно не может никто. Например, если хочется потестировать VMWare ESXi с вложенной виртуализацией внутри QEMU, то nvme — для вас!
=== cache=writeback ===
# Блюстор блокирует запись в журнал записью на HDD. Когда включен спец.кэш, HDD начинает рандомно писать сильно быстрее, и блокировки при сбросе уходят. Действует кэш, естественно, временно — когда он кончится, производительность случайной записи опять упадёт. Однако плюс в том, что в Ceph-е этого, скорее всего, не произойдёт, так как скорость случайной записи ограничивается, собственно, самим Ceph-ом и распределяется по всем дискам кластера :).
# Однако, для обычных дисков без SSD-кэша отключение кэша тоже даёт выигрыш… есть гипотеза, что из-за того же тормоза с bluefs (проверю).
Более свежие тесты бенчилкой ceph-gobench на том же самом стенде. Версия Ceph Mimic 13.2.2, Bluestore, журналы на SSD.
osd.14 | 302 | 229 | 135 | Hitachi Ultrastar A7K2000 | HUA722020ALA330
</tab>
==== Примечания ====
Toshiba MG07ACA14TE тоже замечены в подобном поведении, см. обсуждение в списке рассылки: https://www.spinics.net/lists/ceph-users/msg60753.html
== Почему вообще Bluestore такой медленный? ==
Особенность NAND флеш-памяти заключается в том, что пишется она мелкими блоками, а стирается большими. Актуальное соотношение для Micron 3D NAND — страница (page) 16 КБ, блок стирания (block) — 16 или 24 МБ (1024 или 1536 страниц, MLC/TLC соответственно). Случайное чтение страницы быстрое. Запись тоже, но писать можно только в предварительно стёртую область — а стирание медленное, да ещё и число стираний каждого блока ограничено — после нескольких тысяч (типичное значение для MLC) блок физически выходит из строя. В более дешёвых и плотных (MLC, TLC, QLC — 2-4 бита на ячейку) чипах лимит стираний меньше, в более дорогих и менее плотных (SLC, один бит на ячейку) — больше. Соответственно, при «тупом» подходе — если при записи каждого блока его просто стирать и перезаписывать — случайная запись во флеш-память, во-первых, будет очень медленной, а во-вторых, она будет быстро выводить её из строя.
Но почему тогда SSD быстрые? А потому, что внутри SSD на самом деле есть очень мощный и умный контроллер (1-2 гигагерца, типично 4 ядра или больше, примерно как процессоры мобильников), и на нём выполняется нечто, называемое Flash Translation Layer — прошивка, которая переназначает каждый мелкий логический сектор в произвольное место диска. FTL всё время поддерживает некоторое количество свободных стёртых блоков и направляет каждую мелкую случайную запись в новое место диска, в заранее стёртую область. Поэтому запись быстрая. Одновременно FTL делает дефрагментацию свободного места и Wear Leveling (распределение износа), направляя запись и перемещая данные так, чтобы все блоки диска стирались примерно одинаковое количество раз. Кроме того, во всех SSD некоторый % реального места зарезервирован под Wear Leveling и не виден пользователю («overprovision»), а в хороших серверных SSD этот процент весьма большой — например, в Micron 5100 Max это +60 % ёмкости (в Micron 5100 Eco — всего лишь +7.5 %, 1.92 ТБ SSD содержит 10 чипов NAND по 1.5 терабита и 2 по 768 гигабит).
Именно из наличия FTL вытекает и проблема с энергонезависимостью и «power loss protection»-ом. Карты отображения секторов — это метаданные, которые при сбросе кэша тоже нужно сбрасывать в постоянную память, и именно этот сброс и вносит торможение в работу настольных SSD с fsync.
* с prefer_deferred_size и min_alloc_size они, видимо, не игрались
* обновлённые диски не играют никакой роли гарантированно. 260000 или 310000 iops — для цефа никакой разницы нет.
=== Бонус: висян (vSAN) ===
[https://media-www.micron.com/-/media/client/global/documents/products/other-documents/micron_vsan_6,-d-,7_on_x86_smc_reference_architecture.pdf Micron Accelerated All-Flash SATA vSAN 6.7 Solution]
Конфигурация серверов:
* 384 GB RAM 2667 MHz
* 2X Micron 5100 MAX 960 GB (randread: 93k iops, randwrite: 74k iops)
* 8X Micron 5200 ECO 3.84TB (randread: 95k iops, randwrite: 17k iops)
* 2x Xeon Gold 6142 (16c 2.6GHz)
* Mellanox ConnectX-4 Lx
* Connected to 2x Mellanox SN2410 25GbE switches
«Соответствует конфигурации VMWare AF-6, по заявлениям дающей от 50K iops чтения на каждый сервер»
* 2 реплики (аналог size=2 в цефе)
* 4 сервера
* 4 ВМ на каждом сервере
* 8 диска на каждую ВМ
* 4 потока на каждый диск
Суммарный параллелизм ввода/вывода: 512
100%/70%/50%/30%/0% write
* «Baseline» (данные умещаются в кэш): 121k/178k/249k/314k/486k iops
* «Capacity» (не умещаются): 51k/66k/90k/134k/363k
* Задержка равна 1000*512/IOPS миллисекунд во всех тестах (1000мс * параллелизм / iops)
* '''Нет тестов задержки с низким параллелизмом'''
* '''Нет тестов линейного чтения/записи'''
Заключение:
* ~3800 iops на запись в пересчёте на каждый диск данных
* ~1600 iops на запись в пересчёте на диск, если данные не влезают в кэш
* ~15000 iops на чтение в пересчёте на каждый диск данных
* ~11400 iops на чтение в пересчёте на диск, если данные не влезают в кэш
* Итого: при параллельной нагрузке в данном тесте vSAN смотрится хуже, чем Ceph
* С другой стороны, vSAN гиперконвергентный, а Ceph, в идеале, нет — или тормозит сильнее, чем мог бы
== Модели ==
* https://amarao-san.livejournal.com/3437997.html - «IOPS не существует» — сказ о latency
*: ''Прим.вред — iops существуют, но с обязательным указанием режима тестирования и параллелизма''
* https://yourcmc.ru/afr-calc/ - мой калькулятор вероятности потери данных в кластере Ceph в зависимости от размера кластера и схемы отказоустойчивости
== Советы лучших собаководов ==