Как мы строили S3 хранилище DataLine. Эксперименты, тестирование и немного о бегемотах

0kodi796iwhoi16frktb7mytx_4.png

Снова привет, на связи Алексей Приставко, и это вторая часть моего рассказа об объектном S3 хранилище DataLine на базе Cloudian HyperStore.

Сегодня я подробно расскажу о том, как устроено наше S3 хранилище и с какими трудностями мы столкнулись в процессе его создания. Обязательно коснемся «железной» темы и разберем оборудование, на котором мы в итоге остановились.

Поехали!
Если во время чтения у вас возникнет желание ознакомиться с прикладной архитектурой решения Cloudian, вы найдете ее подробный разбор в предыдущей статье. Там мы в деталях обсудили внутреннее устройство Cloudian, отказоустойчивость и логику работы встроенного SDS.

Итоговая схема физического оборудования


Так как далее речь пойдет о наших «муках выбора», сразу же приведу итоговый список железа, к которому мы пришли. Небольшой дисклеймер: выбор сетевого оборудования был во многом обусловлен его наличием на нашем (между прочим, весьма добротном) складе.

Итак, на физическом уровне хранилища мы имеем следующее оборудование:

Наименование
Функция
Конфигурация
Кол-во
Сервер Lenovo System x3650 M5
Рабочая нода
1x Xeon E5–2630v4 2.2GHz,
4×16GB  DDR4,
14×10TB 7.2K 6Gbps SATA 3.5»,
2×480GB SSD,
Intel x520 Dual Port 10GbE SFP+,
2×750W HS PSU
4
Сервер  HP ProLiant DL360 G9
Нода балансировщика нагрузки
2  E5–2620 v3,
128G RAM,
2 600GB SSD,
4 SAS HDD,
Intel x520 Dual Port 10GbE SFP+
2
Коммутатор Cisco C4500
Border Gateway
Catalyst WS-C4500X-16SFP+
2
Коммутатор Cisco C3750
Порт-экстендер
Catalyst WS-C3750X-24T with C3KX-NM-10G
2
Коммутатор Cisco C2960
control plane
Catalyst WS-C2960+48PST-L
1


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

Начнем с серверов. Серверы Lenovo имеют специальную конфигурацию, выполненную совместно и в полном соответствии с рекомендациями и спецификациями Cloudian. К примеру, в них используется контроллер с функцией прямого доступа к дискам. Так как в нашем случае RAID организуется на уровне прикладного ПО, такой режим повышает надежность и ускоряет работу дисковой подсистемы. Точно такие же серверы можно приобрести в качестве Cloudian Appliance вместе со всеми лицензиями.

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

Пара Cisco 4500X на шестнадцать 10GB SFP+ выполняет роль ядра и бордера нашей маленькой, но гордой сети хранилища. Конечно, железо немного старомодно, но не уступает «новому» в надежности, имеет внутреннее резервирование, а его функционал удовлетворяет всем нашим требованиям. C3750 играют роль фабрик-экстендера, незачем 1G трансиверы в 10G слоты пихать. А переходить полностью на 10GB линки также большого смысла пока нет. Как показали тесты, в процессор и диски мы упираемся раньше.

Схема ниже достаточно подробно иллюстрирует описанную мной физическую организацию:

jjcsmrwqvzkqrder_z9zv3pr4ca.jpeg1. Схема физической организации хранилища

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

Идем ниже по схеме. Обе пары Cisco (4500/4500, 3750/3750) объединены в единые логические устройства с помощью стека и VSS. Стек собран двумя стек-кабелями, VSS через три 10G оптических линка. Это позволяет добиться того, что оба устройства в каждой паре взаимодействуют как единое целое. Такая кластеризация позволяет нам работать в рамках одного прозрачного L2-сегмента через оба устройства пары и сделать общую агрегацию линков с помощью LACP, так как эта технология нативно поддерживается как ОС серверов, так и Cisco IOS. Со стороны сервера это выглядит так, будто он работает с одним свитчом вместо двух, и выше в приложении доступен агрегированный канал двойной ёмкости.

Вся коммутация сетевого оборудования между собой и на входящие каналы выполнена с помощью оптических 10G линков, серверное оборудование подключается при помощи 10G Twinax кабелей Cisco и 1G медью.

Для отказоустойчивости на входящем канале используется BGP, для балансировки между внешними IP-адресами — Round Robin DNS. Сами внешние адреса запаркованы на серверах-балансировщиках нагрузки и в случае необходимости мигрируют между нодами с помощью связки Pacemaker/Corosync.

