company_banner

Состояние и производительность решений для постоянного хранения данных в Kubernetes

Автор оригинала: Bruno Cabral
  • Перевод
Прим. перев.: хотя этот обзор не претендует на статус тщательно проработанного технического сравнения существующих решений для постоянного хранения данных в Kubernetes, он может стать хорошей отправной точкой для администраторов, которым актуален данный вопрос. Наибольшего внимания здесь удостоилось решение Piraeus, знакомство с которым пойдет на пользу не только любителям Linstor, но и тем, кто об этих проектах ещё не слышал.



Это ненаучный обзор решений для хранения данных для Kubernetes. Постановка задачи: требуется возможность создания Persistent Volume на дисках узла, данные которого будут сохранны в случае повреждения или перезапуска узла.

Мотивация для проведения этого сравнения — потребность миграции серверного парка компании со множества выделенных bare metal-серверов в кластер Kubernetes.

Моя компания — стартап Escavador из Бразилии с огромными потребностями в вычислительной мощности (преимущественно в CPU) и весьма ограниченным бюджетом. Мы разрабатываем решения в области NLP для структурирования юридических данных.


Из-за кризиса с COVID-19 бразильский реал подешевел до рекордно низкого уровня по отношению к доллару США

Наша национальная валюта на самом деле очень недооценена, поэтому средняя зарплата старшего разработчика составляет всего 2000 USD в месяц. Таким образом, мы не можем позволить себе роскошь тратить значительные средства на облачные сервисы. Когда я проводил расчеты в последний раз, [благодаря использованию своих серверов] мы экономили 75 % в сравнении с тем, что пришлось бы заплатить за AWS. Другими словами, на сэкономленные деньги можно нанять еще одного разработчика — думаю, что это гораздо более рациональное использование средств.

Вдохновленный серией публикаций от Vito Botta, я решил создать кластер K8s с помощью Rancher (и с ним пока всё хорошо…). Vito также провел отличный анализ различных решений для хранения. Явным победителем оказался Linstor (он даже выделил его в особую лигу). Спойлер: я с ним согласен.

В течение некоторого времени я слежу за движением вокруг Kubernetes, но только недавно решил поучаствовать в нем. Связано это в первую очередь с тем, что у используемого провайдера появилась новая линейка процессоров Ryzen. И тогда я сильно удивился, увидев, что многие решения до сих пор находятся в разработке или незрелом состоянии (особенно это касается кластеров на bare metal: виртуализация VM, MetalLB и т.д.). Хранилища на bare metal всё ещё пребывают в стадии созревания, хоть и представлены множеством коммерческих и Open Source-решений. Я решил сравнить основные перспективные и бесплатные решения (попутно протестировав один коммерческий продукт, чтобы понять, чего лишаюсь).


Спектр решений для хранения в CNCF Landscape

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

Для экспериментов использовались 4 worker'a со следующей конфигурацией: процессор Ryzen 3700X, 64 GB памяти ECC, NVMe размером 2 TB. Бенчмарки делались с помощью образа sotoaster/dbench:latest (на fio) с флагом O_DIRECT.

Longhorn


  • Лицензия: Apache 2
  • Коммерческая поддержка: Rancher
  • URL: github.com/longhorn/longhorn
  • Звезды на GitHub: 1,3 тыс.

Longhorn мне очень понравился. Он полностью интегрирован с Rancher и установить его через Helm можно одним кликом.


Установка Longhorn из Rancher

Это инструмент с открытым исходным кодом и статусом sandbox-проекта от Cloud Native Computing Foundation (CNCF). Его разработку финансирует Rancher — довольно успешная компания с известным [одноименным] продуктом.



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

При тестировании я запустил бенчмарк с использованием 2 реплик и Longhorn 0.8.0:

  • Случайное чтение/запись, IOPS: 28.2k / 16.2k;
  • Пропускная способность чтения/записи: 205 Мб/с / 108 Мб/с;
  • Средняя задержка чтения/записи (usec): 593.27 / 644.27;
  • Последовательное чтение/запись: 201 Мб/с / 108 Мб/с;
  • Смешанное случайное чтение/запись, IOPS: 14.7k / 4904.

OpenEBS


  • Лицензия: Apache 2
  • Коммерческая поддержка: несколько компаний(?); mayadata.io представляется самой большой
  • URL: github.com/openebs/openebs
  • Звезды на GitHub: 6 тыс.

Этот проект также имеет статус sandbox от CNCF. С большим числом звезд на GitHub он выглядит вполне перспективным решением. В своем обзоре Vito Botta пожаловался на недостаточную производительность. Вот что ему на это ответил гендиректор Mayadata:

