Погружаемся в S3 на Ceph. Как мы удаляли 460 млн мелких объектов

Привет! Меня зовут Дмитрий Сорокин, я занимаюсь развитием облачных сервисов в Nubes (НУБЕС). 

Недавно мы представили новый сервис — объектное хранилище S3 на базе нашего облака. Запустили его на Ceph. Перед этим провели множество тестов. В частности, решили выяснить, как на практике Ceph справляется с мелкими объектами — проблемой любого S3. Как все прошло и какие результаты получили, рассказываю далее.

b74791698ff73d0115e8380f73fe80ee.jpegСправка: что такое Ceph >>

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

Принцип действия максимально прост: диски располагаются на разных серверах, но объединяются в единое пространство с общей точкой входа. Благодаря Ceph данные распределяются равномерно, без перекосов нагрузки и прочих бед.

Почему мы это тестировали 

Иногда случается, что объекты в S3 весят по несколько килобайт и их очень много. Если это ваш случай и вам нужно удалить огромное множество объектов, то поздравляем. История может растянуться на несколько месяцев, а то и лет. 

С такой проблемой сталкиваются все, кто работает с S3. Чтобы понять, как поведет себя Ceph при подобной нагрузке, мы провели тест. А еще сделали это, потому что:

  • нам нужны предсказуемые результаты работы хранилища при апокалипсисе самых худших сценариях,

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

  • ранее мы использовали Ceph только для хранения VM, а это достаточно большие объекты и совсем другой опыт,

  • одновременно проводили другие тесты, и было время запустить этот тест в фоновом режиме.

Создание объектов

Для эксперимента взяли 12 OSD нод по 12 жестких дисков NL-SAS с выносом журналов на nvme. Отдельно от них подключили 3 rgw и LB.

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

Нам требовалось нагенерировать много (а для вас много — это сколько?) миллионов объектов на 1 бакет. По опыту с демо-стендом на VM, где нам остро не хватало дисковой емкости, мы создавали объекты размером в символический 1 байт и в больших количествах.

Исходный код теста немного исправили под наши задачи (оказывается, на Go писать несложно, а я и не знал). Исключили код, который чистит бакет после теста и читает объекты. После всего этого запустили процесс создания мелких объектов и пошли пить кофе.

Когда вернулись, обнаружили явно недостаточное количество объектов, хотя тест завершился. Запустили его повторно, но прироста так и не случилось. Посмотрели код повнимательнее и поняли, что объекты всегда создаются с одними и теми же именами. При повторном запуске они затираются.

Исправили код: прописали имя объекта в виде случайного uuid. Затем запустили тест повторно. Прокатило. 

На следующий день в тестовом бакете мы увидели ~460 млн объектов, которые занимали 1,7 терабайта. Скорость заливки заметна на графике:  

344df78ad8d20e64de8278eb0cb06502.png

Запуск удаления объектов

По старому опыту с закрытыми решениями мы знали, что удаление такого количества данных может растянуться на 1–3 года. Но так как стенд на тот момент еще не вышел в продуктив, у нас была возможность и полное право полностью его зачистить и перезалить, в случае если бы потерпели фиаско с тестом.

Запаслись терпением и запустили процесс удаления бакета. Вернулись на следующий день и посмотрели на график количества объектов. Стало понятно, что с текущим трендом процесс займет чуть более 30 дней.

a78b4ab952d8e4005016ae1a9f773000.png

Но нам хотелось быстрее. Поэтому мы пошли читать про механизмы сбора мусора и их оптимизацию. Утилизация шпинделей была порядка 20%, по nvme — тоже далеко не запредельная. Мы явно не упирались в это узкое место.

Ускорение процесса

Тюнинг сборщика мусора

Изучили документацию и изменили настройки сборщика мусора на более агрессивные.

ceph config set client.rgw rgw_gc_max_trim_chunk 64
ceph config set client.rgw rgw_gc_max_concurrent_io 20

Чтобы применить их, потребовалось перезапустить rwg, что мы и сделали через ceph orch restart, который поочередно перезапустил процессы.

И чистка встала!  

800b863a0cfb55e63ec1e85540545e45.png

Жизненный цикл любой операции продолжался до рестарта rgw. Запустив удаление повторно, мы получили примерно ту же картину:

31553718e4fb25a8aa41dc4c989c3810.png

Удаление в обход сборщика мусора

Что делать, если хочется еще быстрее? Мы нашли способ. 

Чтобы ускорить очистку, мы запустили удаление в обход GС. Кажется, это ни на что не повлияло, и размер занятого места в пуле уменьшался пропорционально удалению объектов из бакета. Мы увеличили конкурентные io-потоки:

# radosgw-admin bucket rm --bucket="zzz/s3-flood-benchmark" --bypass-gc --purge-objects --max-concurrent-ios 256

Благодаря этому маневру картина изменилась:

d61e084e198cbf35673fa908190dcc70.png

При таком паттерне нагрузочные тесты, которые запускались краткосрочно, уже давали значительную просадку по параметру запросов в секунду.

Мы добились того, что скорость удаления объектов увеличилась в четыре раза

Чем пришлось расплачиваться

В какой-то момент получили проблему деградации:  

health: HEALTH_WARN
1532 large omap objects

О чем речь? Существует мягкое ограничение Ceph в 100 тысяч записей. Когда их становится больше, следующая глубокая очистка делит каталог на два, чтобы избежать создания большого OMAP. Но этого не произошло, так как мы отключили сборку мусора при удалении объектов.

Что в итоге

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

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

© Habrahabr.ru