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

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

Нужно сказать, что больше всего я работал с Ceph, поэтому в основном методология строится исходя из этого опыта, но, если не вдаваться в детали, то подход к тестированию более-менее одинаков для всех распределенных программных хранилищ данных (SDS).

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

Задачи


  1. Оценить минимальную задержку обработки операций. Насколько быстро работает хранилище в идеальных условиях.
  2. Оценить максимальную глубину очереди операций до достижения лимитов. Как только производительность клиента начинает деградировать из-за достигнутых лимитов — это и есть максимальная глубина очереди.
  3. Оценить предельное количество одновременно работающих максимально эффективных клиентов до начала деградации производительности.
  4. Оценить скорость деградации кластера при большом количестве клиентов.

Подготовка


Клиенты


Клиентская нагрузка во время тестов генерируется таким же способом, как будет генерироваться клиентами в продакшне. Клиенты не должны мешать друг другу, конкурируя за локальный ресурс. Например, должно быть доступно достаточное количество гипервизоров, на которых будут созданы виртуальные машины (VM). Если мы тестируем хранилище для дисков VM, то внутри них запустим тестовую нагрузку. Если это хранилище с S3 API, то нужны несколько клиентов S3, способных создать достаточную нагрузку и не мешать друг другу.

Идеально, если можно создать реальную, а не синтетическую нагрузку. Менее идеально, но тоже очень хорошо — знать профиль нагрузки для создания синтетических тестов на его основе. Так, например, поступили ребята из Facebook при тестировании дисков.

Лимиты


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

На хранилище может быть установлено два типа лимитов:

  1. Лимиты на количество операций (IOPS).
  2. Лимиты на количество переданных данных (MB/s).

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

Определяться с лимитами следует на этапе планирования, основываясь на потребностях клиента. Заданные лимиты во время тестирования производительности играют роль этакого SLO (Service Level Objective — целевой уровень сервиса) на ресурсы — это граничные пределы, в которых клиенты будут работать. Эти же лимиты послужат ограничениями, в пределах которых проводятся тесты.

Набор тестов


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

В качестве основного инструмента используется FIO. Фактически — это индустриальный стандарт для тестирования блочных устройств. FIO запускается внутри VM. В роли тестового файла выступает файл, расположенный в корневой файловой системе. Мы делаем так, чтобы учесть нюансы работы стандартной для многих файловой системы ext4, включая работу журнала. Все остальные параметры теста касаются настроек FIO.

Мы отталкиваемся от предположения, что наиболее требовательный к задержкам клиент будет работать с диском синхронно. Значит, что на каждую операцию записи будет поступать операция синхронизации кеша(flush). И только дождавшись завершения такой операции, клиентское ПО будет считать запись успешной. Так работают, например, классические БД с WAL (Write-Ahead Log).

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

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

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

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

Статистика


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

Понадобится статистика со всех элементов системы:

  • гипервизоров,
  • серверов хранилища,
  • самого софта,
  • сетевого оборудования.

При тестах дисков VM в идеальном варианте нужно иметь статистику и с них.

Минимальный набор метрик предоставляется любыми современными системами сбора статистики с операционной системы из коробки, такими как node-exporter, collectd и тп. В деталях же, эта тема требует отдельной проработки, так как чтобы понимать какие дополнительные метрики необходимо собирать именно вам для дальнейшего анализа, зависит от конкретной системы и особенностей ее эксплуатации.

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

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

  1. Авария вызвана нагрузкой. В таком случае хорошо, что мы получим оповещение и сможем выявить узкие и проблемные места перед запуском.
  2. Авария не вызвана нагрузкой. В таком случае хорошо, что мы сможем остановить тестирование и запустить его заново после устранения аварийной ситуации.

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

Окружение


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

Примеры того, что нужно собрать:

  • версия ОС;
  • версия ядра;
  • версия используемых драйверов;
  • версия софта хранилища;
  • модель, количество и частота процессоров;
  • модель, количество, объем и частота оперативной памяти;
  • модель материнской платы;
  • модель сетевых карт и сетевая топология;
  • модель и количество дисков;
  • количество хостов в кластере;
  • количество гипервизоров;
  • количество и характеристики VM.

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

Тестирование


Пустой кластер


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

Заполнение


На этом этапе нужно знать целевую заполненность кластера. Понятно, что очень редко кластер с данными заполняется на 99-100%, ведь в этом случае его становится практически невозможно обслуживать и разработчиками наверняка неосознанно заложены дополнительные «спецэффекты» на такой случай. Поэтому, с учетом экономики проекта, нужно заранее определить целевой процент заполненности кластера, который не стоит превышать, но до которого система будет заполнена данными.

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

Первый тест


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

Оценка задержки


Для оценки минимальной задержки используется тест на синхронную случайную запись с глубиной очереди 1, запускаемый на одном клиенте. После этого проводится такой же тест на чтение. В результате мы узнаем скорость работы хранилища в идеальных условиях для одного клиента. Этот показатель будет ориентиром во всех будущих тестах. По отклонению значения задержки (latency) операции от этого значения можно будет оценить деградацию производительности.

Выбор эталонной глубины очереди


Для запуска масштабного тестирования нужно подготовить «максимально эффективного» клиента. Это такой клиент, который постоянно работает на пике доступной производительности диска. Если не брать в расчет загруженность кластера, то доступная клиенту производительность диска зависит от двух показателей:

  1. Cкорость обработки каждой операции.
  2. Количество параллельно выполняемых операций.