Информация сильно устарела. OpenEBS раньше поддерживал 3, а сейчас поддерживает 4 движка, если включить динамическое обеспечение и оркестрацию localPV, которая может работать на скоростях NVMe. Вдобавок, движок MayaStor теперь открыт и уже получает положительные отзывы (хотя и имеет альфа-статус).

На странице проекта OpenEBS есть такое пояснение по его статусу:

OpenEBS — одна из наиболее широко используемых и проверенных инфраструктур для хранения данных под Kubernetes. OpenEBS приобрела статус sandbox-проекта CNCF в мае 2019-го и является первой и единственной системой хранения, обеспечивающей согласованный набор программно-определяемых возможностей на различных бэкендах (local, nfs, zfs, nvme) как в on-premise, так и в облачных системах. OpenEBS первой открыла свой фреймворк для хаос-инжиниринга под stateful-нагрузки — Litmus Project, — который позволяет сообществу автоматически проверять на готовность ежемесячные обновления OpenEBS. Корпоративные клиенты используют OpenEBS в production с 2018 года; еженедельно выполняется более 2,5 млн docker pull'ов.

У него есть множество движков, и последний из них представляется довольно перспективным в плане производительности: «MayaStor — alpha engine with NVMe over Fabrics». Увы, я не стал его тестировать из-за статуса альфа-версии.

В тестах же использовалась версия 1.8.0 на движке jiva. Кроме того, ранее я проверял и cStor, но не сохранял результаты, которые, впрочем, оказались чуть медленнее jiva. Для бенчмарка был установлен Helm-чарт со всеми настройками по умолчанию и использовался Storage Class, стандартно созданный Helm'ом (openebs-jiva-default). Производительность оказалась самой плохой из всех рассматриваемых решений (буду признателен за советы по ее повышению).

OpenEBS 1.8.0 с движком jiva (3 реплики?):

  • Случайное чтение/запись, IOPS: 2182 / 1527;
  • Пропускная способность чтения/записи: 65.0 Мб/с / 41.9 Мб/с;
  • Средняя задержка чтения/записи (usec): 1825.49 / 2612.87;
  • Последовательное чтение/запись: 95.5 Мб/с / 37.8 Мб/с;
  • Смешанное случайное чтение/запись, IOPS: 2607 / 856.

Дополнение от переводчика. Эти результаты прокомментировал Evan Powell, возглавляющий проект OpenEBS (также он известен тем, что ранее основал StackStorm и Nexenta):

Спасибо за проделанную работу, Bruno! Мы немного не согласны с выводами по сравнению OpenEBS с альтернативами. Был использован движок Jiva, который в основном применяется на ARM или схожих конфигурациях для минимального overhead'а и простоты. Клиенты же вроде Bloomberg предпочитают работать с DynamicLocal PV от OpenEBS. Такой же подход рекомендуется ребятами вроде Elastic и для других рабочих нагрузок, требующих отказоустойчивости. К слову, всеми движками можно управлять всегда бывшим бесплатным OpenEBS Director (https://account.mayadata.io/signup). В любом случае — спасибо за обзор и надеюсь, что мы останемся на связи.

StorageOS



Это коммерческое решение, которое бесплатно при использовании до 110 ГБ пространства. Бесплатную лицензию (Developer license) можно получить, зарегистрировавшись через пользовательский интерфейс продукта; она дает до 500 ГБ пространства. В Rancher'е оно значится как партнерское, поэтому установка с помощью Helm'а прошла легко и беззаботно.

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

В тесте задействован имеющийся Storage Class под названием «Fast» (Template 0.2.19, 1 Master + 0 Replica?). Результаты поразили. Они значительно превзошли предыдущие решения.

  • Случайное чтение/запись, IOPS: 117k / 90.4k;
  • Пропускная способность чтения/записи: 2124 Мб/с / 457 Мб/с;
  • Средняя задержка чтения/записи (usec): 63.44 / 86.52;
  • Последовательное чтение/запись: 1907 Мб/с / 448 Мб/с;
  • Смешанное случайное чтение/запись, IOPS: 81.9k / 27.3k.

Piraeus (основан на Linstor)


Лицензия: GPLv3