Мониторинг и управление по IPMI осуществляется по прямому внутреннему линку. Все менеджмент-интерфейсы (как серверов, так и Cisco) подключены через отдельные свитчи control plane. Они же, в свою очередь, включены в сеть управления ЦОД. Это гарантирует нам невозможность потери связи с оборудованием в ходе работ или в результате аварии на внешней сети. На самый крайний случай есть дежурные с KVM.

Логическая сеть


Чтобы понять, как устроена логическая сеть S3 хранилища DataLine, обратимся к еще одной схеме:

lpznubpzqosgkhzts8tm7sp0ssi.png
2. Схема логической сети хранилища

Как видно, логика сети состоит из нескольких сегментов.

Внешняя сеть (Q) общей ёмкостью 20G подсоединена напрямую к Provider Edge. Далее следуют Cisco 4500 и балансировщики.

Следующий логический блок (X) — VLAN между балансировщиками и рабочими нодами. Со стороны балансировщиков используется то же подключение, что и для входящего трафика. Рабочие ноды подключены через стек 3750 4-мя 1G линками (по два на каждый 3750). Все физические линки собраны в единый логический также с помощью LACP. Эта сеть используется только для обработки клиентского трафика.

Все соединения внутри кластера Cloudian (Y) идут через третий логический сегмент, построенный поверх 10G. Такая организация помогает избежать проблем на внешнем канале из-за внутреннего трафика и наоборот. Это чрезвычайно нагруженный и важный для работы кластера сегмент. Именно через него осуществляется репликация данных и метаданных, его используют любые процедуры перебалансировки и т.д., поэтому его «непотопляемость» мы выделили в отдельную задачу.

Немного красоты


Вот так выглядит всё в сборе:

_m_1sd2pvc2h5nbt2wco5bdkl4s.png
3. Сетевое оборудование и балансировщики анфас

xoq0e4outgmbcgswdzb4uzs4bsg.png
4. То же, вид сзади

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

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

uu8xtwvqpdcvw45xlugyfysq5is.png
5. Рабочие ноды

wlgn5gc7cttpbkra7cpmnza_pdo.png
6. Вид сзади

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

Whitelisting


В комментариях к прошлой статье я обещал подробнее рассказать об устройстве whitelisting.

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

Помните, на первой схеме была ветка на DIST«ы и Cloud? Кроме основного интернет-канала на 20Gb, мы используем агрегированный канал до свитчей, к которым подключаем всех клиентов на уровне ЦОД. Если клиент захочет прямой линк до хранилища, мы сможем настроить VLAN от клиента до наших 4500X c постройкой отдельной трассы (или без неё) и пустить L3. После этого на адреса клиента уже в самом Cloudian настраивается привязка к тарифному плану. Тогда для всех, кто подключен к этому тарифному плану, использование S3 с whitelisting-адресов  считаться не будет.

mrncyda-0oquwo4kpos3snsyp2e.png
7. А вот так выглядит специальный интерфейс в Cloudian.

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

История постройки


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

Экспериментируем с 10G


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

По устоявшейся традиции, прежде чем закупать новое вспомогательное оборудование, мы идем на склад и подбираем более-менее подходящие компоненты. Это позволяет быстро провести тесты и определиться с будущим списком покупок. Разумеется, пока мы не добиваемся надежного на все 100% результата, ничего не уходит на продуктив.

Так было и в этот раз. И если Cisco никаких сюрпризов не подкинули, то с балансировщиками нагрузки «жадность» нас едва не сгубила.

Опыт первый. Серверы Supermicro


Здесь нас подвело желание провести быстрый тест с минимальными затратами. На складе мы обнаружили серверы Supermicro, у которых было прекрасно всё, кроме отсутствия SFP-интерфейсов. Мы решили установить на них наши любимые Intel 520DA2 и тут же столкнулись с первой проблемой: машинки одноюнитовые, а райзеров нет. При этом, нашего корпуса в compatibility-листах почему-то не оказалось, а родных райзеров — очень много.

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

lfwxt6csco5ndrm--6qzy4kqfhi.png
8. Опытный образец №1

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

sptoaf-lv4w_imfhvnro9i12f1y.png
9. Вид сзади

Что из этого получилось, хорошо видно на скриншоте айперфа:

494311900ac9a09852f260ebbfb4e4b8.png
10. На самом деле это не скриншот :)

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

082bb26ac22d6de01f22f464b778314b.png
11. На первый взгляд, шпионских чипов здесь нет

Вспомнили курс физики: электромагнитные наводки, высокочастотные сигналы и т.д… Разумеется, продолжать эксперимент с таким количеством и качеством «колхоза» не имело смысла. Так что мы окончательно разобрали систему и вернули серверы на место.

Опыт второй. Citrix Netscaler MPX8005


В процессе возвращения серверов на место мы нашли новых героев: Citrix Netscaler MPX8005. Это замечательное брендовое железо, к тому же, практически не использованное. Выглядят они вот так:

dqv1vawcvfgpmmijwrie29ewkgy.png
12. Салазки в стойку не поместились по длине, но мы дальновидно решили отложить это на потом

Разместили оборудование в стойке, скоммутировали и настроили. Это действительно отличные «взрослые» железки, по 2 SFP-слота под 10GB на каждый, HA, продвинутые алгоритмы, есть даже L7. Правда, до 5 гигабит по лицензии, но мы всё равно использовали L3, а там этих лимитов нет.

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

show channel LA/1
 
1)  Interface LA/1 (802.3ad Link Aggregate) #10
  flags=0x4100c020 
  MTU=9000, native vlan=1, MAC=XXX, uptime 0h03m23s
  Requested: media NONE, speed AUTO, duplex NONE, fctl NONE,
                throughput 160000
  Link Redundancy Throughput 80000
  Actual: throughput 20000
  LLDP Mode: NONE
  RX: Pkts(9388) Bytes(557582) Errs(0) Drops(1225) Stalls(0)
  TX: Pkts(10514) Bytes(574232) Errs(0) Drops(0) Stalls(0)
  NIC: InDisc(0) OutDisc(0) Fctls(0) Stalls(0) Hangs(0) Muted(0)
  bandwidthHigh: 160000 Mbits/sec, bandwidthNormal: 160000 Mbits/sec.
  LA mode: AUTO
 
> show interface 10/1
 
1)  Interface 10/1 (10G Ethernet, unsupported fiber SFP+, 10 Gbit) #1
  flags=0x400c020 
  LACP 
  MTU=9000, MAC=XXX, uptime 0h05m44s
  Requested: media AUTO, speed AUTO, duplex AUTO, fctl OFF,
                throughput 0
  Actual: media FIBER, speed 10000, duplex FULL, fctl OFF, throughput 10000
  LLDP Mode: TRANSCEIVER,       LR Priority: 1024
 
  RX: Pkts(8921) Bytes(517626) Errs(0) Drops(585) Stalls(0)
  TX: Pkts(9884) Bytes(545408) Errs(0) Drops(3) Stalls(0)
  NIC: InDisc(0) OutDisc(0) Fctls(0) Stalls(0) Hangs(0) Muted(0)
  Bandwidth thresholds are not set.
 
> show interface 10/2
 
1)  Interface 10/2 (10G Ethernet, unsupported fiber SFP+, 10 Gbit) #0
  flags=0x400c020 
  LACP 
  MTU=9000, MAC=XXX, uptime 0h05m58s
  Requested: media AUTO, speed AUTO, duplex AUTO, fctl OFF,
                throughput 0
  Actual: media FIBER, speed 10000, duplex FULL, fctl OFF, throughput 10000
  LLDP Mode: TRANSCEIVER,       LR Priority: 1024
 
  RX: Pkts(8944) Bytes(530975) Errs(0) Drops(911) Stalls(0)
  TX: Pkts(10819) Bytes(785347) Errs(0) Drops(3) Stalls(0)
  NIC: InDisc(0) OutDisc(0) Fctls(0) Stalls(0) Hangs(0) Muted(0)
  Bandwidth thresholds are not set.

Мы использовали родные трансиверы Cisco, с которыми, по идее, никаких проблем возникнуть не должно. Даже оптику проверили и на всякий случай поменяли трансиверы — та же самая картина. Не едет наша машина, и всё тут! Смотрим внимательнее.

«Красивые» трансиверы Cisco:

ix1:  port 0xe000-0xe01f mem 0xf7800000-0xf781ffff,0xf7840000-0xf7843fff irq 17 at device 0.1 on pci1
ix1: ixgbe bus speed = 5.0Gbps and PCIe lane width = 8
SFP+/SFP, vendor CISCO-AVAGO , part number XXX , 10G 0x10 1G 0x00 CT 0x00
  *** Unsupported SFP+/SFP type!

Не определяются нормально трансиверы, unsupported же!

Пришлось найти самые-самые «родные»:

wi-iswj9672s8q0skvpw4s3s2xw.png
13. Самые родные трансиверы на диком западе

ix0:  port 0xe020-0xe03f mem 0xf7820000-0xf783ffff,0xf7844000-0xf7847fff irq 16 at device 0.0 on pci1
platform: Manufacturer Citrix Inc.
platform: NSMPX-8000-10G 4*CPU+6*E1K+2*IX+1*E1K+4*CVM 1620 675320 (28), manufactured at 8/10/2015
platform: serial 4NP602H7H0
platform: sysid 675320 - NSMPX-8000-10G 4*CPU+6*E1K+2*IX+1*E1K+4*CVM 1620
ix0: ixgbe bus speed = 5.0Gbps and PCIe lane width = 8
SFP+/SFP, vendor CITRIX                 , part number XXX   , 10G 0x10 1G 0x01 CT 0x00
ix0: [ITHREAD]
10/2: Ethernet address: 00:e0:ed:45:39:f8
ix1:  port 0xe000-0xe01f mem 0xf7800000-0xf781ffff,0xf7840000-0xf7843fff irq 17 at device 0.1 on pci1
ix1: ixgbe bus speed = 5.0Gbps and PCIe lane width = 8
SFP+/SFP, vendor CITRIX                 , part number XXX  , 10G 0x10 1G 0x01 CT 0x00

Эти трансиверы без проблем определились, но ситуацию это не спасло. Обновили прошивки — то же самое. Поддержка Citrix решила тактично отмолчаться (нет, не из-за родословной трансиверов).

Мы глубоко вздохнули и зарылись в аппаратные спецификации. Выяснилось, что ответ всё это время был у нас перед глазами: ixgbe bus speed = 5.0Gbps and PCIe lane width = 8. Это проблема с картой. Ей самой не хватает скорости PCIe. У наших Citrix максимальная производительность самого PCI-e слота под карту с трансиверами составляет 5.0Gbps, о чем он нам и кричал все это время. Как Citrix на MPX8015 (аппаратно он точно такой же!) 15 гигабит выдавать хотели, не понятно. Зато мы поняли, почему такие «классные» балансировщики всё это время лежали на складе. Работать корректно с 10G линками они не могут в принципе.

Опыт последний. Используем правильное железо и делаем красиво


Здесь наше терпение закончилось вместе с верой в человечество, и пришлось применять технологию «отжайл», чтобы добыть нормальное железо в виде HP ProLiant DL360 G9 с фотографий выше. Они сюрпризов нам устраивать не стали, качают 10G и не жалуются. :)

Нагрузочное тестирование


Поскольку мы не приемлем подход «hujak-hujak — и в продакшен», да и знаем по опыту, что не протестированная система после сборки почти со 100% гарантией окажется неработоспособной, мы решили провести нагрузочное тестирование. К тому же, с его помощью можно сделать некоторый тюнинг на будущее.

Для генерации нагрузки был выбран привычный инструмент — Apache Jmetr. Он сам по себе весьма неплох, как я уже писал пару статей назад, и это одно из наиболее гибких решений на рынке, даже несмотря на то, как Java любит кушать. Для работы с S3 мы использовали самописный модуль с использованием AWS SDK, также на Java. В тестах нам удалось добиться скорости в 12,5 Гбит на запись для файлов более 250 мегабайт при параллельной загрузке чанками в 5 мегабайт, и для файлов менее 5 мегабайт — обработки примерно 3000 HTTP запросов в секунду. При параллельном запуске обоих тестов получилось около 11 Гигабит и 2200 запросов в секунду. При этом есть возможность улучшения работы при смешанной нагрузке и с мелкими объектами. Мы «уткнулись» в CPU, а второй сокет у нас свободен. На генераторе нагрузки тестовые файлы брались из оперативной памяти, чтобы исключить влияние на результаты дисковой подсистемы самого генератора. Для проведения тестов, помня о любви Java к оперативной памяти и необходимости работы с большим количеством потоков при параллельной загрузке, в качестве генератора мы использовали сервер HP DL980 g7. Это восьмиюнитовый сервер с 8 процессорами Intel E7- 4870 и 512Gb оперативной памяти на борту.

Внутри команды к нему прилепилась ласковая кличка Бегемотик.

ylefwbgvc4ypecxwot1jtcr7yrc.png
14. Наш бегемотик. Правда, чем-то похож?

b8qlan70ud31dkucw7dt252sbxi.png
15. Вид сзади. Страшные кабели внизу в центре — это кроссконнект внутренней межмостовой шины

6cxeniwbbzfcuh7e06brn-ko7pe.png
16. Так выглядит одна из двух голов сервера. В каждой установлено по 4 процессора и 16 планок по 16 гигабайт оперативной памяти

wxvtp91ap3cdeu0y0kmn9komqwo.png
17. Чтобы комфортно использовать Htop в консоли такого сервера, нужен большой монитор :)

На практике смешанный тест заметно нагрузил даже такой мощный сервер.
Чтобы прийти к полученным результатам производительности, нам пришлось перевести внутреннюю сеть кластера на 9k jumbo frame«ы и слегка тюнинговать сетевой стек балансировщиков и рабочих нод (мы используем CentOS Linux), а также оптимизировать ряд других параметров ядра на рабочих нодах:  

cat /etc/sysctl.conf
…
 
kernel.printk = 3 4 1 7
read_ahead_kb = 1024
write_expire = 250
read_expire = 250
fifo_batch = 128
front_merges = 0
net.core.wmem_default = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 16777216
net.core.rmem_max = 16777216
net.core.somaxconn = 5120
net.core.netdev_max_backlog = 50000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_max_syn_backlog = 30000
net.ipv4.tcp_max_tw_buckets = 2000000
fs.file-max = 196608
vm.overcommit_memory = 1
vm.overcommit_ratio = 100
vm.max_map_count = 65536
vm.dirty_ratio = 40
vm.dirty_background_ratio = 5
vm.dirty_expire_centisecs = 100
vm.dirty_writeback_centisecs = 100
net.ipv4.tcp_fin_timeout=10
net.ipv4.tcp_congestion_control=htcp
net.ipv4.netfilter.ip_conntrack_max=1048576
net.core.rmem_default=65536
net.core.wmem_default=65536
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.ip_local_port_range=1024 65535

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

Cisco C3750 + LACP = pain
Еще один подводный камень в сетевой производительности — балансировка нагрузки при использовании LACP/LAGp. К сожалению, Cisco 3750 не умеют балансировать нагрузку по портам, только по адресам источника и назначения. Чтобы добиться корректной балансировки трафика, пришлось навесить по 12 IP адресов на bond-интерфейсы рабочих нод, «смотрящих» в сторону клиентов. Условно, по 3 на каждый физический линк. При такой конфигурации можно было обойтись вообще без LACP на «внешних» интерфейсах рабочих нод, так как все адреса указаны в конфиге Nginx, но тогда при потере линка мы бы автоматически снижали вес ноды в балансировке. При «отвале» линка LACP позволяет сохранить полную доступность по всем адресам.

bond0.10  Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
                RX packets:2390824140 errors:0 dropped:0 overruns:0 frame:0
                TX packets:947068357 errors:0 dropped:0 overruns:0 carrier:0
                collisions:0 txqueuelen:0
                RX bytes:18794424755066 (17.0 TiB)  TX bytes:246433289523 (229.5 GiB)
 
bond0.10:0 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX  Bcast:192.168.XX Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:1 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:2 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:3 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX  Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:4 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:5 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX  Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:6 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX  Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:7 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX  Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:8 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX  Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:9 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX Bcast:192.168.XXMask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1
 
bond0.10:10 Link encap:Ethernet  HWaddr XXX
                inet addr:192.168.XX  Bcast:192.168.XX  Mask:255.255.255.0
                UP BROADCAST RUNNING MULTICAST  MTU:9000  Metric:1

Функциональное тестирование


Уже закончив работу над хранилищем, мы познакомились с сервисом flexify.io. Они помогают облегчить миграцию между различными объектными хранилищами. Но чтобы стать партнером Flexify, необходимо пройти серьезные тесты. «А почему бы и нет?» — подумали мы. Стороннее тестирование — это всегда полезный опыт.

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

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

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

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

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

Реализованные тесты для объектов