С точки зрения клиента мы не можем повлиять на скорость обработки конкретных операций, но можем увеличивать параллелизм. Следовательно, максимально эффективный клиент, это тот клиент, который использует максимальный параллелизм при работе с диском, при этом укладывается в доступные ему ресурсы (IOPS / MB/s). Это значит, что для поиска такого клиента нам нужно запускать каждый тест из набора с разной глубиной очереди. В результате мы получим информацию о том, на какой глубине очереди каждый из тестов работает наиболее эффективно.

По результатам тестов нужно строить графики, показывающие распределение latency и IOPS. Задача — найти такую глубину очереди, при которой распределение задержки еще не растет, при этом показатели IOPS или MB/s уже находятся максимально близко к заданному лимиту. Максимальная эффективная глубина очереди для тестов с разными параметрами может отличаться. Берем ее за эталон для тестов и используем на следующем этапе. Это и есть наши самые эффективные клиенты.

Тестирование кластера


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

По результатам нужно дать оценку для каждого теста:

  1. Максимальное количество максимально эффективных клиентов до деградации производительности кластера.
  2. Скорость деградации производительности при дальнейшем росте количества клиентов.

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

Сопровождение процесса


Подконтрольный запуск


Весь процесс тестирования нужно отслеживать, что все идет по плану. Запуск первых тестов на ночь, перед уходом с работы — наиболее частая ошибка. В таком случае очень часто можно получить такие варианты развития событий:

  1. Тест «упал» сразу после запуска по причине неправильной конфигурации.
  2. Тест «упал» в середине работы из-за нехватки какого-либо ресурса.
  3. Тест частично «упал» или частично не запустился.
  4. Автоматизированные тесты наложились один на другой.

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

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

Узкие места


Во время и после тестов, важно внимательно изучать статистику состояния ресурсов и промежуточные результаты тестов. Популярная ошибка — это запуск большого количества тестов последовательно, не глядя на результаты. В таком случае часто случается:

  1. Клиенты конкурировали за локальный ресурс. Например, CPU гипервизора.
  2. Локальные перегрузки на сети из-за неудачной балансировки.
  3. Что угодно, что могло быть замечено в процессе теста или сразу после первого прогона и влияет на результат.

Конечно, в таких случаях результаты выбрасываются на помойку, ситуация исправляется, а тестирование проводится заново.

В статистике и результатах нужно искать любые аномалии — перегрузка, неравномерная нагрузка, отсутствие нагрузки. Любые странности должны насторожить оператора.

Документирование


Необходимо документировать все. Все успешные результаты тестов должны сохраняться на будущее в исходном формате. Это даст возможность повторно построить какие-то графики в будущем, если возникнет такая необходимость.

Структуру хранения результатов так же стоит продумать заранее, она не должна сильно изменяться в будущем. Например, разделить по каталогам по номеру задачи, с подкаталогами по названию теста, далее по количеству клиентов, а ссылки на задачи держать в Wiki. Четкая структура сильно облегчает обращение к историческим данным, например для построения сравнительных графиков нескольких кластеров.

Интерпретация результатов


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

Если же с увеличением количества клиентов добиться деградации качества обслуживания не удалось, то возможно стоит подумать над увеличением лимитов.

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

  1. Утилизация CPU, как на хостах хранилища, так и у клиентов. Нужно смотреть не только общую нагрузку, но и распределение нагрузки по ядрам, отсутствия длительного ожидания в очереди на CPU. Что происходит, когда система начинает деградировать? Не ошибка ли это в выборе железа или количества сервисов на хост? Или CPU тратит время в ожидании какого-то ресурса?
  2. Утилизация и перегрузка сети. Раз мы работаем с сетевым хранилищем, то стоит посмотреть, не оказалась ли сеть «бутылочным горлышком». Потери пакетов, ошибки и утилизация — основные параметры.
  3. Утилизация и latency дисков. Опять же — это ведь хранилище. В идеальном мире самым медленным элементом системы должен быть конечный элемент. Т.е. не должно быть узких мест, система должна быть настроена так, чтобы реализовать потенциал дисков. В реальности, во-первых, нужно опять-таки учитывать профиль нагрузки, а во-вторых, реализовать потенциал дисков иногда невозможно.

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

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

В итоге


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

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

  1. Собираем статистику и подключаем мониторинг. Эти две вещи сэкономят время на тестировании и помогут с интерпретацией результатов.
  2. Описываем окружение и чем точнее, тем лучше.
  3. Перед запуском тестов определеяемся с целевым заполнением кластера и заполняем его данными до этой отметки, если это возможно. Необходимость в этом зависит от используемой системы и временных затрат.
  4. Перед любыми тестами проводим инициирующую запись, чтобы получить реальное значение производительности, которое будет у активных клиентов.
  5. Делаем простой тест для определения скорости работы хранилища в идеальных условиях. После этого, проводим поиск максимально эффективного клиента, последовательно увеличивая глубину очереди. Когда такой клиент найден, запускаем тестирование кластера, прогоняя тесты с одновременной работой нескольких максимально эффективных клиентов, количество которых последовательно увеличиваем.

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

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

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

Полезные ссылки: