09 Май

Как мы храним почти 160 миллионов фотографий…

…, количество которых увеличивается более чем на миллион в неделю.

Как понятно из логотипа, мы для этого используем Ceph. Что такое Ceph и зачем он нужен — в этой статье не рассматривается. За таким можно сходить на Википедию или официальный сайт.

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

Для начала, пару слов о том, кто такие «мы». Мы — это айтишная компания «Колеса, Крыша, Маркет», которая известна своими classified-проектами, являющимися одними из самых посещаемых и высоконагруженных в Казахстане.

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

На момент написания этой статьи мы храним 157172336 фотографий в одном из кластеров, и пока я допишу этот текст, их количество увеличится на несколько тысяч.

О чем здесь речь

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

Например, в пике мы отдаем фотографии со скоростью более 3 Gbps, но лишь 3% трафика отдается непосредственно с Ceph, остальные 97% трафика отдаются из кэша. При такой архитектуре нам не нужны быстрые Ceph кластера с мегапроизводительностью, так что описываться будут больше отказоустойчивые и надежные системы, нежели производительные.

Нагрузка на кластер

В данный момент каждый отдельный кластер при нормальной работе испытывает нагрузку в ~200 операций записи (сюда так же считаются удаления объектов) при 2 Mb/s трафика с пиками до 8 Mb/s. Нагрузка на чтение в разы больше — ~1300 операций чтения с пиками до 4000 при 40 MB/s с пиками до 70 MB/s. Таким образом стандартная нагрузка на кластер ~1500 IOPS при соотношении запись/чтение ~15/85%. Как показала практика, каждый отдельный кластер может выдержать характерную нагрузку как минимум в тройном размере. От количества кластеров нагрузка на каждый отдельный кластер практически не меняется — каждый объект записывается во все кластеры, при чтение же активно используется кеш, о котором я упомянул выше.

Что у нас сейчас

На данный момент у нас 3 кластера, один из которых временно не в работе. Зачем столько — поймете далее по тексту.

Каждый кластер состоит из 3 одинаковых серверов и пары простых оптических 10 Gbps свитчей Dell x4012. Серверы Supermicro, конкретная модель — SuperStorage 6048R-E1CR36L. В каждом сервере 2 CPU Intel E5-2630v4, 128Gb Ram, 32 HDD 7k 2Tb WD Gold WD2004FBYZ, 4 SSD 200Gb Intel S3610, 2 оптические сетевые на 10Gbps и 2 медные на 1Gbps.

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

CPU

В первой версии кластера (Ceph Jewel, Filestore) мы использовали процессоры Intel E5-2609v4 и столкнулись c 100% утилизацией и диким load average (LA) в пиковое время при нормальной работе кластера, не говоря уже о пересборке при вылете OSD. Было решено поменять процессоры на Intel E5-2630v4 и это кардинально решило проблему. После перехода на Bluestore утилизация процессора снизилась, и сейчас не превышает 25% в моменты пересборки при LA 0.25 на ядро. Обычная утилизация в районе 5% при LA <0.1.

Глядя сейчас на графики, могу сказать, что если бы переход на Bluestore произошел раньше, то справились бы и первоначальные процессоры 2609.

Ram

128 Gb при нашей конфигурации — оптимальный вариант как на Filestore, так и на Bluestore. Если на Filestore память утилизировалась файловым кэшем, теперь же процессами OSD с внутренним кэшем.

Диски

Для начала — про выбор вендора.

Сейчас мы используем диски WD Gold, до этого в аналогичных системах использовали Seagate Constellation ES, которые показали себя плохо в плане надежности. В подобных системах диски — расходный материал, но когда вылетает с десяток дисков в месяц — это начинает напрягать. Именно так и было у нас — иной раз по два-три раза в неделю посещали ЦОДы для замены дисков. WD тоже мрут, но существенно реже.

То же самое и про SSD — выбирать стоит Enterprise-class write intensive накопители, десктопным вариантам здесь не место. Мало того, что они быстро изнашиваются, так и еще не отвечают заявленным характеристикам по производительности. Выбрали Intel s3610, ныне уже снятые с производства, и не прогадали. Данные накопители прям радуют, за все время работы не помер ни один. Одной рукой текст пишу, другой слезы счастья вытираю.

Далее, про объем.

Разумный, с моей точки зрения, вариант расчета исходя из требуемого объема. Это важно, здесь не про скорость.

Нужно знать, хотя бы примерно, требуемые полезный объем и прогрессию (изменения потребления объема в единицу времени). Я уже точно не помню какие у нас были объемы два года назад, но пусть будет 20 Tb с планируемым увеличением до 30 Tb в течение двух лет.

Количество реплик (size) 3 — тут, по-моему, даже обсуждать нечего, если говорим про хранение критичных данных. Хотя при достаточно большом количестве нод в кластере можно так же рассмотреть и erasure code для экономии места. Исходя из этого нужно брать минимум 3 сервера на кластер при домене отказа в кластере = хост. Умножаем требуемый объем (30 Tb) на 3 (количество реплик) = 90 Tb.

