- Кластерное хранилище в Proxmox. Часть первая. Fencing
- Кластерное хранилище в Proxmox. Часть вторая. Запуск
Здравствуйте!
Третья часть статьи является своеобразным приложением двум предыдущим, в которых я рассказывал о работе с Proxmox-кластером. В этой части я опишу проблемы, с которыми мы сталкивались в работе с Proxmox, и их решения.
Авторизованное подключение к iSCSI
Если вам понадобилось при подключении к iSCSI указать креденшиалы — лучше это делать в обход Proxmox. Почему?
- Во-первых, потому что через web-интерфейс Proxmox невозможно создать авторизованное iSCSI-подключение.
- Во-вторых, даже если вы решите создать в Proxmox неавторизованное подключение с тем, чтобы указать авторизационную информацию вручную, то вам придется бодаться с системой за возможность изменить конфигурационные файлы таргетов, так как при неудачной попытке подключения к iSCSI-хосту Proxmox перезаписывает информацию о таргетах и производит повторную попытку подключения.
root@srv01-vmx:~# iscsiadm -m discovery -t st -p 10.11.12.13 root@srv01-vmx:~# iscsiadm -m node --targetname "iqn.2012-10.local.alawar.ala-nas-01:pve-cluster-01" --portal "10.11.12.13:3260" --op=update --name node.session.auth.authmethod --value=CHAP root@srv01-vmx:~# iscsiadm -m node --targetname "iqn.2012-10.local.alawar.ala-nas-01:pve-cluster-01" --portal "10.11.12.13:3260" --op=update --name node.session.auth.username --value=Admin root@srv01-vmx:~# iscsiadm -m node --targetname "iqn.2012-10.local.alawar.ala-nas-01:pve-cluster-01" --portal "10.11.12.13:3260" --op=update --name node.session.auth.password --value=Lu4Ii2Ai
Эти команды надо выполнить для всех порталов, предоставляющих нужный нам таргет на всех нодах кластера.
Монтирование на новой ноде GFS2-FS
Для того, чтобы на новой ноде смонтировать GFS2-файловую систему, ей (файловой системе) необходимо добавить еще один журнал. Делается это следующим образом: на любой ноде кластера, на которой смонтирована нужная нам FS, выполняется команда:
root@pve01:~# gfs2_jadd -j 1 /mnt/cluster/storage01
Параметр "-j" указывает количество журналов, которое необходимо добавить к FS.
Эта команда может завершиться с ошибкой:
create: Disk quota exceeded
Причины возникновения ошибки:
Внутри GFS2-тома находится на самом деле не одна файловая система, а две. Еще одна файловая система предназначена для служебных целей. При желании ее можно смонтировать, добавив опцию "-o meta". Изменения внутри этой FS потенциально могут привести к разрушению файловой системы с данными. При добавлении журнала к FS происходит монтирование meta-файловой системы в каталог "/tmp/TEMP_RANDOM_DIR", после чего в ней создается файл журнала. По непонятным пока нам причинам, ядро иногда считает, что в примонтированной meta-FS превышена квота на создание объектов, из-за чего такая ошибка и возникает. Выйти из положения можно, перемонтировав GFS2 с данными (разумеется, для этого необходимо остановить все виртуалки, расположенные на этой FS), и еще раз выполнить команду добавления журнала. Также необходимо отмонтировать meta-FS, оставшуюся от прошлой неудачной попытки добавления журнала:
cat /proc/mounts | grep /tmp/ | grep -i gfs2 | awk '{print $2}' | xargs umount
Монтирование источника данных внутрь контейнера
Технология контейнерной виртуализации хороша тем, что хост имеет практически неограниченные возможности общения с виртуальной машиной.
При старте контейнера vzctl пытается выполнить следующий набор скриптов (при их наличии):
- /etc/pve/openvz/vps.premount
- /etc/pve/openvz/CTID.premount
- /etc/pve/openvz/vps.mount
- /etc/pve/openvz/CTID.mount
- /etc/pve/openvz/CTID.start
При остановке выполняются следующие скрипты:
- /etc/pve/openvz/CTID.stop
- /etc/pve/openvz/CTID.umount
- /etc/pve/openvz/vps.umount
- /etc/pve/openvz/CTID.postumount
- /etc/pve/openvz/CTID.postumount
, где "CTID" — это номер контейнера. Скрипты "vps.*" выполняются при операциях с любым контейнером. Скрипты "*.start" и "*.stop" выполняются в контексте контейнера, все остальные — в контексте хоста. Таким образом, мы можем заскриптовать процесс запуска / остановки контейнера, добавив в него монтирование данных. Вот несколько примеров:
Монтирование каталога с данными внутрь контейнера
Если контейнер работает с большим объемом данных, мы стараемся эти данные не держать внутри контейнера, а монтировать их с хоста. В таком подходе есть два положительных момента:
- Контейнер маленький, быстро бэкапится средствами Proxmox. Мы имеем возможность в любой момент быстро восстановить / клонировать функционал контейнера.
- Данные контейнера можно централизованно бэкапить хорошей системой бэкапа со всеми удобствами, предоставляемыми ею (разноуровневые бэкапы, ротация, статистика и так далее).
Содержимое файла "CTID.mount":
#!/bin/bash . /etc/vz/vz.conf # подключаем файл с глобальным описанием внутренних переменных OpenVZ. В частности, в нем определена переменная ${VE_ROOT} - корневой каталог контейнера на хосте. . ${VE_CONFFILE} # подключаем файл с описанием переменных контейнера DIR_SRC=/storage/src_dir # каталог на хосте, который надо примонтировать внутрь контейнера DIR_DST=/data # каталог внутри контейнера, к которому будет примонтирован $DIR_SRC mkdir -p ${VE_ROOT}/${DIR_DST} # создаем внутри контейнера каталог назначения mount -n -t simfs ${DIR_SRC} ${VE_ROOT}/{$DIR_DST} -o /data # монтируем каталог внутрь контейнера
Монтирование файловой системы внутрь контейнера
На хосте есть том, который надо отдать контейнеру. Содержимое файла "CTID.mount":
#!/bin/bash . /etc/vz/vz.conf . ${VE_CONFFILE} UUID_SRC=3d1d8ec1-afa6-455f-8a27-5465c454e212 # UUID тома, который надо примонтировать внутрь контейнера DIR_DST=/data mkdir -p ${VE_ROOT}/${DIR_DST} mount -n -U ${FS_BY_UUID} ${VE_ROOT}/{$DIR_DST}
Монтирование файловой системы, находящейся в файле, внутрь контейнера
Зачем такое может понадобиться? Если какой-нибудь хитрый продукт (например, Splunk) ни в какую не хочет работать с simfs, либо нас не устраивает скорость работы GFS2 при определенных условиях. Например, у нас есть какой-нибудь кэш на куче мелких файлов. GFS2 не очень быстро работает с большими объемами маленьких файлов. Тогда можно на хосте создать файловую систему, отличную от GFS2 (ext3), и подключить ее к контейнеру.
Монтируем loop-устройство из файла в контейнер:
Сначала создаем файл:
root@srv01:~# truncate -s 10G CTID_ext3.fs
Форматируем FS в файле:
root@srv01:~# mkfs.ext3 CTID_ext3.fs mke2fs 1.42 (29-Nov-2011) CTID_ext3.fs is not a block special device. Proceed anyway? (y,n) y ...
Содержимое файла "CTID.mount":
#!/bin/bash . /etc/vz/vz.conf . ${VE_CONFFILE} CFILE_SRC=/storage/CTID_ext3.fs # путь к файлу, который надо примонтировать внутрь контейнера DIR_DST=/data mkdir -p ${VE_ROOT}/${DIR_DST} mount -n ${CFILE_SRC} -t ext3 ${VE_ROOT}/{$DIR_DST} -o loop
Отмонтирование внешних данных в контейнере при остановке
При остановке контейнера система пытается автоматически отмонтировать все подключенные к нему файловые системы. Но в особо экзотических конфигурациях у нее этого сделать не получается. Поэтому на всякий случай пример простого скрипта "CTID.umount":
#!/bin/bash . /etc/vz/vz.conf . ${VE_CONFFILE} DIR=/data if mountpoint -q "${VE_ROOT}${DIR}" ; then umount ${VE_ROOT}${DIR} fi
Работа в кластере с не-кластерной файловой системой
Если по каким-то причинам нет желания использовать кластерную FS (не устраивает стабильность работы, не устраивает быстродействие и пр.), но хочется работать с единым хранилищем, то такой вариант возможен. Для этого нам понадобятся:
- Отдельный логический том в CLVM для каждой ноды кластера
- Основное хранилище для штатной работы контейнеров
- Пустое резервное хранилище для срочного монтирования тома чужой ноды в случае ее краха / отключения
Порядок действий:
Каждой ноде кластера выделяем свой логический том в CLVM, форматируем его.
Создаем основное хранилище. Создаем каталог, имеющий одинаковое название на всех нодах кластера (например, "/storage"). Монтируем в него наш логический том. Создаем в админке Proxmox хранилище типа "Directory", называем его, например, "STORAGE", говорим, что оно не является общим.
Создаем резервное хранилище. Создаем каталог, имеющий одинаковое название на всех нодах кластера (например, "/storage2"). Создаем в админке Proxmox хранилище типа "Directory", называем его, например, "STORAGE2", говорим, что оно не является общим. В случае падения / отключения одной из нод, ее том будем монтировать в каталог "/storage2" на той ноде кластера, которая возьмет на себя нагрузку усопшей.
Что мы имеем в итоге:
- Миграция (в том числе онлайн) контейнеров между нодами (если к контейнеру не подмонтировано никаких данных сбоку). Контейнер переносится с ноды на ноду копированием, соответственно, время миграции зависит от объема данных в контейнере. Чем больше данных, тем дольше будет переноситься контейнер между нодами. Не забываем про возрастающую дисковую нагрузку при этом.
- (Недо-)отказоустойчивость. При падении ноды ее данные можно смонтировать на соседней ноде, и теоретически с ними можно начинать работать.
Почему "недо-", и почему "теоретически":
Виртуальные машины живут в хранилище "Storage", которое расположено в каталоге "/storage". Диск с умершей ноды у нас будет подмонтирован в каталог "/storage2", где Proxmox будет видеть контейнеры, но не сможет их оттуда запускать. Для того, чтобы поднять находящиеся в этом хранилище виртуалки, надо сделать три действия:
- Сообщить контейнерам-погорельцам о том, что их новый дом — не каталог "/storage", а каталог "/storage2". Для этого надо в каждом файле "*.conf" в каталоге "/etc/pve/nodes/имя_мертвой_ноды/openvz" изменить содержимое переменной VE_PRIVATE с "/storage/private/CTID" на "/storage2/private/CTID".
- Сообщить кластеру, что виртуалки вон той неживой ноды расположены теперь на этой, живой. Для этого достаточно всего лишь перенести все файлы из каталога "/etc/pve/nodes/имя_мертвой_ноды/openvz" в каталог "/etc/pve/nodes/имя_живой_ноды/openvz". Возможно, для этого существует какая-то правильная API-инструкция, но мы этим не заморачивались 🙂
- Сбросить квоту для каждого контейнера-погорельца:
vzquota drop CTID
Все. Можно запускать контейнеры.
Если контейнеры с мертвой ноды занимают немного места, либо у нас невероятно шустрые диски, либо просто мы можем позволить себе подождать, то можно избежать выполнения этих трех шагов, просто перенеся нужные нам контейнеры из "/storage2/private" в "/storage/private".
Если кластер развалился
Кластер — существо капризное, и бывают случаи, что он встает в позу. Например, после массовых проблем с сетью, либо вследствие массового отключения питания. Поза выражается в том, что при обращении к кластерному хранилищу текущая сессия блокируется, опрос состояния fence-домена выводит тревожные сообщения, вида "wait state messages", а в dmesg сыпятся ошибки подключения.
Если никакие попытки оживить кластер не приводят к успеху, то самое простое — отключить на всех нодах кластера автоматический вход в fence-домен (файл "/etc/default/redhat-cluster-pve"), и последовательно перезагрузить все ноды. Надо быть готовым к тому, что ноды не смогут перезагрузиться самостоятельно. Когда все ноды будут перезагружены, вручную подключаемся к fence-домену, стартуем CLVM, и так далее. В предыдущих статьях написано, как это сделать.
На этом, пожалуй, все.
В следующей части я расскажу о том, как мы автоматизируем работу в кластере.
Спасибо за внимание!
ссылка на оригинал статьи http://habrahabr.ru/company/alawar/blog/178429/
Добавить комментарий