Glusterfs + Стирающее Кодирование: Когда Нужно Много, Дешево И Надежно

Мало у кого в России есть Гластер, а любой опыт интересен.

Наш большой и промышленный и, судя по обсуждению в последний пост , в спросе.

Я рассказал о самом начале опыта переноса резервных копий из хранилища Enterprise в Glusterfs. Это недостаточно хардкорно.

Мы не остановились и решили собрать что-то посерьезнее.

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



Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

  • Еще теория объема/подобъема
  • горячий резерв
  • исцелить/полностью исцелить/перебалансировать
  • Выводы после перезагрузки 3-х нод (никогда этого не делайте)
  • Как запись на разных скоростях с разных ВМ и включение/выключение шарда влияет на загрузку субтома?
  • перебалансировка после сбоя диска
  • быстрая ребалансировка


То, что они хотели

Задача проста: собрать дешевое, но надежное хранилище.

Максимально дешево, надежно — чтобы не страшно было хранить на нем собственные файлы продаж.

Пока.

Потом после долгих тестов и бэкапов на другую СХД, тоже клиентскую.

Приложение (последовательный ввод-вывод) : — Резервные копии — Тестовые инфраструктуры — Тестовое хранилище для тяжелых медиафайлов.

Мы здесь.

— Борьба с дампом файлов и серьезными тестовыми инфраструктурами — Хранилище важных данных.

Как и в прошлый раз, основным требованием является скорость сети между инстансами Glaster. 10G поначалу нормально.



Теория: что такое дисперсный объем?

Рассредоточенный том основан на технологии стирающего кодирования (EC), которая обеспечивает достаточно эффективную защиту от сбоев диска или сервера.

Это как RAID 5 или 6, но не совсем.

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

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



Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно



Что такое субобъем?

Сущность субтома в терминологии GlusterFS проявляется наряду с распределенными томами.

При распределенно-дисперсном кодировании стирания будет работать только внутри субобъема.

А в случае, например, с распределенно-реплицируемыми, данные будут реплицироваться внутри субтома.

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

На рисунке серверы (физические) отмечены зеленым цветом, субтома — пунктиром.

Каждый из них представляется серверу приложений как диск (том):

Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

Было решено, что распределенно-рассредоточенная конфигурация 4+2 на 6 узлах выглядит вполне надежно; мы можем потерять любые 2 сервера или 2 диска в каждом подтоме, продолжая иметь доступ к данным.

В нашем распоряжении было 6 старых DELL PowerEdge R510 с 12 дисковыми слотами и 48 SATA-накопителями по 2 ТБ емкостью 3,5 дюйма.

В принципе, при наличии на рынке серверов с 12 дисковыми слотами и с дисками до 12 ТБ мы можем собрать СХД с полезным пространством до 576 ТБ.

Но не забывайте, что хотя максимальные размеры HDD продолжают расти из года в год, их производительность остаётся на прежнем уровне и восстановление диска объёмом 10-12ТБ может занять у вас неделю.



Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

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

  
  
  
  
  
  
  
  
  
  
  
   

gluster volume create freezer disperse-data 4 redundancy 2 transport tcp \ $(for i in {0.7} ; do echo {sl051s,sl052s,sl053s,sl064s,sl075s,sl078s}:/export/brick$i/freezer ; done)

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

Что мы получили:

Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

Все выглядит вполне нормально, но есть один нюанс.

Он заключается в записи на кирпичиках следующего объёма: Файлы размещаются по одному в субтомах, а не разбросаны по ним равномерно, поэтому рано или поздно мы упираемся в его размер, а не в размер всего тома.

Максимальный размер файла, который мы можем поместить в это хранилище = полезный размер субтома минус уже занятое на нем пространство.

В моем случае это <8 TB. Что делать? Как быть? Эту проблему решает шардинг или страйп-объем, но, как показала практика, страйп работает очень плохо.

Поэтому попробуем шардинг.

Что такое шардинг, подробно здесь .

Что такое шардинг вкратце? : Каждый файл, который вы помещаете в том, будет разделен на части (осколки), которые относительно равномерно распределены по подтомам.

Размер шарда задается администратором, стандартное значение — 4 МБ.

Шардинг включаем после создания тома, но до его запуска :

gluster volume set freezer features.shard on

Установите размер шарда (какой оптимальный? Ребята из oVirt рекомендуют 512МБ) :

gluster volume set freezer features.shard-block-size 512MB