Уже упомянутый Vito Botta в конечном итоге остановился именно на Linstor, что стало дополнительным поводом попробовать это решение. На первый взгляд, проект выглядит довольно странно. Почти нет звезд на GitHub, необычное название и его даже нет на CNCF Landscape. Но при ближайшем рассмотрении все оказывается не так страшно, поскольку:

  • В качестве базового механизма репликации используется DRBD (на самом деле, он разработан теми же людьми). При этом DRBD 8.x уже более 10 лет входит в состав официального ядра Linux. И мы говорим о технологии, которая оттачивается более 20 лет.
  • Носителями управляет LINSTOR — также зрелая технология от той же компании. Первая версия Linstor-server появилась на GitHub в феврале 2018-го. Она совместима с различными технологиями/системами, такими как Proxmox, OpenNebula и OpenStack.
  • По всей видимости, Linbit активно развивает проект, постоянно внедряет в него новые функции и улучшения. 10-я версия DRBD пока имеет альфа-статус, но уже может похвастаться некоторыми уникальными возможностями, такими как erasure coding (аналог функциональности из RAID5/6 — прим. перев.).
  • Компания предпринимает определенные меры, чтобы попасть в число проектов CNCF.

Окей, проект выглядит достаточно убедительно, чтобы доверить ему свои драгоценные данные. Но способен ли он переиграть альтернативы? Давайте посмотрим.

Установка


Vito рассказывает об установке Linstor здесь. Однако в комментариях один из разработчиков Linstor рекомендует новый проект под названием Piraeus. Насколько я понял, Piraeus становится Open Source-проектом Linbit, который объединяет в себе всё связанное с K8s. Команда работает над соответствующим оператором, а пока Piraeus можно установить с помощью этого YAML-файла:

kubectl apply -f https://raw.githubusercontent.com/bratao/piraeus/master/deploy/all.yaml

Внимание! Вы забираете конфиги из моего личного репозитория. Проверьте официальный репозиторий! Я обновил версии образов, чтобы решить ошибку, возникающую при использовании в Ubuntu.

Официальный репозиторий Piraeus доступен здесь.

Также можно воспользоваться репозиторием от kvaps (он кажется даже более динамичным, чем официальный репозиторий piraeus): https://github.com/kvaps/kube-linstor (пользуясь случаем, передаем привет Андрею kvaps — прим. перев.).


Все узлы работают после установки

Администрирование


Администрирование осуществляется с помощью командной строки. Доступ к ней возможен из командной оболочки узла piraeus-controller.



На controller-узле запущен linstor-server. Он представляет собой слой абстракции над drbd, способный управлять всем парком узлов. На скриншоте ниже приведены некоторые полезные команды для наиболее востребованных задач, например:

  • linstor node list — вывести список подключенных узлов и их статус;
  • linstor volume list — показать список созданных томов и их местоположение;
  • linstor node info — показать возможности каждого узла.


Команды Linstor

Полный список команд доступен в официальной документации: User´s Guide LINSTOR.

В случае возникновения ситуаций вроде split brain доступ к drbd можно получить непосредственно через узлы.

Восстановление после сбоев


Я изо всех сил старался уронить свой кластер, в том числе делал hard reset'ы на узлах. Но linstor оказался удивительно живуч.

Drbd отлично распознает проблему, называемую split brain. В моей ситуации вторичный узел выпал из репликации.

Split brain — это ситуация, когда из-за временного сбоя сетевых подключений между узлами кластера, вмешательства ПО для управления кластером или из-за человеческой ошибки оба узла становятся Primary, находясь в «оторванном» состоянии. Опасность этого состояния в том, что измененные данные на любом из узлов не будут реплицированы на другой. Другими словами, могут возникнуть два расходящихся набора данных, которые невозможно объединить тривиальным образом.

Split brain в DRBD отличается от кластерного, который означает потерю связности хостов, управляемых распределенным ПО для управления кластером вроде Heartbeat.

Подробности можно почерпнуть из официальной документации drbd.


Вторичный узел выпал из репликации

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

Мне понадобилось зайти в консоль на проблемном узле piraues (им был worker2-gpu):


Заходим на узел

Там я установил drdbtop. Скачать эту утилиту можно здесь:

wget https://github.com/LINBIT/drbdtop/releases/download/v0.2.2/drbdtop-linux-amd64
chmod +x drbdtop-linux-amd64
./drbdtop-linux-amd64


Работающая утилита drbdtop

Взгляните на нижнюю панель. На ней расположены команды, с помощью которых можно исправить split brain:



После это узлы подключаются и синхронизируются автоматически.

Как повысить скорость?


По умолчанию Piraeus/Linstor/drbd демонстрируют отличную производительность (в этом вы можно убедиться ниже). Настройки по умолчанию разумны и безопасны. Однако скорость записи оказалась слабовата. Поскольку серверы в моем случае разбросаны по разным ЦОД (хотя и физически они находятся сравнительно недалеко), я решил попробовать подстроить их производительность.

Отправной пункт оптимизации — определение протокола репликации. По умолчанию используется Protocol C, предусматривающий ожидание подтверждения записи на удаленном вторичном узле. Ниже приведено описание возможных протоколов:

  • Protocol A — протокол асинхронной репликации. Локальные операции записи на первичном узле считаются завершенными, как только произошла запись на локальный диск, а репликационный пакет был помещен в локальный TCP-буфер на отправку. Важный нюанс заключается в том, что буфер отправки TCP ОЧЕНЬ мал. Его можно увеличить до определенного предела.
  • Protocol B — протокол полусинхронной репликации. Локальные операции записи на первичном узле считаются завершенными, как только произошла запись на локальный диск, а репликационный пакет дошел до другого узла.
  • Protocol C (по умолчанию) — протокол синхронной репликации. Локальная операция на первичном узле считается завершенной только после подтверждения записи на локальный и удаленный диски.

Из-за этого в Linstor я также использую асинхронный протокол (он поддерживает синхронную/полусинхронную/асинхронную репликацию). Включить его можно следующей командой:

linstor c drbd-options --protocol A --after-sb-0pri=discard-zero-changes  --after-sb-1pri=discard-secondary  --after-sb-2pri=disconnect --max-buffers 131072 --sndbuf-size 1085760 --rcvbuf-size 1085760 --c-max-rate 4194304 --c-fill-target 1048576

Результатом ее выполнения станет активация асинхронного протокола и увеличение буфера до 1 Мб. Это относительно безопасно. Или можно использовать следующую команду (она игнорирует сбросы на диск и значительно увеличивает буфер):

linstor c drbd-options --protocol A --after-sb-0pri=discard-zero-changes  --after-sb-1pri=discard-secondary  --after-sb-2pri=disconnect --max-buffers 131072 --sndbuf-size 10485760 --rcvbuf-size 10485760 --disk-barrier no --disk-flushes no --c-max-rate 4194304 --c-fill-target 1048576

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


Во время активной записи узел временно получил статус outdated при использовании протокола ASYNC

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


Все бенчмарки проводились с использованием следующей Job:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
 name: dbench
spec:
 storageClassName:  STORAGE_CLASS
 accessModes:
   - ReadWriteOnce
 resources:
   requests:
     storage: 5Gi
---
apiVersion: batch/v1
kind: Job
metadata:
 name: dbench
spec:
 template:
   spec:
     containers:
     - name: dbench
       image: sotoaster/dbench:latest
       imagePullPolicy: IfNotPresent
       env:
         - name: DBENCH_MOUNTPOINT
           value: /data
         - name: FIO_SIZE
           value: 1G
       volumeMounts:
       - name: dbench-pv
         mountPath: /data
     restartPolicy: Never
     volumes:
     - name: dbench-pv
       persistentVolumeClaim:
         claimName: dbench
 backoffLimit: 4

Задержка между машинами составляет: ttl=61 time=0.211 ms. Измеренная пропускная способность между ними составила 943 Мбит/с. Все узлы работают под управлением Ubuntu 18.04.


Результаты (таблица на sheetsu.com)

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

Выводы


Я провел простое и, возможно, не слишком корректное сравнение некоторых решений для хранения в Kubernetes.

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

Уже некоторое время я использую Linstor/Piraeus в production-средах некоторых проектов. До сих пор все было отлично: диски создавались и удалялись, узлы перезапускались без простоев…

По моему мнению, Piraeus вполне готов к использованию в production, но нуждается в доработке. О некоторых багах написал в канал проекта в Slack'e, но в ответ мне только посоветовали подучить Kubernetes (и это правильно, поскольку я еще плохо в нем разбираюсь). После небольшой переписки мне все же удалось убедить авторов, что в их init-скрипте есть баг. Вчера, после обновления ядра и перезагрузки, узел отказался загружаться. Оказалось, что компиляция скрипта, который интегрирует модуль drbd в ядро, завершилась неудачно. Проблему решил откат к предыдущей версии ядра.

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

Если я сделал что-то не так, если что-то можно улучшить или вам требуется помощь, обращайтесь ко мне в Twitter или на GitHub.

P.S. от переводчика


Читайте также в нашем блоге:

Флант
DevOps-as-a-Service, Kubernetes, обслуживание 24×7

