пятница, 26 марта 2021 г.

Proxmox6 + Linstore (DRBD)

 

Настройка Proxmox6 для работы с DRBD хранилищем и с контроллером Linstore

Linstor  предоставляет несколько служб и клиентов для работы с DRBD хранилищем. С помощью них система контролирует что и когда перемещать по нодам Proxmox6 участвующим в DRBD кластере.

Данная статья основана на вот этой: https://habr.com/ru/post/423101/
Но доработана для proxmox6 и проверены некоторые ситуации.

Определения

Нода - это машина на которой устанавливается драйверы drbd хранилища, в нашем случае это хосты с Proxmox 6 (система виртуализации KVM и линукс контейнеров). Таким образом нода и хост здесь это одно и тоже.

Контроллер (linstor-controller) - это машина или контейнер где устанавливается служба, которая следит за состоянием ДРБД кластера и сохраняет это состояние. Так же она передает информацию нодам что именно и когда синхронизировать.

Сателлит (linstor-satellite) - это служба устанавливаемая на ноде и она предоставляет информацию контроллеру о состоянии дрбд на конкретной ноде.

ДРБД Кластер (DRBD Cluster) - несколько машин с дисками и без участвующие в синхронизации данных на дисках.

Проксмокс Кластер (Proxmox Cluster) - стандартный кластер в который объединяются хосты с proxmox

Проксмокс ХА Кластер (HA Cluster) - Это служба проксмокса организующая высокую доступность к виртуальным машинам находящимся на хостах с проксмоксом. Она следит за машинами и контейнерам добавленными в этот кластер и автоматически переносит их с хоста на хост в случае проблем с хостом на котором машны работают.

Подготовка

В нашем случае применяется решение. где есть две ноды с реальными хранилищами (дисками которые размечаются с помощью Linux LVM) и одна нода без диска, она служит вспомогательной нодой для создания кворума, на случай если одна из нод в ДРБД кластере выйдет из строя.

Все ноды должны быть объеденные в proxmox кластер.

Первый шаг — это установить drbd-utils и собрать модуль ядра на каждой ноде.

Добавим репозиторий linstor и установим kernel-headers, а также все необходимые пакеты из него:

wget -O- https://packages.linbit.com/package-signing-pubkey.asc | apt-key add - 
echo "deb http://packages.linbit.com/proxmox/ proxmox-6 drbd-9.0" \
  > /etc/apt/sources.list.d/linbit.list

apt-get update
apt-get -y install pve-headers
apt-get -y install drbd-dkms drbdtop

После установки давайте проверим вашу версию модуля ядра:

modprobe drbd
cat /proc/drbd

Если вы видите 8 версию, значит что-то пошло не так и у вас загрузился in-tree модуль ядра, проверьте dkms status что бы узнать более подробно о сборке непосредственно dkms-модуля.
Для LINSTOR вы должны использовать DRBD 9 версии.

Убедитесь что в системе стоит python не ниже версии 3.7 - это важно для установки следующих пакетов.

Далее на каждой ноде установим пакеты linstor-proxmox и linstor-satellite:

apt-get -y install linstor-proxmox linstor-satellite
systemctl start linstor-satellite.service
systemctl enable linstor-satellite.service

Для ДРБД кластера лучше создать отдельную логическую сеть.

В нашем случае будем использовать сеть 192.168.10.0/24.
Поднимаем на каждой ноде отдельный сетевой интерфейс и назначаем адреса из указанной выше сети.
Вообще ДРБД кластер позволяет использовать несколько сетей для синхронизации данных, таким образом можно усиливать сетевую надежность. Для этого лучше иметь несколько сетевых карт на нодах.

Также на каждой ноде нужно подготовить хранилище:

vgcreate drbd-vg /dev/sdb1
lvcreate -l 100%FREE --thinpool drbdpool drbd-vg

Выделяем раздел /dev/sdb1 для ДРБД, здесь drbd-vg это lvm группа.

 

Контроллер будем собирать на базе контейнера с debian 10.
ВАЖНО! нужно использовать debian версии 10, т.к. в там есть все необходимое для линстор библиотек.

После того как контейнер готов, заходим в него

Установим обновления:

apt-get update 
apt-get -y upgrade

Добавим репозиторий linstor и установим linstor-controller и linstor-client:

wget -O- https://packages.linbit.com/package-signing-pubkey.asc | apt-key add - 
echo "deb http://packages.linbit.com/proxmox/ proxmox-6 drbd-9.0" \
  > /etc/apt/sources.list.d/linbit.list
apt-get update && apt-get install -y linstor-controller linstor-client
systemctl start linstor-controller.service
systemctl enable linstor-controller.service

Linstor требует настроенной локали. Настроим locale:

sed -i '/en_US.UTF-8 UTF-8/ s/^# //' /etc/locale.gen
locale-gen

Давайте сразу же настроим временную зону:

dpkg-reconfigure tzdata

Конфигурирование хранилища

 

Создадим ноды в линстор контроллере.
Заходим в контейнер с контроллером и выполняем:

linstor node create proxmox1 192.168.10.11
linstor node create proxmox2 192.168.10.12
linstor node create proxmox3 192.168.10.13

добавим имена нод в файл /etc/hosts

Пример вывода команды linstor node list:

┊ proxmox1  ┊ SATELLITE   ┊ 192.168.10.11:3366 (PLAIN) ┊Online┊
┊ proxmox2  ┊ SATELLITE   ┊ 192.168.10.12:3366 (PLAIN) ┊Online┊
┊ proxmox3  ┊ SATELLITE   ┊ 192.168.10.13:3366 (PLAIN) ┊Online┊

Добавим в хранилища в линстор контроллер:

linstor storage-pool create lvmthin proxmox1 drbdpool drbd-vg/drbdpool
linstor storage-pool create lvmthin proxmox2 drbdpool drbd-vg/drbdpool
linstor storage-pool create diskless proxmox3 drbdpool

Здесь нода proxmox3 является бездисковой и добавляется для кворума.

Теперь мы можем добавить наше новое хранилище в конфиг Proxmox:

cat >> /etc/pve/storage.cfg <<EOF

drbd: drbdpool
        resourcegroup drbdpool-group
        content rootdir, images
        controller 192.168.10.15
        controllervm 501
EOF

Здесь мы указываем IP адрес контейнера с линстор контроллером (192.168.10.15) и его номер в проксмоксе (501).

Номер контейнера (или VM) нужно обязательно указывать, т.к. проксмокс не дает ничего сделать с машинами у которых диск находится на ДРБД хранилище если в этот момент нет доступа к контроллеру. А нам нужно перенести контроллер в HA кластер который работает тогда когда у машина находится на ДРБД.
Таким образом сам контроллер будет лежать на ДРБД и чтобы можно было его стартовать и останавливать нужно указать проксмоксу номер этого контейнера (или VM).

Адрес контроллера нужно указать чтобы ноды проксмокса знали где брать информацию о состоянии ДРБД

Настройка HA для контроллера

Теперь мы перенесем наш linstor container на linstor storage.

Для начала нам нужно создать виртуальный диск для него:

pct exec 501 bash
linstor resource-definition create vm-501-disk-0
linstor volume-definition create vm-501-disk-0 4G
linstor resource create vm-501-disk-0 --auto-place 2 -s drbdpool

