Всем привет! Меня зовут Карина Кошева. Я тестирую совместимость СХД с системами виртуализации в YADRO. Мы проводим такое тестирование, потому что нам важно проверять, насколько успешно система будет работать в инфраструктуре заказчика.

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

Особенности тестирования СХД

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

Мы тестируем TATLIN.UNIFIED — систему хранения данных enterprise-класса. Пользователь ожидает от нее быструю запись и чтение данных, устойчивость к сбоям и ошибкам разного рода при отказе одного или нескольких компонентов; масштабируемость без необходимости остановки работы системы — чтобы можно было «на горячую» добавлять диски и полки. Помимо этого, СХД предоставляет возможность работы со снапшотами и репликацию данных. Администратор может настраивать, мониторить и автоматизировать работу СХД. Для этого есть веб-интерфейс, cli (локальный и удаленный), публичный API. Предусмотрен доступ по разным протоколам, встроенные механизмы экономии места — thin provisioning.

Наша система хранения данных — это программно-аппаратный комплекс, железная часть которого состоит из двух storage-контроллеров, двух серверов, соединенных друг с другом по RDMA. У каждого сервера есть свой процессор, оперативная память и системные диски. К storage-контроллерам подключаются дисковые полки — SAS или NVMe, которые содержат набор дисков: HDD, SSD и NVMe.

В терминологии СХД принято называть «таргетом» саму СХД, а клиента, который подключается к СХД по протоколам, — «инициатором». Для блочного доступа у TATLIN.UNIFIED есть протоколы iSCSI, Fiber Channel и NVMe over TCP, для файлового — NFS и CIFS/SMB.

Подробнее ознакомиться с устройством системы хранения данных можно в статье Дениса Довженко.

Гибкий, модульный и открытый: почему OpenStack

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

Моя команда тестирует совместимость СХД с системами виртуализации. Они позволяют запускать несколько изолированных окружений — виртуальных машин или контейнеров — на физическом сервере с гипервизором и управлять выделенными им ресурсами: CPU, память, диск, сеть. Помимо гипервизоров часто система виртуализации включает в себя систему управления всей инфраструктурой.

Система виртуализации — это экономия железа и места в дата‑центре, удобная миграция и масштабирование, быстрое развертывание шаблонов, упрощенное тестирование и резервное копирование. 

Я специализируюсь на OpenStack — достаточно популярной open source-системе виртуализации. Ее преимущества — гибкость и модульность: в ней можно установить только нужные сервисы, быстро расширить кластер, добавив дополнительные серверы, подключить или отключить драйверы, использовать разные типы гипервизоров.

Базовые функции OpenStack — создание и управление облачными ресурсами. Мы можем создавать и удалять виртуальные машины, выполнять операции со снапшотами, добавлять в виртуальные машины ресурсы: например, добавить к ВМ дополнительный диск. А для администрирования системы можно использовать веб-интерфейс, cli и API.

Веб-интерфейс управления облачными ресурсами в OpenStack 
Веб-интерфейс управления облачными ресурсами в OpenStack 

Разберем на примере ресурсов одной виртуальной машины, какие сервисы есть в OpenStack:

  • За размещение ВМ на гипервизоре, выделение ресурсов и подключение к ней устройств отвечает сервис Nova. Нода, на которой находится сервис Nova, называется Compute node.

  • Обычно создание ВМ в OpenStack происходит из заранее подготовленного образа с предустановленной операционной системой — за хранение и управление такими образами (images) отвечает сервис Glance

  • Для предоставления ВМ сетевого доступа в Интернет или к другим ресурсам, а также для ограничения доступа (security groups) используется сервис Neutron.

  • Предоставление хранилища для ВМ происходит через сервис Cinder. Такое хранилище может предоставляться разными СХД, поэтому каждый вендор пишет свой Cinder-драйвер для интеграции с OpenStack. Нода, на которой находится сервис Cinder, называется Storage node.

Схематический вид сервисов ВМ в OpenStack
Схематический вид сервисов ВМ в OpenStack

Другие основные сервисы OpenStack — это Keystone, он же сервис авторизации и аутентификации, и Horizon, который предоставляет веб-интерфейс. Полный список сервисов можно найти на официальном сайте OpenStack: есть мониторинг, шифрование, оркестрация и много других.

Настраиваем тестовую инфрастуктуру

Для тестирования потребуются стенды, на которых мы будем прогонять различные тестовые сценарии. Стенды состоят из связки СХД и серверов, которые подключаются к СХД по одному или нескольким протоколам. Cinder-драйвер TATLIN.UNIFIED поддерживает протоколы FC, iSCSI и NVMe over TCP. 

В инфраструктуре заказчика может быть больше сотни серверов. У нас нет возможности полностью повторить ее (слишком дорого), поэтому при тестировании мы пользуемся вложенной виртуализацией: на «железном» гипервизоре располагаются виртуальные машины, которые сами являются гипервизорами.  В OpenStack виртуальная конфигурация позволяет разнести Cinder (хранилище) и Nova (размещение ВМ на гипервизоре) на разные ноды кластера, благодаря этому можно покрыть больше тестовых сценариев. 

Подготовка стенда начинается с установки и настройки СХД и OpenStack. С СХД все просто: у команд тестирования и разработки есть инструменты для деплоя нужной версии по сети. С деплоем OpenStack все сложнее. Для его установки есть много инструментов: devstack, juju, kolla-ansible, RDO Packstack. Но не все они удобные: установить их за 15-20 минут не получится, особенно если конфигурация сложнее, чем all-in-one — когда все сервисы размещаются на одной ноде. В процессе развертывания могут возникать неожиданные ошибки, или какие-то решения внезапно могут перестать поддерживаться. 

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

Чтобы минимизировать влияние этих факторов при установке, мы используем kolla-ansible — это проект для деплоя и конфигурирования OpenStack, где все сервисы и компоненты находятся в Docker-контейнерах. Благодаря этому инструменту можно:

  • задеплоить нужную версию OpenStack: нам это полезно, так как мы не всегда используем самые свежие версии, а ориентируемся на версии наших заказчиков; 

  • расширить кластер: например, добавить дополнительные Compute node при увеличении нагрузки;

  • изменить конфигурацию определенного сервиса: для этого нужно только правильно заполнить inventory и запустить playbook. 

Для нашего тестового стенда мы разворачиваем на инициаторе три-пять виртуальных машин, которые будут лежать в основе будущего кластера OpenStack. В каждую из них пробрасывается FC-карта, если тестируем с протоколом FC, и Ethernet-бридж, если тестируем c протоколом iSCSI или NVMe over TCP. На ВМ мы заранее готовим операционную систему и выполняем сетевую к��нфигурацию.

Как TATLIN.UNIFIED работает с Cinder-драйвером и OpenStack

СХД взаимодействует с OpenStack иначе, чем с большинством других систем виртуализации. Так, при настройке работы нашей СХД с Linux или VMware, типичный сценарий следующий: в нужном пуле пользователь создает ресурс определенного размера и block size (512e/4kn) через систему администрирования или с помощью утилиты командной строки tatlin-cli. 

Чтобы инициатор мог увидеть созданный ресурс, пользователь экспортирует через веб-интерфейс или cli этот ресурс на порты и хосты или хост-группы, где в качестве идентификатора для iSCSI используется iqn инициатора, а для FC — WWPN. Затем на инициаторе сканируются диски, и созданный ресурс должен отобразиться в списке блочных устройств на сервере. Теперь на нем можно создавать файловую систему и работать. 

В случае OpenStack все нужные действия выполняет Cinder-драйвер — он самостоятельно отправляет СХД команды: например, на создание и удаление ресурсов и выполнение их экспортов. 

При создании ВМ в OpenStack на диске, предоставленном TATLIN.UNIFIED, нам достаточно выбрать несколько основных параметров:

  • flavor — сколько ресурсов — CPU, RAM, Root disk — выделять для ВМ;

  • source — это образ или диск, с которого будет загружаться ВМ; 

  • network — сеть или сети, к которым должна быть подключена ВМ. 

Диалоговое окно создания ВМ в OpenStack
Диалоговое окно создания ВМ в OpenStack

Когда ВМ впервые создается из данного image (образа), а вcinder.confвыставлена настройка image_volume_cache_enabled =true, в СХД создается image cache — пустой ресурс, в который из OpenStack-контроллера будет скопировано содержимое образа операционной системы из Glance. Сначала образ запишется локально на Storage node, а потом в пустой ресурс на СХД. 

В дальнейшем при создании ВМ на базе такого же образа ОС новые ресурсы будут клонироваться непосредственно из Image cache. После того как ресурс готов, он экспортируется на Compute node, где будет создана виртуальная машина.  

Клонирование происходит разными способами, в зависимости от типа пула. Начиная с TATLIN.UNIFIED 3.1 появились пулы с косвенной адресацией и поддержкой снапшотов. Для таких пулов при клонировании чаще всего будут использоваться снапшоты. Если используются пулы с прямой адресацией, клонирование может выполняться одним из двух способов: через инициатор, когда монтируются оба ресурса к одной cinder-ноде, либо на стороне СХД операцией Simple Clone. В таких пулах клонирование будет происходить медленнее, чем на пулах с косвенной адресацией, так как данные будут фактически копироваться.

Тесты с эмуляцией пользовательской нагрузки

Тестирование совместимости СХД с системами виртуализации можно условно разделить на два типа: функциональное и тестирование под нагрузкой. 

Для функционального тестирования мы используем фреймворк Tempest. Он поддерживается OpenStack, и его можно установить непосредственно при деплое. Помимо стандартных тестов из фреймворка, мы написали свой плагин, который продолжаем дополнять новыми тестами для базовых проверок хранилища. 

Тестирование под нагрузкой у нас имеет свою специфику. Так, при разработке сценариев важным является требование к TATLIN.UNIFIED 3.2 на поддержку до 2000 блочных ресурсов на систему. Это значит, что заказчик может развернуть до 2000 виртуальных машин. При работе СХД с таким большим количеством ресурсов может происходить замедление работы самой СХД и появляться нетипичные для функциональных тестов ошибки.

Мы тестируем совместимость СХД с разными системами виртуализации. Их количество продолжает расти, поэтому мы составили общий для всех таких систем шаблон тестирования совместимости СХД под нагрузкой. Чек-лист содержит кейсы, которые часто встречаются в разных системах виртуализации, при этом сценарии из них можно составить разные. Они могут включать в себя: миграции ресурсов между пулами, операции со снапшотами, работу с QoS (Quality of Service), проверки отказоустойчивости и апгрейды СХД.

Хотя я тестирую в основном OpenStack, отмечу, что при тестировании одного и того же сценария на разных платформах виртуализации поведение СХД может различаться. Например, при работе с VMware часто встречается сценарий общего хранилища, когда доступ к datastore (хранилище данных в терминологии VMware) имеет большое количество гипервизоров: в VMware ESXi 9.0 поддерживается до 128 гипервизоров на одну datastore. Со всех этих гипервизоров могут выполняться операции I/O одновременно. Конкурентный доступ в данном случае обеспечивается на стороне СХД с помощью SCSI-примитивов.

Взаимодействие СХД с VMware
Взаимодействие СХД с VMware

При этом в OpenStack такой сценарий встречается гораздо реже. Встретить его можно только в multiattach —  когда том может быть подключен к нескольким ВМ одновременно, — да и то в меньших масштабах. На сайте OpenStack сценарии с общим хранилищем подсвечены красной плашкой с сообщением, что пользователь сам несет ответственность за свои действия. Конкурентный доступ в данном случае обеспечивается не с помощью локов на стороне СХД, а за счет кластерной файловой системы. В остальных случаях доступ к ресурсу есть только у одного сервера: либо у cinder-ноды — если в этот момент происходит копирование образа, либо у compute-ноды — если ВМ уже создана на базе этого ресурса. 