Комментарии 5

    +2

    За все не скажу, но вот longhorn мне не понравился — постоянно отваливаются реплики, вечное выпадание в I/O error после непонятно чего (фиксится только перезапуском пода), томы кушают место просто потому что (какие-то старые реплики, которые никем не используются, но и не удаляются).


    OpenEBS, в котором движок jiva использует наработки longhorn, работает куда стабильнее и по моим тестам быстрее самого longhorn, уж не знаю как, настройки плюс-минус одинаковые — три реплики на том на трёх разных серверах.

      +2
      Всегда рассматривают скорость, но забывают про другие факторы.

      Например, в Longhorn нет возможности освободить диск. Создали volume — заполнили, удалили все, а реальное использование диска на хосте не поменялось.

      Кроме как пересоздать volume освободить неиспользуемое место нельзя.
      По мне так это огромный минус и он очень сильно ужимает области использования Longhorn.

      P.S. Из-за этого вообще не представляю реальные кейсы его использования.
        +2
        Хм, а где же Rook из инкубатора?
        Я после перебора всех вариантов остановился на нем по нескольким причинам:
        1. Под капотом Ceph. Он конечно страшный, но развивается черт знает сколько лет и производительность у него неплохая.
        2. Легко ставится, в целом нормально работает.
        3. Следствие ceph-а — отказоустойчивость нормальная, если не экономить на репликах. Есть erasure, что в некоторых кейсах полезно.
        4. Прицепом получаешь еще и object storage, что тоже полезно.
        Минусы конечно тоже есть, но лично для меня плюсы перевесили. Сравнивал с EBS+Jiva и Longhorn. В моей конфигурации они были сильно медленнее. Очень сильно медленнее.

        P.S. Позабавило весьма высказывание про OpenEBS и DynamicLocal PV. Веселая часть в том, что это фактически не является «системой постоянного хранения данных в кластере», потому что это «альтернатива локальному диску с более удобным в некоторых кейсах провиженом». Сравнивать же производительность локального и сетевого диска (если это конечно не NVMe-oF какой-нибудь) — затея несколько странная. Не говоря уже о том, что никакой речи о миграции подобных дисков между машинами не идет и по сути полнофункциональный аналог облачных дисков вроде EBS не дает.

        P.P.S. Я понимаю что это перевод, но уровень проведения теста по сути не позволяет ответить нормально ни на вопрос проивзодительности в реальных кейсах, ни про надежность. В целом, «я что-то мерил и у меня что-то получилось». Объем записи в разы меньше объема оперативной памяти, тесты проводятся прямо на storage-ноде, что не дает понимания как оно себя будет вести, если обе реплики будут находиться на другой машине и так далее, вплоть до вывода «победила схема с асинхронной репликацией и отложенной записью», что конечно вполне ожидаемо, вот только отказоустойчивость такой схемы более чем сомнительна.
          +4
          С распределенным block-storage на bare-metal вообще в целом все печально, кубернетис тут разве что чуть своих проблем подкидывает. Странно, что в сравнении нет glusterfs и ceph. Оба вполне себе интегрируются в кубер и будут более зрелыми, чем все перечисленные вместе взятые наверное. А так, в итоге все равно непонятно, чему из этого всего можно довериться. Даже glusterfs казалось бы, а проблем от него огребли выше крыши и забыли как страшный сон.

          Это конечно красиво и удобно, когда можно поднять общий block-storage на куче машин и скейлить его бесконечно, но по всем признакам оно работает довольно условно и требует кучи усилий для этого. Либо для этого требуется покупать что-то дорогое и закрытое. Как-то светлое будущее распределенных открытых файловых хранилищ все никак не наступит.

          В итоге мне видится более удачным подходом выносить проблемы и сложности надежности хранения на уровень приложений, где это более менее давно решено. Требуется поднять PostgreSQL? Ставим stolon, маунтим на local volume прямо на хостах. Отвалится хост или его диск — подхватит реплика с другого хоста. Надо Cassandra? Тоже самое, все средства надежности встроены. Надо что-то свое хранить? Тут можно попробовать натянуть на объектные хранилища. На картинке выше в списке решений вон minio есть — пока очень хорошо справляется. Чрезвычайно быстрый и простой (практически линейно скейлится с числом дисков по тестам). Максимально все на него перетащили, что совместимо, и пока устраивает.

            0
            Кстати, тем, кто заинтересовался Piraeus/Linstor — на днях у них будет вебинар на платформе CNCF: «Update on and Demo of Piraeus Datastore (LINSTOR)» — May 27th; 10:00-11:00 AM PT (UTC-7).

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое