- Вопрос или проблема
- Предыстория
- Проблема
- Обходные решения и причины их отклонения
- Ожидаемое решение
- Редактировать: Результаты тестов
- Результаты – Пропускная способность (MiB/s)
- IOPS
- Задержка
- Выводы:
- Ответ или решение
- Вопрос о локальных вариантах хранения для Kubernetes в домашней лаборатории
- Теория
- Пример
- Применение
Вопрос или проблема
Я думаю, у меня проблема XY, если вы можете определить её как таковую, пожалуйста, ответьте соответствующим образом!
Предыстория
Моя главная цель — изучение Kubernetes, а второстепенная цель — домашние лабораторные эксперименты — хостинг различных небольших сервисов для кого-то, кто должен больше времени проводить на улице. У меня есть кластер coolberetes homelab, работающий на K3S, несколько рабочих узлов, управляющий узел, работающий на «картофельном» кластер-менеджере, и QNAP NAS для хранения.
На QNAP установлено 8 дисков объемом 12 ТБ с 7200 об/мин в конфигурации RAID-6. Он отлично подходит для поддерживаемых передач, но случайный ввод-вывод приводит его в ступор. Это ожидаемо из-за режима работы и аппаратного обеспечения. QNAP подключён к 10-гигабитному коммутатору, с портами 2.5/1 гигабит к рабочим узлам, так что пропускной способности не так много, но я думаю, что этого будет достаточно для моих нужд. У каждого узла есть локальный NVMe диск на 1 ТБ, что, как я думаю, будет важно позже.
Проблема
Некоторые из контейнеров, которые я запускаю, являются приложениями, которые я не разрабатывал, и поэтому не могу легко изменить выбор разработчика. Пожалуйста, имейте это в виду.
Большинство контейнеров разделены на два “класса” томов: data
, config
. Тома data
— это большие объемные файлы с последовательным доступом. Их я обрабатываю через NFS/SMB тома, и это работает нормально. Тома config
включают такие вещи, как несколько YAML-файлов, один-два JSON-файла, некоторые папки журналов, база данных SQLite и т. д. Эти тома работают гораздо хуже при монтировании через NFS, а базы данных SQLite полностью выходят из строя из-за проблем с блокировкой.
Обходные решения и причины их отклонения
- “Поместите тома config на NFS” — SQLite вызывает сбои из-за ошибок блокировки. Это v3 и v4.
- “Прекратите использовать SQLite” — Софт в образах жестко запрограммирован на его использование. Переписывание кода невозможно.
- “Просто поместите эти тома config на локальный диск” — как чисто локальные тома позволяют мне мигрировать или масштабировать любые сервисы?
- “Поместите кеши на NAS” — QNAP не позволяет добавлять кеши записи по глупым причинам.
- “Используйте rsync для синхронизации тома” — да, это было сделано, сработало “неплохо”, но я сомневаюсь, что это официальное решение.
Ожидаемое решение
Здесь, как мне кажется, находится моя проблема XY, или, по крайней мере, полное отсутствие знаний. Я ожидаю, что существует способ воспользоваться 1ТБ NVMe дисками на каждом рабочем узле, с блочным хранилищем, экспортируемым через NAS, в виде распределенной или кластерной файловой системы. Я бы ожидал, что могу смонтировать эту распределенную/кластерную файловую систему локально, чтобы контейнеры работали с ней, и в фоновом режиме она будет синхронизироваться среди работающих узлов и обратно на QNAP для резервного копирования. Для моих целей файловая система на 1 TiB подойдет для моих нужд в config
томах.
Если такое решение существует, как оно называется и где я могу узнать больше?
Если это неправильное решение, то какое “правильное”?
Вы определенно хотите распределенное решение для хранения, предназначенное для развертывания в кластере. Я на самом деле в процессе настройки чего-то подобного с Longhorn. Longhorn стал естественным выбором для меня, потому что я использую K3s, который (как продукт Rancher) имеет встроенную интеграцию с Longhorn, но его можно интегрировать с любой дистрибуцией Kubernetes с небольшой доработкой.
Отказ от ответственности: Я еще не настроил это, но я провел все исследования и готов осуществить это, как только у меня будет несколько часов свободного времени. Насколько я понимаю, Longhorn будет управлять репликацией и синхронизацией физических данных в точности так, как вы описали, и поддерживает NFS/SMB как целевой бэкап.
Единственное, что меня беспокоит в этой настройке, — производительность: Как я уже сказал, я еще не настроил это, поэтому я не знаю, как это получится на практике, но я знаю, что Longhorn выполняет синхронную репликацию (всё должно быть записано на репликах до того, как операция записи будет считаться “завершенной”), поэтому это определенно будет медленнее, чем чисто локальный NVMe. Насколько медленнее, пока предстоит узнать, но я думаю, что это не будет проблемой для вас, особенно при 10-гигабитной сетевой связи, поскольку вас не беспокоили, например, производительность SQLite через NFS, только проблемы с согласованностью.
Я постараюсь не забыть опубликовать обновление здесь, как только это будет настроено (планирую сделать это на этой неделе). Я постараюсь провести некоторые базовые тесты производительности на локальном диске и с Longhorn.
К вашему сведению, Longhorn — не единственный вариант, который у вас есть. Другие названия, которые всплыли в ходе моих исследований, включают Piraeus и Linstor, но я не проводил много исследований по ним, поэтому не знаю, как они сравниваются.
Редактировать: Результаты тестов
Я потратил день, играя с fio
и Longhorn в различных конфигурациях, и мой вывод таков, что это рабочее, но определенно не высокопроизводительное решение. Это нормально для вещей, которые в основном простаивают все время (например, веб-приложения локального размещения), но если вы хотите, например, запустить сильно загруженную реляционную базу данных на нем, я бы, вероятно, порекомендовал попробовать что-то другое.
Я провел 3 теста (ну, 6, потому что я тестировал чтение и запись отдельно) для каждой конфигурации, которую я тестировал. Тесты были следующими:
- Максимальная пропускная способность: 4MiB чтений/записей из одного процесса с глубиной очереди 16
- Максимальное число операций ввод-вывод в секунду (IOPS): 4к случайных чтений/записей из 16 параллельных процессов, каждый из которых выполняется с глубиной очереди 16 (то есть 256 операций одновременно)
- Попытка эмулировать более “реальную” рабочую нагрузку для обсуждаемой ситуации: 4к случайных чтений/записей из одного процесса с глубиной очереди 2. Моя цель в этом — подражать, например, слабо загруженному веб-приложению на основе SQLite (который по умолчанию использует страницы размером 4к, если я правильно помню.)
Я провел эти тесты в следующих ситуациях:
- Напрямую против локального диска, без виртуализации
- Против того же диска, но смонтированного в поде с
hostPath
- Против того же диска через Longhorn с 1 репликой
- Из локального пода (работающего на той же ноде, что и реплика)
- Из удаленного пода (работающего на другой ноде, чем реплика)
- Против того же диска через Longhorn с 2 репликами (у меня в кластере в данный момент всего 2 ноды, так что тестировать 3 реплики было бы не очень значимо.)
Сервера работали на процессорах Epyc 7262 (8c16t), 64 ГБ ОЗУ и были подключены через 10GbE. Тестируемые диски были SK Hynix Platinum P41 (с оценкой 7000 MiB/s на чтение, 6500 MiB/s на запись, и ~1.5M IOPS)
Таблицы немного запутанные, поэтому для ясности, строки представляют собой конфигурации хранения (например, тестирование непосредственно против диска по сравнению с тестированием через Longhorn или что-то еще), а столбцы представляют рабочие нагрузки. Колонка “BW – R” относится к нагрузке чтения для максимальной пропускной способности, колонка “IOPS – W” относится к нагрузке записи для максимального числа операций ввод-вывод в секунду, и так далее.
Результаты – Пропускная способность (MiB/s)
BW – R | BW – W | IOPS – R | IOPS – W | Light – R | Light – W | |
---|---|---|---|---|---|---|
Прямое подключение | 7025 | 6333 | 5861 | 5584 | 174 | 143 |
Host path | 7027 | 6196 | 4789 | 5515 | 117 | 405 |
LH – 1R, локальный | 1512 | 354 | 118 | 67.2 | 19.6 | 19.1 |
LH – 1R, удаленный | 244 | 254 | 84.3 | 40.5 | 11.2 | 11.7 |
LH – 2R | 395 | 254 | 96.8 | 34.5 | 19.2 | 10.6 |
IOPS
BW – R | BW – W | IOPS – R | IOPS – W | Light – R | Light – W | |
---|---|---|---|---|---|---|
Прямое подключение | 1756 | 1583 | 1.50M | 1.43M | 44.5k | 36.6k |
Host path | 1.75k | 1.5k | 1.2M | 1.4M | 29.9k | 104k |
LH – 1R, локальный | 377 | 88 | 30.1k | 17.2k | 5.0k | 4.9k |
LH – 1R, удаленный | 61 | 63 | 21.6k | 10.1k | 2.8k | 2.9k |
LH – 2R | 98 | 63 | 24.8k | 8.8k | 4.9k | 2.7k |
Задержка
BW – R | BW – W | IOPS – R | IOPS – W | Light – R | Light – W | |
---|---|---|---|---|---|---|
Прямое подключение | 9.1мс | 10.1мс | 170μс | 357μс | 44.4μс | 54.2μс |
Host path | 9.1мс | 10.2мс | 208μс | 181μс | 65.9μс | 18.8μс |
LH – 1R, локальный | 42.3мс | 181мс | 8.5мс | 14.9мс | 396μс | 408μс |
LH – 1R, удаленный | 259мс | 252мс | 11.85мс | 25.1мс | 713μс | 680μс |
LH – 2R | 162мс | 251мс | 10.3мс | 28.9мс | 406μс | 738μс |
Примечание о задержке: Я использую среднее значение lat
, которое производит fio
, и которое, насколько я знаю, относится ко времени с момента, когда операция отправлена, до момента, когда чтение/запись завершается. Поэтому оно так высоко в сценариях максимальной пропускной способности: они 1000х больше, чем операции на 4к, так что они наверняка займут немного больше времени.
Выводы:
Как ни крути, вы жертвуете много производительности по сравнению с тем, что вы получаете, работая с локальным диском без виртуализации.
Но я не уверен, что это имеет значение! Особенно если мы посмотрим на IOPS и показатели задержки для «легкой» рабочей нагрузки, мы можем увидеть, что мы все еще получаем >1k IOPS, и эти операции завершаются в <1 мс. На мой взгляд, этого достаточно для повседневного использования. Если базе данных вашего веб-приложения нужно будет несколько раз обратиться к диску для обработки запроса, вы все равно не заметите разницы, потому что все, что занимает меньше 1 мс, абсолютно заслоняется сетевой задержкой.
Где все это начнет разваливаться — так это если вам нужно поддерживать значительную нагрузку (что, к слову, ожидается при запуске Kubernetes — он определенно не предназначен для домашней лаборатории). Как только вы достигаете нескольких тысяч одновременно подключенных пользователей, вы действительно начнете ощущать дефицит на этих IOPS.
Longhorn работает над V2 своего механизма хранения, который, как они утверждают, “значительно уменьшает задержку ввода-вывода, одновременно увеличивая IOPS и пропускную способность,” но он все еще находится на стадии активной разработки и пока не поддерживает важные функции, такие как моментальные снимки и резервное копирование. Может быть, когда он будет выпущен, я обновлюсь и пересниму эти тесты.
В то же время, если вам нужна производительность выше, чем может предоставить Longhorn, возможно, Piraeus/Linstor (по-видимому, Piraeus построен на базе Linstor) стоит взглянуть? Исходя из того, что я читаю, он может выполнять асинхронную репликацию, что идеально для ситуации, когда вы запускаете только одну из любой данной вещи за раз и просто хотите репликацию, чтобы контейнеры могли перемещаться между узлами без необходимости беспокоиться.
.
Ответ или решение
Вопрос о локальных вариантах хранения для Kubernetes в домашней лаборатории
Теория
В основе вашего вопроса лежит желание создать кластер Kubernetes в домашней лаборатории, способный эффективно обрабатывать данные, используя локальные ресурсы, что в данном случае представлено NVMe-дисками на рабочих узлах и массивом NAS (Network Attached Storage). Основная задача заключается в том, чтобы справиться с недостатками производительности NFS (Network File System) для файлов систем конфигурации и базы данных SQLite, которые препятствуют формированию стабильной среды для вашего грузового прикладного ПО.
Проблема, с которой вы сталкиваетесь, не является редкостью в мире Kubernetes, особенно когда физическая архитектура включает комбинацию локальных и сетевых хранилищ. Задача состоит в оптимизации производительности и согласованности данных между узлами.
Пример
Вы рассматриваете различные варианты, чтобы справиться с проблемой производительности при работе с конфигурационными файлами на распределенном файловом хранилище. В этом контексте хорошей альтернативой могут стать системы управления хранилищами, созданные специально для работы в кластерах. Например, Longhorn – это облачное программное обеспечение от Rancher, специально предназначенное для интеграции с Kubernetes. Longhorn обеспечивает синхронную репликацию и позволяет использовать NFS/SMB как резервный целевой объект.
Существуют и другие решения, такие как Piraeus, построенный на основе LINSTOR, который обеспечивает асинхронную репликацию, идеально подходящую для сценариев, когда необходимо минимизировать задержки в репликации данных между узлами.
Применение
Для вашей лаборатории рекомендуется внедрить распределенное хранилище, способное управлять репликацией и синхронизацией физических данных. Longhorn, интегрируясь с K3s и поддерживая синхронную репликацию, может стать надежным выбором. Однако, важно учитывать его негативное влияние на производительность по сравнению с локальными NVMe и общем доступе. Это означает, что Longhorn может быть предпочтителен для приложений, которые не подразумевают высокую нагрузку и необходимость максимальной скорости ввода-вывода.
Для более нагруженных приложений либо в случаях, когда требуется минимизировать задержки, стоит рассматривать Piraeus/LINSTOR с асинхронной архитектурой репликации. Это позволяет оперировать с локальными копиями данных без риска конкурентного доступа и сбоев на уровне блокировок.
Также, по мере роста домашних кластеров, стоит протестировать производительность различных конфигураций хранения: сравните поведение приложений при различных сценариях репликации с использованием инструментов, таких как fio
, для оценки производительности ввода-вывода. Это поможет посмотреть, насколько ваши приложения критичны к задержкам и нагрузкам.
Не забывайте про актуальные разработки по улучшению производительности Longhorn v2, который, хотя и находится в стадии разработки, может значительно улучшить показатели производительности и понизить задержки I/O в будущем.
В конечном итоге, выделенные ресурсы для настройки, тщательное тестирование и оценка конфигурации вашего кластера помогут вам добиться максимально эффективной работы Kubernetes в вашей домашней обстановке.