Опытным путем получается, что реальный размер шарда в блоке при использовании рассредоточенного объема 4+2 равен shard-block-size/4, в нашем случае 512M/4 = 128M. Каждый шард, согласно логике стирающего кодирования, раскладывается на кирпичики внутри подобъема такими кусочками: 4*128M+2*128M. Нарисуйте случаи сбоев, которые наблюдаются в этой конфигурации: В такой конфигурации мы можем пережить падение 2-х нод или 2-х любых дисков внутри одного субтома.

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

Включаем последовательную запись с 15 ВМ и делаем следующее.

Перезагрузите 1-й узел: 17:09 Выглядит некритично (~5 секунд недоступности по параметру ping.timeout).

17:19 Запустил хил полный.

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

17:32 Было решено отключить запись с ВМ.

Количество записей об исцелении начало уменьшаться.

17:50 исцеление завершено.

Перезагрузите 2 узла: Наблюдаются те же результаты, что и с 1-м узлом.

Перезагрузите 3 узла: Точка монтирования сообщила, что конечная точка транспорта не подключена, виртуальные машины получили ошибку ioerror. После включения узлов Гластер восстановился самостоятельно, без вмешательства с нашей стороны, и начался процесс лечения.

Но 4 из 15 ВМ не смогли подняться.

Я увидел ошибки на гипервизоре:

2018.04.27 13:21:32.719 ( volumes.py:0029): I: Attaching volume vol-BA3A1BE1 (/GLU/volumes/33/33e3bc8c-b53e-4230-b9be-b120079c0ce1) with attach type generic. 2018.04.27 13:21:32.721 ( qmp.py:0166): D: Querying QEMU: __com.redhat_drive_add({'file': u'/GLU/volumes/33/33e3bc8c-b53e-4230-b9be-b120079c0ce1', 'iops_rd': 400, 'media': 'disk', 'format': 'qcow2', 'cache': 'none', 'detect-zeroes': 'unmap', 'id': 'qdev_1k7EzY85TIWm6-gTBorE3Q', 'iops_wr': 400, 'discard': 'unmap'}).

2018.04.27 13:21:32.784 ( instance.py:0298): E: Failed to attach volume vol-BA3A1BE1 to the instance: Device 'qdev_1k7EzY85TIWm6-gTBorE3Q' could not be initialized Traceback (most recent call last): File "/usr/lib64/python2.7/site-packages/ic/instance.py", line 292, in emulation_started c2.qemu.volumes.attach(controller.qemu(), device) File "/usr/lib64/python2.7/site-packages/c2/qemu/volumes.py", line 36, in attach c2.qemu.query(qemu, drive_meth, drive_args) File "/usr/lib64/python2.7/site-packages/c2/qemu/_init_.py", line 247, in query return c2.qemu.qmp.query(qemu.pending_messages, qemu.qmp_socket, command, args, suppress_logging) File "/usr/lib64/python2.7/site-packages/c2/qemu/qmp.py", line 194, in query message["error"].

get("desc", "Unknown error") QmpError: Device 'qdev_1k7EzY85TIWm6-gTBorE3Q' could not be initialized qemu-img: Could not open '/GLU/volumes/33/33e3bc8c-b53e-4230-b9be-b120079c0ce1': Could not read image for determining its format: Input/output error

С трудом потушить 3 ноды с отключенным шардингом

Transport endpoint is not connected (107) /GLU/volumes/e0/e0bf9a42-8915-48f7-b509-2f6dd3f17549: ERROR: cannot read (Input/output error)

Мы также теряем данные, и их невозможно восстановить.

Мягко погасите 3 ноды с шардингом, не будет ли порчи данных? Да, но гораздо меньше (совпадение?), потеряно 3 диска из 30. Выводы:

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

  2. Никогда не перезагружайте более 2 узлов в конфигурации 4+2 в производстве!
  3. Как не потерять данные, если очень хочется перезагрузить 3+ ноды? Прекратите запись в точку монтирования и/или остановите том.

  4. Узел или кирпич необходимо заменить как можно скорее.

    Для этого крайне желательно иметь в каждом узле, например, 1–2 кирпича а-ля горячего резерва для быстрой замены.

    И еще один запасной узел с кирпичами на случай, если узел выйдет из строя.



Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

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

Смещения кирпичей (дисков): 17:20 Выбиваем кирпич:

/dev/sdh 1.9T 598G 1.3T 33% /export/brick6

17:22

gluster volume replace-brick freezer sl051s:/export/brick_spare_1/freezer sl051s:/export/brick2/freezer commit force

Эту просадку можно увидеть в момент замены кирпича (запись с 1 источника):

Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

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

Регулируемые параметры лечения:

gluster volume set cluster.background-self-heal-count 20 # Default Value: 8 # Description: This specifies the number of per client self-heal jobs that can perform parallel heals in the background. gluster volume set cluster.heal-timeout 500 # Default Value: 600 # Description: time interval for checking the need to self-heal in self-heal-daemon gluster volume set cluster.self-heal-window-size 2 # Default Value: 1 # Description: Maximum number blocks per file for which self-heal process would be applied simultaneously. gluster volume set cluster.data-self-heal-algorithm diff # Default Value: (null) # Description: Select between "full", "diff".

The "full" algorithm copies the entire file from source to # sink. The "diff" algorithm copies to sink only those blocks whose checksums don't match with those of # source. If no option is configured the option is chosen dynamically as follows: If the file does not exist # on one of the sinks or empty file exists or if the source file size is about the same as page size the # entire file will be read and written i.e "full" algo, otherwise "diff" algo is chosen. gluster volume set cluster.self-heal-readdir-size 2KB # Default Value: 1KB # Description: readdirp size for performing entry self-heal

Опция: dispers.background-heals Значение по умолчанию: 8 Описание: эту опцию можно использовать для управления количеством параллельных исцелений.

Опция: dispers.heal-wait-qlength Значение по умолчанию: 128 Описание: эту опцию можно использовать для контроля количества исцелений, которые могут подождать.

Опция: разогнать.

shd-max-threads Значение по умолчанию: 1 Описание: Максимальное количество параллельных исцелений, которые SHD может выполнить на один локальный блок.

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

Опция: dispers.shd-wait-qlength Значение по умолчанию: 1024. Описание: эту опцию можно использовать для управления количеством исцелений, которые могут ожидать в SHD на каждый субобъем.

Вариант: dispers.cpu-extensions Значение по умолчанию: авто Описание: принудительное расширение ЦП для ускорения вычислений поля Галуа.

Опция: dispers.self-heal-window-size Значение по умолчанию: 1 Описание.

Максимальное количество блоков (128 КБ) на файл, для которых одновременно будет применяться процесс самовосстановления.

Стоял:

disperse.shd-max-threads: 6 disperse.self-heal-window-size: 4 cluster.self-heal-readdir-size: 2KB cluster.data-self-heal-algorithm: diff cluster.self-heal-window-size: 2 cluster.heal-timeout: 500 cluster.background-self-heal-count: 20 cluster.disperse-self-heal-daemon: enable disperse.background-heals: 18

С новыми параметрами 1 ТБ данных был собран за 8 часов (в 3 раза быстрее!) Неприятно то, что в результате получается кирпич большего размера, чем был.

был:

Filesystem Size Used Avail Use% Mounted on /dev/sdd 1.9T 645G 1.2T 35% /export/brick2

стал:

Filesystem Size Used Avail Use% Mounted on /dev/sdj 1.9T 1019G 843G 55% /export/hot_spare_brick_0

Нам нужно разобраться в этом.

Вероятно, дело в надувании тонких дисков.

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

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

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

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

Значение по умолчанию является нормальным и позволяет хранить максимум [($(процессорных единиц) - 4) / 2), 2] файлов.

Мы мигрировали одновременно.

Ленивый режим позволит переносить только один файл за раз, а агрессивный режим позволит перенести максимум [($(процессорных единиц) - 4) / 2), 4] Опция: кластер.

lock-миграция Значение по умолчанию: выключено Описание.

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

Опция:cluster.weighted-rebalance Значение по умолчанию: включено Описание: При включении файлы будут распределяться по блокам с вероятностью, пропорциональной их размеру.

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

Сравнение записи и последующего чтения при одинаковых параметрах fio (более подробные результаты тестов производительности - в личном сообщении):

fio --fallocate=keep --ioengine=libaio --direct=1 --buffered=0 --iodepth=1 --bs=64k --name=test --rw=write/read --filename=/dev/vdb --runtime=6000



Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно



Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно



Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

Если вам интересно, сравните скорость rsync с трафиком на узлы Glaster:

Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно



Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

Видно, что примерно от 170 МБ/сек/трафик до 110 МБ/сек/полезные данные.

Получается, что это 33% дополнительного трафика, а также 1/3 избыточности Erasure Coding. Потребление памяти на стороне сервера с нагрузкой и почти без нее не меняется:

Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно



Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

Нагрузка на хосты кластера при максимальной нагрузке тома:

Glusterfs + стирающее кодирование: когда нужно много, дешево и надежно

Теги: #Виртуализация #ИТ-инфраструктура #Хранение данных #Администрирование сервера #файловая система #стирающее кодирование #glusterfs #gluster #gluster #gluster #gluster #dispersed Volume

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.