По умолчанию linstor-satellite (Сателлит на ноде) удаляет конфиги всех ресурсов на момент запуска сервиса, затем он ожидает новую кофигурацию от linstor-controller, но если мы будем держать linstor-controller в том же месте что и данные, мы должны сделать исключение для его ресурса, добавив опцию --keep-res=vm-501 для linstor-satellite на всех нодах:

echo -e "[Service]\nExecStart=\nExecStart=/usr/share/linstor-server/bin/Satellite --logs=/var/log/linstor-satellite --config-directory=/etc/linstor --keep-res=vm-501" | SYSTEMD_EDITOR=tee systemctl edit linstor-satellite.service

Это действие должно предотвратить удаление ресурса vm-501-disk-0 при каждом запуске ноды и сервиса linstor-satellite.

Теперь мы остановим linstor-controller контейнер и перенесем все данные с локального диска на drbd-диск.

pct shutdown 501
dd if=/var/lib/vz/images/100/vm-501-disk-0.raw of=/dev/drbd/by-res/vm-501-disk-0/0 bs=8M status=progress
e2fsck -f /dev/drbd/by-res/vm-501-disk-0/0 
resize2fs /dev/drbd/by-res/vm-501-disk-0/0 

Обновим конфиг контейнера:

sed -i '/^rootfs:/d' /etc/pve/lxc/501.conf
echo 'rootfs: drbdpool:vm-501-disk-0,size=4G' >> /etc/pve/lxc/501.conf

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

linstor resource list:

 

╭──────────────────────────────────────────-╮
┊ ResourceName    ┊ Node ┊ Port ┊    State  ┊
╞┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄-┄┄╡
┊ vm-501-disk-0 ┊ proxmox1 ┊ 7000 ┊ UpToDate┊
┊ vm-501-disk-0 ┊ proxmox2 ┊ 7000 ┊ UpToDate┊
╰─────────────────────────────────────────-─╯

Если нет такой информации ее можно скопировать с локального контейнера. Это все файлы из папки:

/var/lib/linstor

Теперь нам нужно только добавить наш контейнер в proxmox ha-manager.
Для этого сначала нужно создать группу в которую будут входить только дисковые ноды - proxmox1, proxmox2.
Затем добавлем в HA кластер этой группы контейнер 501.
Этому контейнеру нужно указать автозапуск

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

Замеченные проблемы

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

 

среда, 3 июня 2020 г.

Solarhouse python package

Я кроме программирования занимаюсь экодомостроительством о чем пишу в своем отдельном блоге:

http://yaricblog.blogspot.com/

В моем доме применяется солнечная энергия для нагрева воздуха и для получение электрической энергии.

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

Чтобы оценить эффективность того или иного типа солнечного коллектора, а также эффективность формы дома, его размера, утеплителя и массы накопителя тепла внутри дома, для этого был создан программный пакет на python3

https://github.com/yaricp/py-solarhouse

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

PyMesh
PVLIB
Pandas

Суть работы пакета в следующем:

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

По этим графикам можно оценить когда можно прекращать отапливать дом электричеством или печью или котлом.

Как это работает:

Перед началом расчетов с помощью библиотеки PVLIB получаем значения солнечной энергии от прямых лучей и от рассеянного солнечного света на один квадратный метр поверхности, которая перпендикулярна солнечным случам. При этом если указано, что нужно учитывать погоду, то извлекаются данные о солнечной радиации с учетом погоды.
Все данные извлекаются для указанной точки на карте (координаты дома указываются перед началом расчета).
Данные получаются в виде таблицы Pandas (библиотека Python).
В этой таблице содержатся три вида солнечной активности и температура окружающей среды для указанной местности.
Затем спомощью библиотеки PyMesh поверхность дома, которая задана в файле *.stl или *.obj, разбивается на треугольники. Также спомощью этой библиотеки вычисляется общая площадь дома, внутренний объем.
Также моделируется внутренний объем дома с учетом толщины стенки (указывается во входных данных).
Для каждого треугольник определяется угол наклона над горизонтом и направление относительно сторон света (Tilt,  Azimuth). После этого спомощью PVLIB для каждого треугольника вычисляется новая таблица Pandas с почасовыми значениями полученной солнечной энергии.
В итоге солнечного расчета мы имеем столько таблиц сколько треугольников в меше дома. Из этих таблиц суммируются мощности и формируется одна выходная таблица Pandas.

После этого выполняется следующий этап - это тепловой расчет дома.

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

Тепловая модель дома

Далее для каждого часового значения солнечной энергии и температуры окружающей среды вычисляются температура каждого элемента дома.

В итоге мы получаем Pandas таблицу в которой почасовые значения температур элементов дома и значения солнечной энергии.

Как устроен пакет:

В пакете описаны несколько классов

Calculation
Building
ThermoProcess
ThermoModel
ThermoElement

Класс Calculation описывает весь процесс расчета.
В нем подготавливаются таблицы Pandas из библиотеки PVLIB.
Также в нем организована очередность разных расчетов.
Экзепмляру этого класса передаются все необходимые данные для расчетов, в том числе и файл меша форма дома.
Затем вызывается единственный метод: .compute(date) с указанием даты или периода. И в результате получаем таблицу Pandas.

Класс Building описывает всю геометрию дома на базе PyMesh.
В момент инициализации экземпляра класса проверяются все возможные геометрические коллизии, а также оценивается является ли форма дома выпуклой и замкнутой.
Методы класса вычисляют геометрию разных элементов дома.
Также вычисляются объем и масса элементов.

Класс ThermoProcess подготавливает термоэлементы дома согласно выбранной термомодели и запускает тепловой расчет.
Основным параметром класса является объект класса Building.
Согласно упрощенной тепловой модели описанной тут имеется 9 элементов. Все эти элементы описываются при инициализации экземпляра класса. Данные этих элементов вычисляются на базе геометрии из класса Building.
Элементы соединяются в цепочку согласно выбранной тепловой модели.
Тепловая модель описывается классом: ThermoModel
И в итоге вызывается метод compute в котором для каждого значения солнечной энергии и температуры окружающей среды вычисляются температуры элементов дома.
В тепловой расчет мощность солнечной энергии задается с учетом КПД выбранного типа столнечного коллектора.

Класс ThermoModel описывает цепочку термоэлементов (ThermoElement).
Также здесь указывается какой элемент является начальным для теплового расчета и какой конечный. Т.к. расчет идет изнутри наружу то обычно конечными элементами являются температуры окружающей среди.


Класс ThermoElement описывает свойства термического элемента.
А также именно в этом классе выполняются главные тепловые расчеты.
Расчет выполняется для маленького промежутка времени.
И если термоэлемент является слоистой структурой, то в каждый момент вычисляются изменения температуры для всех слоев.

Установка пакета очень проста:

pip install solarhouse


В общем и процесс установки и использование пакета можно прочесть в документации:

Solarhouse

Вот так!



django3-pki

Когда-то на работе понадобилось поднять свой собственный центр сертификации для управления сертификатами для серверов и для клиентов VPN серверов и прочих сервисов.
Т.к. у нас использовался Django в качестве фреймворка для нашей системы управления компьютерами в сети, то я стал искать приложения к Django.
Едиственный нормально проработанный вариант это был django-pki
Это был проект Джанго с встроенным приложением центра сертификации.
Это была версия 1.2 и  тогда не разрабатывали приложения отлельно от самого фреймворками.

Я сделал форк этого проекта и переписал проект с поддержкой Django1.8
Там появилось много удобного и в коде питона и в разметке в шаблонах.

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

В этот раз я переписал код под Django3 и оформил это в виде отдельного приложения, которое можно установить через pip и потом просто добавить его в INSTALLED_APPS в settings.py

И да! конечно код был переписан на python. Нужно отметить что теперь требования к коду намного более строгие чем тогда когда писались первые версии этого приложения. Это я про то что настроена проверка кода разными валидаторами кода типа flake8, black и isort.

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

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

Теперь про само приложение.
Само приложение представляет собой обертку над библиотекой openssl.
В настройках приложения есть переменная :

PKI_OPENSSL_BIN = getattr(settings, "PKI_OPENSSL_BIN", "/usr/bin/openssl")

Здесь Вы можете указать путь к openssl в вашей системе.

Само приложение управляется через админку Django.

Когда вы нажимаете "Refresh Metadata" на странице приложения создается папка PKI в папке приложения, хотя Вы конечно можете указать и свой путь к папке сертификатов в вашей системе.

Основная конфигурация центра сертификации описана в шаблоне

/templates/pki/openssl.conf.in
На базе этого файла в папке PKI создается openssl.conf

Все сертификаты и корневые и для серверов и для клиентов будут находиться именно в папке PKI

Любые операции по изменению или удалению сделанные в веб интерфейсе будут актуализироваться тут же в папке PKI

В приложении реализовано логгирование всех действий с сертификатами и их можно посмотреть на странице приложения.

Будьте осторожней когда работаете непосредственно с файлами сертификатами. Если файл изменен или удален, приложение ничего об этом не узнает и данные в базе данных будут не актуальны.

Так же в этом приложении добавлена возможность формировать конфиг для клиентов ВПН серверов.

Шаблон для формирования таких конфигов лежит тут:

/pki/templates/ovpn.tpl

При формировании конфига в него будут добавлены сертификат клиента , ключ клиента и корневой сертификат центра.


Адреса ВПН сервером придется добавить в конфиг руками.

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

Но сейчас возникли некоторые особенности с новых версиях Django.
Дело в том, что разные приложения теперь можно располагать в разных базах данных  (для этого в новых версиях Django есть dbRouter). А вот связать модели из разных баз через конструкции
ForeignKey уже не возможно..
Поэтому теперь в приложении в модели хранится только имя пользователя.
Искать такого пользователя придется вручную.


В общем пользуйтесь! и пишите замечания и предложения.

https://pypi.org/project/django3-pki/

https://github.com/yaricp/django3-pki




среда, 10 октября 2018 г.

Бездисковые станции на слоистой файловой системе OverlayFS

Идея реализации бездисковых станций на базе OverlayFS была не моя, а моих коллег по работе.
Вероятно, уже многие рассматривали варианты как сделать бездисковые станции на базе слоситых файловых систем. Например на базе AuFS.
Но это было не просто  - т.к. много работы по установке и настройке модулей ядра, которых нет по умолчанию.
А зачем вообще такие бездисковые станции? спросите вы.

Область применения:


Сразу скажу это решение для Linux систем.
А с другими я особо и не работаю :))

1. Самое понятное - Класс в учебном заведении.
на всех машинах должны стоять одинаковые системы, они должны обновляться одинаково. На них должны стоять одинаковые наборы программ с одинаковыми настройками и связями между собой и с принтерами например.
Ну а наработанные данные пользователя должны тоже сохраниться и они будут лежать в отдельных папках на сервере.
2. Разные операционисты в банках, в торговых заведениях. Если например все они должны работать в общем пространстве программ и все программы должны быть настроены одинаково на всех машинах.
3. Различные пультовые и компьютеры управления какими-нибудь системами.
Суть в том что в разных местах сложных больших по площади установок могут стоять бездисковые машины для контроля и управления этой установкой и при запуске эти машины будут работать совершенно одинаково и показывать одни и теже приложения которые настраиваются один раз для всех машин.

Ну и можно еще много всего перечислять.

Идея:


Есть один большой и мощный NFS сервер, который для каждого клиента (бездисковой машины) имеет свой ресурс выдачи.
Этот ресурс формируется из двух слоев, можно и больше если в этом есть производственная необходимость (позже расскажу какая может быть потребность).
Нижний или Базовый слой содержит всю основную систему со всеми пакетами программ и настройками драйверов для внешних и устройств. В этом плане все клиентские машины должны быть унифицированы и иметь одинаковые подключенные внешние и внутренние устройства. Ну или придется устанавливать драйвера для всех имеющихся на клиентах устройств.
На верхнем слое будет лежать только то, что наработал пользователь. Здесь имеется ввиду логи его действий, временные и рабочие каталоги или настройки программ для этой машины.
А вот данные пользователя и его домашний каталог можно держать совершенно в отдельном каталоге. Это можно было делать и без использования слоистой файловой системы.
В итоге мы получаем :
1. настроенная  система в одном экземпляре
2. пользовательские папки  - на каждого пользователя по одной папке, независимо от количества бездисковых машин. На всех них он может работать с одинаковыми программами и со своими данными
3. в верхних слоях для каждой машины лежат временные папки и папки логов. Эти папки кстати можно периодически чистить без особого урона.

За счет этого объединения слоев мы получаем значительную экономию места на nfs сервере
и унификацию всех настроек программ на всех машинах. Скорость внесения изменений в базовый слой - мгновенно!

Особенности:


В общем то все зависит как будут организованы слои.
Самый простой способ использования это два слоя базовый и верхний слой где лежат только пользовательские настройки. Пользователь не может устанавливать в этом случае программы и добавлять устройства в машину.
Можно организовать трехслойную структуру, в этом случае у администора конкретной машины будет возможность устанавливать пакеты в средний слой, который базируется на общий для всех машин. А пользователи по-прежнему будут сохранять свои настройки в верхний слой.
Но в любом случае нельзя исправлять или добавлять файлы в верхние слои если слои не смонтированы в overlayfs. Дело в том что если слои размонтировать , то в папках слоев будут лежать файлы, которые привязаны к файлам более нижнего слоя и поэтому если файл более верхнего слоя изменился а система overlayfs об этом не знает , это может привести к не предсказуемым результатам.
Также есть особенность в пересборке ядра. Ядро нужно будет пересобирать только в базовом слое, то есть нужно загрузить машину с этим слоем, собрать ядро с указанием аргументов с тем что при загрузке ядро подмонтирует рутовую директорию коорая находится  на nfs ресурсе. Затем нужно пересобрать iniramfs и скопировать ядро и initramfs на tftp сервер, для того чтобы следующая загрузка машины произошла уже с новым ядром.


Реализация:


Итак рассмотрим реализация системы с двумя слоями.
В качестве сервера будет выступать система Centos 7.4
Поддержка модуля  overlayfs  в ядре появилась только с версии 4.16. Поэтому обновляем ядро до 4.16 или выше.
Устанавливаем пакет с репозиторием elrepo:


# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm


Оставляем только ядерные ветки репозитория:


# yum --disablerepo="*" --enablerepo="elrepo-kernel" list available


Устанавливаем последнее ядро:


# yum --enablerepo=elrepo-kernel install kernel-ml


После этого перегружаем машину и смотрим какое ядро появилось в папке /boot

После этого нужно убедиться что в grub.conf - е указана правильная строка загрузки по умолчанию.
То есть смотрим файл /etc/default/grub и убеждаемся что там написано: 
GRUB_DEFAULT=0

Обычно после установки нового ядра оно прописывается в самый первый (нулевой) уровень загрузки.   Но если оно установилось в другой уровень то пропишите этот уровень в GRUB_DEFAULT

Создадим структуру папок для слоистой файловой системы:

Давайте подключим отдельный диск или раздел диска и подмонтируем его в папку /DATA
В ней создадим базовый слой:

# mkdir /DATA/base/centos7.4

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

Создаем место для верхних слоев :


# mkdir /DATA/hosts/host1
# mkdir /DATA/hosts/host2
# mkdir /DATA/hosts/host3


И еще нужно  создать папки для временных рабочих файлов слоистой файловой системы:


# mkdir /DATA/works/host1
# mkdir /DATA/works/host2
# mkdir /DATA/works/host3


Устанавливаем систему в базовый слой :

# yum groups -y install "Server with GUI" --releasever=7 --installroot=/DATA/base/centos7.4

Здесь мы ставим например сервер с GUI.


Теперь устанавливаем nfs сервер:


# yum install nfs-utils


Создаем папки для выдачи соединенных слоев (соединять будем позже):


# mkdir  /export/hosts/host1
# mkdir  /export/hosts/host2
# mkdir  /export/hosts/host3


устанавливаем права на папки:


# chmod -R 755 /export/hosts/host1
# chown nfsnobody:nfsnobody  /export/hosts/host1


все то же самое для остальных папок.

Настраиваем файерволл:

firewall-cmd --permanent --zone=public --add-service=nfs
firewall-cmd --permanent --zone=public --add-service=mountd
firewall-cmd --permanent --zone=public --add-service=rpc-bind
firewall-cmd --reload


Запускаем все сервисы:


systemctl enable rpcbind
systemctl enable nfs-server
systemctl enable nfs-lock
systemctl enable nfs-idmap
systemctl start rpcbind
systemctl start nfs-server
systemctl start nfs-lock
systemctl start nfs-idmap


создаем файл /etc/exports и пишем туда примерно следующее:


/export/hosts/host1   192.168.0.1(rw,sync,no_root_squash,no_all_squash)
/export/hosts/host2   192.168.0.2(rw,sync,no_root_squash,no_all_squash)
/export/hosts/host3   192.168.0.3(rw,sync,no_root_squash,no_all_squash)


Теперь настроим монтирование слоев в overlayfs:

Во первых нужно настроить модуль ядра overlayfs, включаем возможность експортировать слои через NFS:


В файле /sys/module/overlay/parameters/nfs_export
 пишем YВ /sys/module/overlay/parameters/redirect_always_follow тоже пишем Y


Теперь подготовим файл /etc/fstab. Пишем для каждой машины:

overlay /exports/hosts/host1    overlay noauto,x-systemd.requires=/DATA,x-systemd.automount,lowerdir=/DATA/base/centos7.4/,upperdir=/DATA/hosts/host1/,workdir=/DATA/works/host1/,index=on 0 0

Здесь нужно отметить, что используется опция ядра index=on это важно для работы overlayfs через nfs. Иначе смонтированные по nfs верхние слои не будут видны на клиенте nfs.
А так же тут указаны важные опции noauto, x-systemd.requires и x-systemd.automount .
Это нужно для того чтобы монтирование папок происходило последовательно друг за другом.
То есть сначала монтируется диск с данными nfs ресурсов /DATA, а затем монтируются слои overlayfs. Чтобы такое произошло, нужно отключить автомонтирование слоев overlayfs. Кроме того монтирование будет производиться спомощью системы systemd.automount.

После перезагрузки сервера слои смонтируются и будут доступны по nfs.

Теперь нужно настроить выдачу загрузочного образа ядра для хостов через tftp сервер:


# yum install tftp-server


Меняем настройки по-умолчанию:

в файле /etc/xinetd.d/tftp меняем параметр disable  на  'no'

перегружаем xinetd:

# service xinetd restart

Устанавливаем основные загрузочные образы:

# yum install syslinux

Копируем нужные файлы в корень  (/var/lib/tftpboot/) tftp сервера:

# cp /usr/lib/syslinux/pxelinux.0 /var/lib/tftpboot
# cp /usr/lib/syslinux/menu.c32 /var/lib/tftpboot
# cp /usr/lib/syslinux/memdisk /var/lib/tftpboot
# cp /usr/lib/syslinux/mboot.c32 /var/lib/tftpboot
# cp /usr/lib/syslinux/chain.c32 /var/lib/tftpboot

Создаем директорию для загрузочного меню:

# mkdir /var/lib/tftpboot/pxelinux.cfg

Тут же создаем директорию для загрузочного образа базовой системы бездисковых станций:

# mkdir /var/lib/tftpboot/base-centos7.4

Туда же копируем vmlinuz и initrd.img.

в файле  /var/lib/tftpboot/pxelinux.cfg/default пишем примерно следующее:

default vesamenu.c32
prompt 0
timeout 300
ONTIMEOUT local

MENU TITLE PXE Menu
Local HHD0 Boot

LABEL Centos
    MENU LABEL Centos Install
        KERNEL base-centos7.4/vmlinuz
        APPEND initrd=base-centos7.4/initrd.img root=/dev/nfs rw nfsroot=nfs-server:/DATA/base/centos7.4 ip=eth0:dhcp selinux=0 ipv6.disable=1 console=tty0 plymouth.enable=0
       

Это настройки загрузки любой машины которую DHCP сервер перенаправил для загрузки ядра по сети на этот сервер. В данном случае загрузится базовый слой.

Для каждого хоста определяем IP адрес, который будет выдавать DHCP сервер, переводим этот адрес в hex представлении и создаем файл с таким именем и в нем прописываем загрузочное меню для этого хоста. tftp сервер будет выдавать это меню загрузки только для машин с IP для которого был сделан файл.
Вот пример файла:

default vesamenu.c32
prompt 0
timeout 60
ONTIMEOUT Main

MENU TITLE PXE Boot Host1

LABEL Main
    MENU LABEL host1
        KERNEL base-centos7.4/vmlinus
        APPEND initrd=base-centos7.4/initrd.img root=/dev/nfs rw nfsroot=nfs-server:/exports/hosts/host1 ip=eth0:dhcp selinux=0 ipv6.disable=1 console=tty0 plymouth.enable=0
LABEL base-pult
    MENU LABEL base-centos7.4
        KERNEL base-centos7.4/vmlinuz
        APPEND initrd=base-centos7.4/initrd.img root=/dev/nfs rw nfsroot=nfs-server:/DATA/base/centos7.4  ip=eth0:dhcp ipv6.disable=1 console=tty0 plymouth.enable=0


Теперь перегружаем сервисы :


# service xinetd restart
# service tftpbootd restart


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

Прописываем в /etc/dhcp/dhcpd.conf

next-server nfs-server;
filename "pxelinux.0";

в секции описывающей сеть или сегмент сети.

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

Про особенности работы в слоистой файловой системе было написано выше.


Добавление нового хоста в слоистую файловую систему


Как можно понять из описанного выше добавление нового бездискового хоста потребует внести изменения как минимм в трех местах на nfs сервере:

1. Cоздаем структуру в /DATA/hosts/newhost и /DATA/works/newhost
2. Делаем соответствующие записи в /etc/fstab
3. Создаем файл соответствующий IP адресу новой машины в /var/lib/tft[pboot/pxelinux.cfg/
4. Перегружаем все нужные сервисы.

Ну конечно же можно просто написать скрипт для автоматизации всего этого дела:

#!/usr/bin/python
import os, sys
import socket

ROOT_PATH = '/DATA'
EXPORT_PATH = '/exports'
BASE = 'base-centos7.4'
WORK_NET = '192.168.0.0/24'
EXPORT_CONF_FILE = '/etc/exports'
ROOT_TFTP = '/var/lib/tftpboot/pxelinux.cfg/'
IP_NFS_SERVER = '192.168.0.254'
LOWER_DIR = os.path.join(ROOT_PATH,'base',BASE)
BASE_WORK_DIR = os.path.join(ROOT_PATH,'works')


def ip_to_hex(ip):
    out = ''
    hex_symbol = ''
    for i in ip.split('.'):
        hex_symbol = hex(int(i)).replace('0x','').upper()
        if len(hex_symbol) == 1:
            hex_symbol = '0'+hex_symbol
        out += hex_symbol
    return out


def make_export_conf(EXPORT_CONF_FILE, export_row):
    with open(EXPORT_CONF_FILE,'r') as expfile:
        text_file  = expfile.read()
    if text_file.find(export_row) == -1:
        with open(EXPORT_CONF_FILE,'a') as expfile:
            expfile.write(export_row)
    return


def make_tftp_file(hex_name,EXPORT_DIR,ROOT_TFTP,if_name):
    conf_file_text = ''
    dict_replace = {'hostname':hostname,
                     'export_dir':EXPORT_DIR,
                     'ip_nfs_server':IP_NFS_SERVER,
                     'if_name':if_name}
    text_tpl = open('tftpboot.tpl','r').read()
    text_next = text_tpl
    for k in dict_replace.keys():
        conf_file_text = text_next.replace('{'+k+'}',dict_replace[k])
        text_next = conf_file_text
    print conf_file_text
    conf_file = open(ROOT_TFTP+'/'+hex_name,'w')
    conf_file.write(conf_file_text)
    return


def make_fstab(mount_row):
    with open('/etc/fstab','r') as expfile:
        text_file  = expfile.read()
    if text_file.find(mount_row) == -1:
        with open('/etc/fstab','a') as expfile:
            expfile.write(mount_row)
        os.system('umount '+EXPORT_DIR)
        print 'mount -t overlay overlay -o lowerdir='+LOWER_DIR\
                  +'/,upperdir='+UPPER_DIR+'/,workdir='+WORK_HOST_DIR+'/,index=on '+EXPORT_DIR
        os.system('mount -t overlay overlay -o lowerdir='+LOWER_DIR\
                  +'/,upperdir='+UPPER_DIR+'/,workdir='+WORK_HOST_DIR+'/,index=on '+EXPORT_DIR)
    return


count_args = len(sys.argv)
name_interface = 'eth0'
ip = None
print count_args
if count_args < 2:
    print "hostname is needed. python create_layer.py {hostname} "
    sys.exit(1)
# get name of network interface of machine
if count_args >= 2:
    hostname = sys.argv[1] #get hostname
if count_args >= 3:
    ip = sys.argv[2] #get ip address
if count_args == 4:
    name_interface = sys.argv[3] #get name ethernet

if not ip:
    IPHOLDER = socket.gethostbyname(hostname)
else:
    IPHOLDER = ip
hex_name = ip_to_hex(IPHOLDER)
print hostname
print ip
print name_interface
print hex_name



Ну и вызов этого скрипта: python create_layer.py {hostname}
Необходим хотябы один аргумент для этого скрипта - это имя бездисковой станции который прописан в ДНС сервере и для которого IP адрес соответствует выдамаемомы dhcp сервером.
Можно так же указать еще два аргумента это ip адрес (на случай если нет записи в ДНС) и имя интерфейса, если хочется указать какой именно интерфейс будет подключаться к сети и к nfs серверу.

Вот так можно все это создавать и автоматизировать.

Все успехов и удачи!

вторник, 11 сентября 2018 г.

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


Итак имеем:



Одна дисковая корзина с 4 мя дисками.

https://www.supermicro.com/products/chassis/2U/826/SC826BE2C-R741JBOD


Корзина поключена к двум машинам на каждой из которых установлен Proxmox 5.2


Внутри каждого хоста видно по 4 диска, каждый по 5 ТB

Что нужно получить?



Нужно чтоб диски были объеденены в рейд (1 или 10). При этом каждый из хостов должен уметь обрабатывать события рейда, так чтобы при выходе из строя одного из хостов второй без промедления продолжил работу, зная состояние рейда и имея возможность продолжить все что начал первый хост (если в момент выхода из строя первого хоста, этот первый хост что-то делал с рейдом, например выводил из строя умерший диск или восстанавливал данные на замененный диск). Другими словами нужна система кластерного рейда на двух хостах.


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

Это можно сделать, например, создав LVM группу и указать ее как общий ресурс для этих двух хостов проксмокса в настройках кластера проксмокса (через веб интерфейс).


Это нужно чтоб виртуальные машины которые будут создаваться как lvm разделы внутри этой lvm группы "жили" на этих двух хостах в HA кластере (High Availability). То есть хранилище образов машин у этих двух хостов одно и то же, и когда на нем появляется образ машины то оба хоста видят этот образ. И в том случае если один из хостов отказывает, то второй просто подхватывает образ машины и продолжает работать.

Возможные варианты

Первый и кажущийся самый простой вариант: использование линукс софт рейд - mdadm для создания рейда из имеющихся физических дисков. Далее мы получаем одно устройство в системе /dev/md0 , которое мы добавляем в LVM группу и добавляем в кластере проксмокса как общее хранилище. 

Второй вариант это использование возможностей самого LVM2. lvm сам умеет создавать рейды, правда рейд там не связан напрямую с физическими устройствами, а работает с группой LVM куда добавлены все физические устройства. Далее LVM разбивает все доступное пространство на логические разделы и делает из них рейд.
В нашем случае т.к. дисков четыре, то скорее всего границы условных разделов совпадают с физическими дисками, но если бы их было три или более четырех, то границы полос которые собираются в рейд располагались бы как попало , на разных дисках.
Но в любом случае избыточность данных обеспечивается.
На выходе мы получаем LVM раздел, который внутри себя содержит рейд.
Но теперь нам нужно создать еще одну группу LVM, добавить туда раздел с рейдом и добавить эту группу в проксмоксе как общую для данных хостов.
Можно использовать хитрую и мощную ZFS для того чтоб спомощью ее создать нужный рейд и получить в итоге директорию на каждом из хостов и добавить ее в проксмоксе как общую для хостов.
В этом случае образы виртуальных маших будут храниться уже как файлы, а не разделы. Что замедляет работу, т.к. включается в работу уровень файцловой системы.

Проблемы


Вариант с использованием mdadm страдает тем, что нет нормальной реализации работы mdadm в кластере. То есть, если на одном из хостов вы решили провести например замену диска, то второй хост об этом ничего не узнает и будет продолжать работать с этим рейдом как с нормально работающим рейдом.
Если диск реально вышел из строя, то оба хоста и их mdadm начнут как-то реагировать на это (помечать диск и сообщать о вышедшем из строя устройстве). Но потом при восстановлении данных, когда диск будет заменен, каждый из хостов будет производить по своему и риск попортить восстанавливаемые даные очень велик. Когда две машины пишут в одно и то же место не договариваясь (а работа с договоренностью и есть работа в кластере), это приводит к непредсказуемым результатам.
В проксмоксе нет поддержки работы mdadm как кластерного софта.
Есть специальные дистрибутивы линуксов, где такую возможность реализовали, но это коммерческие продукты и не совместимые с дебиан системами. Это связано с тем что mdadm используют модули ядра.
Например это реализовали вот в таком дистрибутиве:

https://www.suse.com/products/highavailability/

Так что на чистом проксмоксе невозможно реализовать рейд на базу mdadm, работающий в кластере. 


В варианте где используется LVM для создания рейда, тоже не все
Сам LVM умеет работать в кластере использую CLVM (реализация LVM для кластера). Но здесь проблема в том что в той реализации CLVM, которая используется в проксмоксе кластерными создается только первичная группа физических томов. То есть если использовать группу LVM, которая создана как кластерная и затем добавлена в кластер проксмокса как общаяя, то с ней нет никаких проблем. Машины создаются и перемещаются. НО! нам нужен еще рейд!
Когда мы создаем рейд средствами lvm у нас нет возможности указать что это тоже кластерный раздел.
Дело в том что любой раздел LVM созданный внутри кластерной группы LVM уже не считается кластерным и доступ к нему на редактирование разрешен только тому хосту который его создавал. Второй хост может получить к нему доступ только если первый хост выключен и второй хост при этом должен перегрузить свою систему LVM. По сути второй хост должен перегрузиться чтоб получить доступ к разделу созданному на другом хосте.
В этом и есть засада, дальше все надстройки над группой LVM созданной как кластерная не имеют смысла, т.к. они уже не могут быть кластерными. 

Вот пример создания рейд10 средствами LVM:
# lvcreate --type raid10 -m 1 -i 4 -L 200G -n myr10vol myvg

Кроме этого в некоторой документации по CLVM прямо пишут что кластерный рейд в LVM не поддерживается.


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

Кроме этого внешнего инструмента придется использовать еще и pacemaker и pcsd службы для создания кластерной инфраструктуры, которая будет обслуживать ZFS. Эти службы будут взаимодействовать с corosync, которая по умолчанию работает в проксмоксе. Все вышеуказанные службы по факту дублируют службы HA самого проксмокса и в каких то места могут конфликтовать ними. Например они могут претендовать на взаимодействие с dlm службой и не давать другим службам работать с dlm.
Получается что кроме того что сама ZFS не быстрая, она еще требует дополнительных служб и ресурсов.
Для того чтобы она заработала в кластере нужно использовать export import функции ZFS. Есть специальный агент который может отслеживать изменения и делать экспорт и импорт вовремя: https://github.com/skiselkov/stmf-ha/
Но настройка и запуск его весьма не тривиальная задача. Проект весьма сырой и поддрежка его очень не большая. Поэтому не стоит расчитывать что он будет работать надежно.


Возможные решения:


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

Давайте разделим задачу на несколько по функциям:

1. Нам нужно что-то что создает и поддерживает рейд из физических дисков
2. Нам нужно что-то что обеспечивает высокую доступность к общему хранилищу
желательно чтобы общее хранилище давало доступ к блочному устройству

поэтому первый вариант:


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

И дальнейшие работы с рейдом производятся на одной этой машине.

Сама эта машина содержит iSCSi сервер и предоставляет доступ к блочному устройству.

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

При выходе из строя одного из хостов проксмокса, кластер HA запускает машину с рейдом на втором хосте и хранилище снова доступно.

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

Вот здесь описано подробно как собрать такую схему:
http://yaricprog.blogspot.com/2018/09/jbod-raid10-proxmox-ve-ha-cluster.html


Еще один вариант

Это тоже отделение процессов от процессов хоста виртуальной машиной или линукс контейнером LXC.

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

в итоге машины тоже выдают на выходе iSCSI ресурс, но только выдают они каждый своему хосту.

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

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

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


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

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

Но это уже не совсем HA.

JBOD + RAID10 + Proxmox VE + HA cluster. Как сделать дешевое надежное хранилище.

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

Повторю исходные условия:
Имеем корзину с дисками (JBOD) по 5 Тб (4 диска).
Каждый диск имеет двойное проводное соединение с в двумя машинами, на которых устновлен Proxmox VE.
Таким образом мы имеем две системы (proxmox), в которых видны диски /dev/sda, /dev/sdb, /dev/sdc, /dev/sdd.

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

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

Итак начнем.

Подготовка хостов с проксмоксом.


Подготовим сначала основной диск, на котором установлен проксмокс. Это нужно сделать на обоих хостах.
Нужно сделать на основном диске отдельную партицию (первичный раздел). Размер этого раздела должен быть не меньше размер виртуальной машины для рейда + запас для разметки LVM. Минимальный размер , например Centos7.4  - 8 Gb. Поэтому если вы создатите раздел 10 - 15 Gb этого будет достаточно. Но это вы сами прикидывайте, т.к. если у вас машина с рейдом будет еще для чего-нибудь задействована, то может не хватить.
реть какой размер
И еще нужно убедиться, что при создании дополнительной партиции не пострадают данные в партиции где живет система проксмокса. Т.е. нужно посмотреть какой размер занимает сейчас проксмокс и оставлять ему этот размер с запасом.

Делается примерно так:


# fdisk /dev/sda

Command (m for help):d   - удаляем последнюю партицию

Command (m for help):n   - создаем новую партицию и указываем размер, который занимает проксмокс с запасом. А лучше это размер = прошлый размер последней партиции - размер создаваемой дополнительной партиции для виртуалки с рейдом (с запасом конечно).

Command (m for help): t  - Указываете тип партиции Linux LVM

Command (m for help): n   - создаем еще одну партицию теперь это уже для виртуалки

Command (m for help): t  - Указываете тип партиции Linux LVM

Command (m for help): w - записываем изменения на диск.

Теперь у нас есть  отдельный диск например /dev/sda4
Добавляем этот диск в LVM :


# pvcreate /dev/sda4


И добавляем группу drbd_pool . Фраза "drbd" должна быть обязательна для создания drbd пула.


# vgcreate drbd_pool /dev/sda4


Ну и гарантированно заполним предыдущий (обрезанный) раздел проксоксом:


# pvresize /dev/sde3

DRBD


Создаем пул для хранилища drbd

# lvcreate --size 15G --name drbdthinpool --thin drbdpool


Если у вас не установлен специальный пакет для thin-provisioning, то ставим его и еще пакет для работы с drbd:


# apt-get install thin-provisioning-tools drbdmanage -y


Теперь настроим хранилище drbd на этих вновь добавленный раздел.


# drbdmanage init -q 192.168.1.1
# drbdmanage add-node -q proxmox2 192.168.1.2
# drbdmanage nodes


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

Рассмотрим настройку конфигурации drbd хранилища.
После создания хранилища появляется файл /etc/drbd.d/drbdctrl.res
Добавляем в раздел net{ следующие строки:


        allow-two-primaries yes;
        after-sb-0pri discard-zero-changes;
        after-sb-1pri discard-secondary;
        after-sb-2pri disconnect;


После этого нужно убедиться, что раздел .drbdctl внутри drbd хранилища на обоих нодах являются primary. Если какая-то нода не является primary вы можете сделать ее такой :


# drbdadm primary .drbdctl


Не забудьте добавить drbd хранилище в конфигурацию проксмокса. Добавляем следующие строки в файл /etc/pve/storage.cfg:


drbd: drbd-hw
        content rootdir,images
        nodes hw1,hw2


Назвать этот ресурс можно назвать как угодно, проксмокс сам найдет нужный раздел в LVM, т.к. на одной машине он должен быть только один.

Особенности работы drbd в HA кластере расмотрим позже.

RAID10


Во-первых создаем виртуальную машину на одном из проксмокс хостов.
Учтите что основной диск этой машины должен располагаться в drbd хранилище.
Прокидываем в машину диски. Это делается через конфиги виртуальной машины. 
После того как вы создали машину, то в папке /etc/pve/qemu-server/ появляется файл типа 100.conf.
Добавляем в конец этого файла:

virtio1: /dev/disk/by-id/scsi-35000cca24d4f5394,backup=0,replicate=0,size=5860522584K
virtio2: /dev/disk/by-id/scsi-35000cca24d4f7534,backup=0,replicate=0,size=5860522584K
virtio3: /dev/disk/by-id/scsi-35000cca24d4f07c0,backup=0,replicate=0,size=5860522584K
virtio4: /dev/disk/by-id/scsi-35000cca24d4f08fc,backup=0,replicate=0,size=5860522584K

Обратите внимание здесь нужно прописывать именно UUID дисков. Их вы можете посмотреть в /dev/disk/by-uuid/
Это нужно чтобы когда диски будут использоваться на разных хостах проксмоксах они не перепутывались

backup=0  - означает, что проксмокс не будет складывать эти диски в бекап во время бекапирования.
replicate=0  - тоже самое касается репликации данных этих дисков между хранилищами  данных о машинах.

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

Я поставил  на машину Centos 7.4, поэтому дальше все описание будет для нее.

Делаем апдейд пакетов и ставим самые необходимые пакеты:

# yum update
# yum install mc mdadm targetcli

подготавливаем диски, они видны внутри виртуалки как /dev/vdb и т.д.:

# fdisk /dev/vdb
Command (m for help): n - создаем партицию.

указываем границы раздела, от первого блока до последнего чтобы использовать весь диск.
Далее не забываем:

Command (m for help): w - Записываем изменения на диск.

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

Создаем рейд10:

# mdadm --create --verbose /dev/md0 --level=10  --raid-devices=4 /dev/vdb1 /dev/vdc1 /dev/vdd1 /dev/vde1

Теперь у нас есть один большой диск /dev/md0.

После этого рейд начинает синхронизировать блоки на диске и процесс можно наблюдать вот таким образом:

# cat /proc/mdstat

Далее запускаем targetcli и настраиваем iscsi-server

# targetcli

targetcli shell version 2.1.fb46
Copyright 2011-2013 by Datera, Inc and others.
For help on commands, type 'help'.

/>

Далее нужно настроить ресурс для выдачи в сеть одного iscsi диска.
Подробно процесс описывать не буду, т.к. в интернете полно подобных описаний.

В итоге мы должны получить примерно вот такое:

/> ls
o- / ......................................................................................................................... [...]
  o- backstores .............................................................................................................. [...]
  | o- block .................................................................................................. [Storage Objects: 1]
  | | o- disk0 ........................................................................... [/dev/md0 (10.9TiB) write-thru activated]
  | |   o- alua ................................................................................................... [ALUA Groups: 1]
  | |     o- default_tg_pt_gp ....................................................................... [ALUA state: Active/optimized]
  | o- fileio ................................................................................................. [Storage Objects: 0]
  | o- pscsi .................................................................................................. [Storage Objects: 0]
  | o- ramdisk ................................................................................................ [Storage Objects: 0]
  o- iscsi ............................................................................................................ [Targets: 1]
  | o- iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.87fd8bccd4d6 ....................................................... [TPGs: 1]
  |   o- tpg1 .................................................................................................. [gen-acls, no-auth]
  |     o- acls .......................................................................................................... [ACLs: 2]
  |     | o- iqn.1993-08.org.debian:01:952561107f8e ............................................................... [Mapped LUNs: 1]
  |     | | o- mapped_lun0 ................................................................................. [lun0 block/disk0 (rw)]
  |     | o- iqn.1993-08.org.debian:01:bb376e9bb6b ................................................................ [Mapped LUNs: 1]
  |     |   o- mapped_lun0 ................................................................................. [lun0 block/disk0 (rw)]
  |     o- luns .......................................................................................................... [LUNs: 1]
  |     | o- lun0 ...................................................................... [block/disk0 (/dev/md0) (default_tg_pt_gp)]
  |     o- portals .................................................................................................... [Portals: 1]
  |       o- 0.0.0.0:3260 ..................................................................................................... [OK]
  o- loopback ......................................................................................................... [Targets: 0]
/>

Здесь мы видим, что iscsi сервер берет локальный (для виртуалки это локальный) диск /dev/md0 и выдает его в кчестве ресурса iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.87fd8bccd4d6
Также мы видим, что к этому ресурсу разрешено подключаться машинам с идентификаторами:
iqn.1993-08.org.debian:01:952561107f8e и iqn.1993-08.org.debian:01:bb376e9bb6b
И что сервер работает на порту 3260, поэтому нужно открыть этот порт в файерволле.

# firewall-cmd --permanent --add-port=3260/tcp
# firewall-cmd --reload

И запускаем службу iscsi сервера:

# systemctl enable target
# systemctl start target

Теперь заходим в веб интерфейс проксомкса и во вкладке Datacenter -> Storage и добавляем там ISCSI ресурс.

ID  - Любое имя для ресурса
Portal  - Сетевое имя или IP адрес Iscsi  сервера. В данном случае это адрес нашей виртуалки с рейдом.
Taget - Это  адрес сетевого ресурса. В нашем случае: iqn.2003-01.org.linux-iscsi.localhost.x8664:sn.87fd8bccd4d6
Nodes - здесь нужно указать имена только тех проксмокс хостов к которым будет подключен ресурс.

После подключения этого ресурса на хосте появляется еще один диск типа /dev/sdf

Теперь добавляем диск /dev/sdf в физические диски в LVM :


# pvcreate /dev/sdf


Далее создаем группу LVM :


# vgcreate raid10_vg /dev/sdf


Теперь в веб-интерфейсе добавляем эту группу в хранилище. Это нужно делать через конфигурацию проксмокса.
Открываем файл /etc/pve/storage.cfg и добавляем:


lvm: raid10_vg
        vgname raid10_vg
        content rootdir,images
        nodes proxmox1, proxmox2
        shared 1


Это нужно делать именно так, потому что через вебинтерфейс можно добавить только lvm группу pve, которую проксмокс создает автоматически.

Заметьте shared = 1 это обязательно, т.к. оба хоста должны видеть изменения в группе.

 HA Cluster

Теперь рассмотрим как настроить кластер высокой доступности.
В веб-интерфейсе проксмокса настройка HA кластера делается весьма просто на вкладке Datacenter -> HA.
Сначала во вкладке Groups создаем группу и добавляем в нее оба хоста проксмокса
Затем переходим в основную вкладку HA и добавляем машину с рейдом и все машины у которых диски находятся на этом рейде.

Теперь рассмотрим особенности работы HA кластера с drbd и виртуальными машинами.

Проксмокс может менять статус drbd ресурсов, которые создавал сам проксмокс.
Дело в том что диск типа raw на которых живут виртуальные машины это всего лишь LVM раздел который создал проксмокс. Когда он создает такой раздел в drbd пуле , он устанавливает статус primary для этого раздела на том хосте, на котором в данный момент располагается и работает виртуальная машина этого раздела.
Но вот специальный раздел .drbdctl не изменяется проксмоксом, поэтому в момент когда один из хостов проксмокса выходи из строя, то на втором ничего не меняется в специальном разделе drbd. Если на оставшемся в живих хосте работает primary спец раздел drbd, то перезд и запуск всех машин в HA кластере проходит нормально. Но если этот хост оказался с secondary спецразделом, то машиные переезжают на живой хост и не запускаются, т.к. доступ к дискам заблокирован самим drbd. То есть secondary нода drbd ждет появления primary ноды и не дает работать с хранилищем.
Поэтому нужно следить затем чтобы на обоих нодах drbd спецраздел должен быть primary.

Вторая особенность работы HA кластера это восстановление нормальной работы после восстановления упавшего проксмокс хоста.
После того как все ноды drbd увидят друг друга,скорее всего проксмокс вообще заблокирует  все созданные им ресурсы на упавшем хосте. Это выглядит как переименование файла ресурса в папке /var/lib/drbd.d/ во что-то типа raid10-iscsi-disk-1.res.old
Нужно привести имя файла к типу *.res и перегрузить drbd систему. И делается это не тривиальным способом, а именно нужно перегрузить сервис dbus:


# systemctl restart dbus


после этого ресурс появится в стаусе drbd, но будет помечен как StandAlone, это означает, что он не синхронизован с текущей актуальной версией данных на этом ресурсе.
Спецраздел .drbdctl на упавшем и восстановленном хосте скорее всего будет secondary  и его можно легко перевести в состояние primary, но перед этим стоит синхронизовать все созданные проксомоксом ресурсы, чтобы данные были актуальные и чтобы не потерять наработок, которые произошли во время восстановления хоста.
Для этого сделаем следующие манипуляцие с разделом (в данном случае это раздел машины с рейдом).

На восстановленном хосте пишем:


# drbdadm disconnect raid10-iscsi-disk-1
# drbdadm connect raid10-iscsi-disk-1 --discard-my-data


на уцелевшем хосте нужно просто отцепить и опять прицепить этот ресурс:


# drbdadm disconnect raid10-iscsi-disk-1
# drbdadm connect raid10-iscsi-disk-1


НО! проследите чтобы пока данные не синхронизовались уцелевший хост должен иметь primary  статус в разделе машины, а восстановленный secondary.
Хотя автоматически это и так проставляется при появлении ноды в кластере.

И последняя особенность HA кластера проксмокса - в нем нельзя специально проставить время задержки запуска машины при восстановлении ее на уцелевшем хосте проксмокса.
То есть при падении одного из хостов, через минуту HA кластер просто запускает все машины которые находятся в той группе в которой находятся и хосты проксмокса сразу безо всяких задержек.
А нам в данной ситуации важно запускать машины, которые живут в рейде на пару минут позже чем запуск самой машине с рейдом.
Но эту ситуацию можно исправить установив количество перезапусков при неудачном пуске 5 -6 раз, тогда проксмокс будет пытаться запустить машины живущие на рейде несколько раз пока запускается машина в с рейдом. Несколько не приятная ситуация, но в принципе рабочая.

Вывод:

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



пятница, 28 октября 2016 г.

пароли, пароли, пароли

Итак решил написать про то как хранить пароли от разных интернет сервисов не запоминая их.

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

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

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

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

Но как же это все запомнить?
Для этого существует менеджер паролей - это программа для хранения паролей в зашифрованном виде. У менеджера паролей есть один мастер пароль, который нужно хранить как зеница око. Но чтобы украсть все пароли нужно пробраться на компьютер  украсть файл с базой данных с паролями. Конечно стопроцентной защиты не существует. Но с менеджером паролей пароли могут "утечь" более вероятно в результате целенаправленной атаки. Поэтому мастер-пароль (от менеджера паролей) должен быть сложный и храниться супер секретно.

 Это действительно важно!

Ну обзор менеджеров паролей производить не буду потому что это уже сделали за меня и очень хорошо. вот например - https://habrahabr.ru/post/225053/ или вот http://www.securitylab.ru/analytics/472353.php
А вот здесь показали как можно поломать менеджеры паролей всякими хакерскими штучками:
https://xakep.ru/2014/09/08/password-manager-pentest/

И как результат на первое место выходит БЕСПЛАТНЫЙ keepass2...
Цитата: "Из всех пяти менеджеров паролей только один KeePass смог успешно противостоять всем трем атакам. Открытый код и постоянная поддержка со стороны энтузиастов сделали действительно достойный продукт"

Итак KeePass2


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




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

Как можно безопасно пользоваться менеджером?

Ну сначала добавим наш пароль в базу:



Здесь вполне понятные поля. Сложность пароля определяется автоматически. Можете сгенерировать пароль сами. Можете указать время действия пароля (тоже повышение безопасности). Можете в вкладке auto-type настроить автоматическое заполнение формы логина, если есть какие-то особенности.
Если заполните поле URL то будет возможность заходить на сайт автоматически, просто по кнопке.

И теперь например я хочу зайти на github.com:



1. в верхнем меню выбираю "открыть  URL" (есть возможность выбрать в каком именно браузере это сделать)
2. выбираю "скопировать имя в буфер", при этом начинается обратный отсчет, если я не скопипастю имя (логин) в нужное место на страничке, логин сотрется из буфера обмена. Это дополнительная защита от проникновения в буфер обмена.
3. выбираю пункт "скопировать пароль в буфер" и опять же обратный отсчет.
Копи-паст и я вошел в нужный сервис, я даже не видел пароля и никто его не видел, даже тот кто стоит у меня за спиной.
Есть также возможность автоматически заполнить форму логина, но не везде и не всегда этот способ отрабатывает корректно, особенно где есть всякого рода капчи не получается нормально залогиниться и там где ввод имени и пароля делается на разных страницах следующих друг за другом. Но, как я писал выше, есть возможность настроить автоматическое заполнение форм.

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

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

Существуют также клиенты KeePass под Android и поэтому можно логиниться даже с телефона.

Если базы паролей локальной версии и вновь загруженной с облака получились разные сам KeePass произведет синхронизацию и слияние паролей.

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

Я лично пользуюсь своим приватным облаком на базе опенсурсного owncloud.

Забыл сказать что KeePass позволяет использовать вместо пароля любой файл хранящийся у вас на машине. Это ключевой файл, про который знаете только вы. Но здесь есть опасность ... если вы потеряли этот файл  или изменили его то он перестанет открывать базу паролей. Лучше использовать не изменяемый файл. Ну и кроме того нужно будет иметь точно этот же файл на всех устройствах где вы предполагаете пользоваться менеджером. Это не очень гибко, а если положить этот файл в облаке, то злоумышленнику не трудно будет догадаться что это иенно и есть ключевой файл. Хотя если вы его так спрячете что никто и не поймет, то возможно можно обойтись совсем без паролей.
Главное быть уверенным что файл всегда будет доступен и будет неизменным.

Всем удачи! безопасной работы!