GET Object request with no optional parameters
GET Object request multithread
GET Object request to an encrypted object with provided sse parameters
GET Object request to an encrypted object with no provided sse parameters
GET Object request with range that intersects file«s bytes range
GET Object request with range out of range of file’s bytes range
GET Object request with a suffix range parameter
GET Object request with a suffix range parameter out of range of file’s bytes range
GET Object request with invalid range parameter
Head Object request to an existing object
Head Object request to a recently deleted object
Head Object request with a Key that was never existed in a Bucket
Head Object request to an encrypted object with provided sse parameters
Head Object request to an encrypted object with no provided sse parameters
List Objects request
List Objects v2 request
List Objects request with provided Marker parameter
List Objects request with provided Prefix parameter
List Objects request with provided Marker and Prefix parameters
Receive all objects on endpoint with List Objects with provided Marker and Prefix parameters
List Objects request with skipped Delimiter parameter
List Objects request with passed Marker parameter, but with skipped Delimiter parameter
List Objects request with passed non-existing Prefix
List Objects request with passed non-existing Marker
Multipart upload with native upload_file () method
Multipart upload with native upload_fileobj () method
Multipart upload with custom method
Stopping multipart upload with abort_multipart_upload () method
Performing abort_multipart_upload () method with incorrect uploadId
Performing abort_multipart_upload () method with incorrect Key and uploadId
Multipart upload of 2 files with a same key simultaneously. 2nd file uploaded before 1st
Multipart upload of 2 files with a same key simultaneously. 1st file uploaded before 2nd
Multipart upload of 2 files with a different keys simultaneously. 1st file uploaded before 2nd
Multipart upload with a part size of 512kb
Multipart upload with a part size larger than maximum allowed size
Multipart upload of a file with parts of different size
List multipart upload request
PUT Object ACL request to an object with provided grantee id
GET Object ACL request to an object with granted additional access permissions
PUT Object Tagging method
GET Object Tagging method
DELETE Object Tagging method
PUT Object request with no optional parameters
PUT Object requests multithread
PUT Object requests with passed optional encryption parameters
PUT Object requests with passed empty Body parameter
GET Object with native download_file () method
GET Object with native download_fileobj () method
GET Object with custom method using ranges
GET Object with prefix with native download_file () method
GET Object with prefix with native download_fileobj () method
GET Object with prefix with custom method using ranges
DELETE Object request to an existing object
DELETE Object request to an not existing object
DELETE Objects request to a group with existing objects

Реализованные тесты для бакетов

PUT Bucket Encryption
GET Bucket Encryption
DELETE Bucket Encryption
PUT Bucket Policy request
GET Bucket Policy request to a bucket with Policy
DELETE Bucket Policy request to a bucket with Policy
GET Bucket Policy request to a bucket with no Policy
DELETE Bucket Policy request to a bucket with no Policy
PUT Bucket Tagging
GET Bucket Tagging
DELETE Bucket Tagging
Create bucket request with existing bucket name
Create bucket request with unique bucket name
Delete bucket request with existing bucket name
Delete bucket request with unique bucket name
PUT Bucket ACL request to a bucket with provided grantee id
GET Object ACL request to an object with granted additional access permissions


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

Провалился аплоад с ключами, содержащими:

  • U+0000-U+001F — первые 32 нечитаемых контрольных символа. На Amazon, к примеру, напрямую не заливается только первый U+0000.


  • А также U+18D7C, U+18DA8, U+18DB4, U+18DBA, U+18DC4, U+18DCE. Это тоже нечитаемые символы, но Amazon их принимает в качестве ключей. Со всеми остальными символами проблем не возникло.


При чтении содержимого бакета возникает проблема на 66,675 ключе, который содержит символ U+FFFE. Получить полный список ключей в бакете, содержащем объект с таким ключом, не получается.

В остальном тесты прошли успешно, и в конце сентября мы появились в списке доступных поставщиков!

Небольшое послесловие и бонус для читателей


Ранее я писал, что Cloudian HyperStore, не смотря на свои многочисленные преимущества, практически не освещен в русскоговорящем сегменте интернета.

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

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

Те из вас, кому захотелось пощупать ручками то, о чем мы говорим уже 2 статьи подряд, могут воспользоваться формой обратной связи на этой страничке и лично выяснить, в чем соль. Стандартно мы даем 15Gb на 2 недели бесплатно, естественно, с пользовательским доступом. Если у вас возникнет желание поделиться впечатлениями от работы с хранилищем, пишите мне в личку. :)

А для тех, кому 15 Gb на 2 недели мало, у нас есть небольшой квест! На фотографиях в статье мы разместили трёх бегемотиков. Первые 50 человек, которые их найдут, получат 30Gb на 4 недели. Чтобы получить увеличенный тест, напишите в комментариях номера картинок, где спрятались бегемотики, и подайте заявку по ссылке выше. Не забудьте в заявке указать ссылку на свой комментарий.

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

© Habrahabr.ru