Также разница в том, что создание и удаление ресурсов для VMware будет осуществляться вручную или через cli, а для сценариев в OpenStack — через public API посредством Cinder-драйвера. То есть сценарий на создание большого числа ВМ будет затрагивать на СХД разные компоненты и может приводить к обнаружению разного типа багов.

Взаимодействие СХД с OpenStack
Взаимодействие СХД с OpenStack

Автоматизируй и разделяй (задачи): что умеет OpenStack

OpenStack весьма популярен, поэтому уже оброс многочисленными инструментами для автоматизации под разные задачи: OpenStack cli, различные Ansible-модули для управления OpenStack, Terraform для развертывания инфраструктуры.

OpenStack cli подходит для простых однострочных скриптов. Более того, в OpenStack cli есть удобные ключи --format (-f) и --column (-c), которые позволяют гибко настраивать формат вывода. Например, можно вывести имена всех ВМ в выключенном состоянии в json-формате командой: 

openstack server list --all --status SHUTOFF -c Name -f json 

Также для каждой команды есть ключ --debug для отладки, который выводит подробные логи запросов и ответов.

В Ansible мы часто используем динамические inventory, чтобы получить список ВМ OpenStack и что-нибудь с ними сделать. Для этого Ansible должен знать IP-адрес и данные учетной записи администратора от OpenStack — это все хранится в файле clouds.yaml, который можно скачать из вкладки API Access. Например, проверить доступность всех ВМ, запущенных на OpenStack, можно с помощью команды:

ansible-playbook playbooks/ping.yml -i inventories/dynamic/yoga/openstack.yml

Если часть ВМ будет удалена, или, наоборот, добавятся новые — все эти изменения подтянутся автоматически при запуске playbook.

Также мы активно применяем Ansible при конфигурировании OpenStack: например, чтобы закинуть конфиг multipath или скопировать Cinder-драйвер на storage-ноды. 

Тестирование производительности или Rally-тестинг

Наша команда активно использует фреймворк Rally для тестирования производительности OpenStack. Он предоставляет большое количество сценариев, которые можно модифицировать, объединять между собой для последовательного запуска. Также можно написать свои специфичные сценарии и подключить их как плагин. Фреймворк написан на Python (как и весь OpenStack), что позволяет легко модифицировать его под свои нужды. Сами сценарии — это yaml-файлы, в которых указываются необходимые параметры для запуска. Полный список этих сценариев можно посмотреть в документации Rally. 

Как ранее упоминалось, в TATLIN.UNIFIED 3.2 поддерживается до 2000 блочных ресурсов, на базе каждого из них может быть создана отдельная виртуальная машина. Чтобы их создать, используется подобный сценарий.  

NovaServers.boot_server_from_volume:
  - args:
      flavor:
        name: m1.medium
      image:
        name: debian
      volume_size: 10
      auto_assign_nic: true
      volume_type: tatlin-ssd
      userdata: |
        {% filter indent(width=18) %}{% include 'rally/cloud-init/run-fio.j2'%}
        {% endfilter %}
    runner:
      type: "constant"
      times: 20
      concurrency: 10
      timeout: 1500
    context:
      existing_network: {}
      users:
        tenants: 3
        users_per_tenant: 2

NovaServers.boot_server_from_volume  — название задачи, которая будет выполняться. В секции args задаются параметры запуска ВМ: 

  • flavor — ресурсы, выделяемые для ВМ; 

  • image — образ; 

  • volume size — размер диска; 

  • volume type — тип диска.

Можно добавить параметры auto_assign_nic: true — в этом случае к ВМ будет подключен сетевой интерфейс. И если добавить параметр userdata, можно при запуске ВМ выполнять различные скрипты и команды — у нас так запускается fio профиль. 