Добавляем еще половину от этого объема на случай выхода одной из нод из строя (90 Tb должны обеспечиваться двумя нодами) и получаем 135 Tb.

По-умолчанию, при заполнении OSD на 80% Ceph начнет сигнализировать WARN, при 90% остановит запись, и вам это точно не понравится. Лучше до такого не доводить, у нас уже было подобное с одним из кластеров. Эти трешхолды можно настроить, но они достаточно адекватные на мой взгляд. В общем, при выходе из строя одной ноды и пересборке, заполняемость OSD должна быть не выше 80%, так что добавляем еще 25% и получаем примерно 170 Tb.

170 Tb. Именно столько требуется сырого объема для относительно безопасного хранения всего 30 Tb полезных данных на трех нодах одного кластера.  Примерно так у нас и получилось при забивке серверов дисками на 2 Tb. С увеличением количества нод издержки немного сокращаются, но не кардинально.

Количество.

Ceph любит много OSD. Много OSD — это хорошо, это меньше времени на пересборку и больше IOPS с кластера. Старайтесь использовать максимальное разумное количество OSD при требуемом объеме.

Когда мы собирали первый кластер, диски в 2-4 Tb были мейнстримом, сейчас уже в ходу диски на 8 и даже 10 Tb. Могли вместо 4U серверов взять 2U c меньшим количеством дисков, но большего объема, но в итоге выбрали текущее решение. В первую очередь, исходя из времени на пересборку, ну и как бонус — прирост производительности. Пересборка Ceph всегда не айс, а если она длится 3 часа вместо 1.5 — еще грустнее.

И да, не верьте рекламным буклетам, что мол recovery state не влияет на производительность Ceph, это не правда.

И последнее про диски — IOPS.

Тут все сложнее. Во-первых, достаточно сложно просчитать требования, только если у вас уже нет идентичной системы, с которой можно снять показатели. Во-вторых, хоть в этих ваши интернетах много статей и калькуляторов IOPS, все это — абстрактные данные, по которым прямо ориентироваться при построении кластера я бы не советовал. Зачастую получить реальную производительность кластера можно уже только после постройки оного, да и синтетические тесты всегда отличаются от реальной нагрузки. Всегда учитывайте самые плохие показатели и закладывайте производительность с избытком.

Нам было легче, приблизительный характер нагрузки был известен заранее. Да и выбранное количество дисков уже по самым негативным прогнозам покрывало требуемое количество IOPS, так что здесь я никакой полезной информации не предоставлю.

Журналы WAL & DB

Мы хоть и строили медленное хранилище, но все равно использовать SSD под журналы (Filestore) или WAL & DB (Bluestore) — обязательно.

Про объем особенно говорить нечего, скорее всего вам хватит самых мелких SSD на рынке, потому что все это кушает дисковое пространство не особо.

А вот про количество — здесь нужно подойти к выбору исходя из баланса. Можно использовать единственный SSD под WAL & DB всех OSD и тогда выход из строя этой SSD будет равнозначен выходу из строя всей ноды. Так же при таком варианте вы скорее всего упретесь в производительность этого SSD. Часто можно встретить best practice, где рекомендуют использоваться 1 SSD под журналы для 4-6 OSD, но… SSD бывают разные по производительности, OSD тоже могут быть разными, как по производительности, так и по объему. Мы же решили использовать 3 SSD на 33 OSD для этих целей, таким образом при вылете SSD мы теряем 11 OSD, что приемлемо для нас, производительность нас тоже устроила.

В данный момент у нас так же на каждой ноде заменен один HDD на SSD под пул с индексом rgw, ибо с его производительностью были проблемы. В итоге получилось не очень красивое, но достаточно эффективное отношение 3 SSD / 32 HDD, + 1 SSD.

// Небольшое отступление… в высокопроизводительных кластерах под RBD с большим количеством операций записи мы используем 1 NVME (WAL, DB, отдельный NVME-пул) / 4 SAS 15k.

Сеть

Под кластерную сеть использовать не менее 10 Gbps — обязательно. Был опыт и на гигабитной сетке, плачевный. Чем больше нод, OSD и их скорость, тем выше требования к пропускной способности сети. В какой-то момент имеет смысл перейти на 40 Gbps и даже выше.

Первый кластер коммутировали оптикой, потом уже использовали твинаксы. Задержки выше, но существенного снижения производительности не заметили. Хороший вариант для снижения затрат.

Свитчи Dell x4012 — ущербные, как по функционалу, так и возможностям управления. Но для небольшого кластера до 5-6 нод хороший вариант по надежности и цене. Так как свитчи не стекируемые, используем на серверах бонды в режиме balance alb. В дальнейшем будут использоваться стекируемые свитчи Huawei s6720, которые уже в работе и показали себя на отлично.

Так же понравились свитчи Netgear M4300-24X24F, но нам 1 из 4 попался с браком, может только нам так повезло?

Был печальный опыт использования Ubiquiti EdgeSwitch ES-16-XG. Очень дешевый свитч, по функционалу сравнимый с используемым Dell, но в 3 раза дешевле при большем количестве портов. Из двух полученных свитчей один был с браком, а на втором спустя какое-то время отказал интерфейс управления, но сам свитч продолжал работать. В общем, крайне не рекомендую, разве что только для тестового стенда.