В runner задаются параметры прогона: сколько раз должен выполниться сценарий, с какой параллельностью, то есть во сколько потоков и с каким таймаутом. В context конфигурируются используемые OpenStack сети, количество пользователей и проектов. Тут же указывается, нужно ли создавать новые или использовать существующие.

По умолчанию в Rally, как и в Tempest после завершения сценария удаляются все созданные сущности: ВМ, сети, проекты. Нам такое не подходит, потому что для нас подача нагрузки — это чаще всего только начало теста. Мы решили проблему за счет установки конфига cleanup_threads = 0 в rally.conf, который запрещает выполнение очистки.

Тестирование происходит на минимальном количестве железных серверов, поэтому ВМ также требуются небольшие. Мы используем ту же ОС, что и во фреймворке Rally для тестирования, — CirrOS. Ее образ занимает около 25 МБ. Требования к ресурсам минимальны: хватает flavor m1.nano с 128 Мб RAM и одним CPU. Эти ВМ мы используем для тестирования большого количества ресурсов, а для тестирования нагрузки на СХД по data-path у нас есть «большие» ВМ на базе Debian. На образе предустановлена утилита fio широко используемый инструмент для моделирования различных I/O нагрузок — и настроен компонент cloud-init, чтобы автоматически выполнять необходимые скрипты сразу после создания и запуска ВМ.

Во время тестов важно проверять состояние ВМ и отсутствие I/O-ошибок. Для этого при помощи динамического inventory Ansible получаем список IP-адресов всех ВМ, после чего можно их пропинговать, чтобы проверить их доступность или логи на предмет I/O-ошибок. 

Пример динамического inventory в Ansible:

plugin: openstack.cloud.openstack
clouds_yaml_path:
 - cloud_configs/clouds.yaml
only_clouds:
 - yoga
all_projects: true
expand_hostvars: false
fail_on_errors: true
legacy_groups: false
strict: true
keyed_groups:
 - key: "openstack.project_id"

С помощью параметра keyed_groups можно разделять ВМ по группам. Допустим, 100 виртуальных машин мы можем поделить на группы функционально: 25 машин будут записывать данные в СХД, 25 машин — читать данные, 25 ВМ — будут выключены, а еще 25 — переезжают на другой гипервизор. Чтобы разделить их таким образом, мы создаем их в четырех разных проектах, но также можно использовать для этого другие критерии — например, flavor. В примере выше идет разделение по project ID. Такое разделение помогает нам запускать разные типы нагрузки на каждую группу. 

Тесты отказоустойчивости 

В TATLIN.UNIFIED многие компоненты продублированы для обеспечения отказоустойчивости: даже если один или несколько из таких компонентов выйдут из строя, работа всей СХД должна быть продолжена без потери данных или их недоступности. Например, система должна работать при отключении одного из блоков питания, или при отказе сетевой карты. 

Обычно такие тесты выполняются двумя инженерами: один выдергивает провода, а второй контролирует состояние системы. В веб-интерфейсе TATLIN.UNIFIED есть вкладка «Аппаратная платформа», на которой есть изображения СХД со всех сторон. Они облегчают проведение таких тестов.

Веб-интерфейс «Аппаратной платформы»
Веб-интерфейс «Аппаратной платформы»

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

Отключен один из сетевых линков для iSCSI
Отключен один из сетевых линков для iSCSI

Вместо заключения

Мы разобрали механику работы TATLIN.UNIFIED с OpenStack и особенности тестовых стендов, которые помогают нам проверять систему под реальной нагрузкой. Рассмотрели инструменты и фреймворки, которые позволяют нам повторять сложные сценарии заказчиков и видеть, как система поведет себя под реальной нагрузкой. Однако мир тестирования СХД куда шире — я не затрагивала темы тестирования апгрейдов, автоматизации, а тестирования отказоустойчивости коснулась совсем немного. Если вам интересны подобные материалы, оставляйте комментарии, а мы напишем продолжение!