Вокруг да около

Как уже описано выше, у нас достаточно медленные кластера объектного хранилища, и вот почему: пользователь достаточно редко (почти никогда) общается с Ceph напрямую и ждет от него ответа. Все дело в сервисах, который окружают Ceph при заливке и отдаче объектов.

Запись объектов непосредственно в Ceph отложенная. При заливке, фотография сначала попадает в быстрый Redis. Отдельный сервис периодически проверяет Redis и переливает все фотографии уже непосредственно в Ceph. Таким образом, даже если заливка фотографии в Ceph занимает 10 сек, пользователь увидит ее уже через мгновение.

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

Грабельки

Основную массу объектов в наших кластерах генерируют три проекта, и исторически сложилось так, что эти объекты размещаются в трех больших бакетах. Они не одинаковые по количеству, но пусть для наглядности будет 3 бакета по 50 миллионов. И это при рекомендуемом количестве объектов на бакет не более 1 миллиона. Не так давно представилась возможность лично наблюдать увеличение задержек индекса по мере увеличения количества объектов, пока мы заливали весь объем из одного кластера в другой. При количестве меньше 1 миллиона на бакет, rgw отдает список из 10к записей меньше секунды, далее задержка увеличивается линейно до десятков секунд. В конце концов, где-то после 10 миллионов объектов на бакет, rgw не в состоянии отдать список 10к вообще. Учитывайте это, если собираетесь хранить большое количество объектов. У нас же решение этой проблемы уже в работе, каждый бакет будет разбит на 256 частей.

Один единственный тормозной диск способен испоганить жизнь всего кластера, даже если у вас десятки нод и сотни OSD. Я не отношу это к проблемам Ceph, ибо он работает с тем железом, что дают. Важно мониторить latency каждого отдельного OSD. У нас из-за этого наблюдались slow request и деградация производительности всего кластера.

Как уже было сказано выше, у нас используется SSD пул для индекса. Так было не всегда. Практика показала, что перенос индекса на SSD пул существенно повышает производительность rgw. Лучше сразу заложить это при проектировании кластера под большое количество объектов.

Проблемы…

…, или почему у нас 3 кластера.

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

В телегочате прозвучал вопрос про домен отказа. С учетом практики, могу сказать, что правильный вариант для критичных данных — домен отказа = кластер.

В один прекрасный понедельник индекс одного из наших больших бакетов просто исчез. Исчез и пересоздался. Сами объекты из кластера никуда не пропали, но индекс отдавал список в несколько тысяч вместо 35 миллионов. Ситуация осложнилась тем, что второй кластер был остановлен на обслуживание днем ранее. Доступ к объектам был через rados (ls | export). Срочным делом был написан скрипт на Bash, который выгружал через rados export объект и загружал его обратно через curl. Горячие данные удалось восстановить в течение суток, остальные объекты восстанавливались в три раза дольше.

Это, наверное, самая большая и эпичная проблема с Ceph, произошедшая с нами. Были и другие проблемы, но именно эта красноречиво дает понять, что не стоит целиком и полностью полагаться на один кластер.

Итоги и немного будущего

Уже получены и ждут своего часа еще 6 идентичных серверов, по 2 на каждый кластер. На существующих кластерах мы подбираемся к лимиту по объему, плюс ожидается увеличение используемого объема и нагрузки в связи с запуском некоторых проектов.

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

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

6 thoughts on “Как мы храним почти 160 миллионов фотографий…

  1. > Умножаем требуемый объем (30 Tb) на 3 (количество реплик) = 90 Tb.
    > Добавляем еще половину от этого объема на случай выхода одной из нод из строя (90 Tb должны обеспечиваться двумя нодами) и получаем 135 Tb.

    По вашей логике, при выходе одной ноды, ее данные отреплицируются на оставшиеся две.
    Не понятно, зачем вам это?
    На двух нодах уже есть по одной копии данных. То, что там будет по 1,5 копии, вам ничего не даст. Это не спасет вас при падении еще одной ноды.
    Имхо, можно оставить кластер в режиме «для полного счастья нужна третья нода», пока вы чините эту третью ноду. Это уменьшит количество требуемых ТБ.

    • Закон Мерфи. Всё, что может пойти не так, пойдет не так.

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

      Ну и еще есть есть причины, почему нельзя делать на ceph фактор репликации x2. Об этом лучше в интернетах почитать.

  2. А почему бы не посмотреть в сторону облачных хранилищ? Скажем, тот же Amazon S3? Вроде по цене не должно много выходить?

    • Медленно. Мы использовали Amazon S3 как резервное хранилище (disaster recovery). Сейчас отказались от Amazon и перешли на mailru S3. Оно быстрее, чем Amazon (потому что ближе), но все равно слишком медленное для отдачи.

  3. Очень полезная статья, одно дело когда все общими терминами и понятиями, а тут реальный пример с реальными конфигурациями. Большое спасибо.

Добавить комментарий для Игорь Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *