FreeBSD virtual environment management and repository

2020-10 upd: we reached the first fundraising goal and rented a server in Hetzner for development! Thank you for donating !

Внимание! Данные страницы описывают CBSD версии 13.0.x. Если вы используете более раннюю версию, рекомендуется сначала обновиться.

Пример интеграции CBSD с MONIT (health-check).

Введение

Если вы посмотрите на список ПО, посвященного управлению jail на FreeBSD, то наверняка отметите, что дефицита в количестве подобного рода утилит нет. Различные jail (актуально и для bhyve/XEN) врапперы предоставляют на любой вкус формат записей директив, команд и аргументов. Однако все они (включая CBSD, конечно), в основном, предлагают одинаковые операции и возможности с незначительными отличиями, а именно: базовые 'создание', 'удаление', 'запуск' и 'остановка' окружений. Но никто не идет дальше: сущности более высокого уровня, такие как контроллер, супервизор, health-check, DRS и т.д. - отсутствуют как класс. Без доработок, это ограничивает круг применения jail/bhyve врапперов до масштабов локаххоста, из-за отсутствия возможности прозрачно использовать деплой на группу физических нод. Этому есть достаточно логичное объяснение - в современных реалиях довольно опрометчиво пытаться решить все проблемы вселенной одним продуктом. Именно поэтому CBSD уделяет большое внимание возможностям интеграции с инструментами, которые расширяют возможности CBSD фреймворка для предоставления пользователям дополнительных возможностей.

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

Другие главы этой серии:


Почему Monit? Когда в 2021 году мы говорим об автоматическом перезапуске контейнеров в зависимости от определеных условий, на ум сразу приходят такие монструозные Linux-центричные решения, как OpenShift, Kubernetes, Systemd...

В лагере FreeBSD, скорее всего наиболее близко будет использование продукта от HashiCorp под названием Consul. Продукты HashiCorp славятся тем, что имеют крайне хорошую интеграцию между собой: всем известна шайка из закадычных друзей: Nomad, Consul и Vault.

Это неплохой и качественный современный стек, но мы выберем путь минимализма и простоты, где наша задача - выбор не по принципу 'о чем говорят все', а наибее дешевом и легковесном решении поставленной задачи - мониторинг и рестарт сервиса, где функциональностей monit для нас более чем достаточно. Для оценки разницы, достаточно взглянуть хотя бы на разницу потребляемых ресурсов обоих сервисов:

  monit consul
размер исполняемого файла: 425 Kb78 Mb
потребление RAM без чек-правил (default):25 Mb 80 Mb


Кроме этого, цель статьи - показать саму концепцию, которая леко может быть использована с любыми другими, более массивными инструментами.

Идея и архитектура

monit работает по конфигурационному файлу monitrc, в котором перечислены правила проверок тех или иных событий и реакция на них. Наша задача - при создании контейнера добавлять в рантайме правила, если у контейнера есть что проверять. И соответственно, снимать с мониторинга, когда контейнер остановлен или удаляется. В качестве реакции на неуспешный тест, заставим monit перезагружать контейнер. Это означает, что каждый физический CBSD-хост будет запускать свой уникальный экземпляр monit, работающий только с локальными окружениями. Конечно, мы можем обойтись и одним monit, который будет проверять все, но это будет являться single-point-of-failure, что потребует дополнительных трудозатрат по обеспечению надежности самого внешнего сервиса monit.

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

В этом примере мы можем проверять доступность TCP порта или определенного контента по HTTP протоколу, поэтому из всех динамических параметров, от CBSD процессу monit будут нужны лишь два - имя контейнера (для рестарта) и IP адрес, доступность порта на котором и будет проверяться. Для этого заготовим шаблон в каталоге ~cbsd/jails-system/JNAME/monit/ из которого при старте, останове или удалении, будет формироваться или удаляться рабочая конфигурация monit, при обновлении которой, основной процесс monit должен ее перечитать. Простейшая имплементация в качестве примера реализована с использованием shell скриптинга в виде одноименного модуля для CBSD.

Установка и конфигурирование monit

Установим monit через pkg:

 pkg install -y monit
	

Скопируйте пример конфигурационного файла в рабочий и допишите в конце директиву подключения всех конфигурационных файлов в ~cbsd/jails-system/*/monit/monitrc - их будет генерировать модуль. Обратите внимание, что /usr/jails (рабочий каталог CBSD) в вашем случае может отличаться:

 cp -a /usr/local/etc/monitrc.sample /usr/local/etc/monitrc
 echo 'include /usr/jails/jails-system/*/monit/monitrc' >> /usr/local/etc/monitrc
	

Конфигурирование CBSD

Выполним установку модуля, как описывает страничка проекта:

  cbsd module mode=install monit
  echo 'monit.d' >> ~cbsd/etc/modules.conf
  cbsd initenv
	

Скопируем скрипты, которые будут запускаться в качестве destroy/start/stop хуков окружений. Примеры этих скриптов находятся здесь: /usr/local/cbsd/modules/monit.d/share.

mkdir -p /root/share/cbsd-monit
cp -a /usr/local/cbsd/modules/monit.d/share/*.d /root/share/cbsd-monit/
	

В /root/share/cbsd-monit/ у нас теперь находятся три каталога по имени каталогов, которые отрабатывают в CBSD при определенных событиях:

  • master_poststart.d - работает после запуска окружения;
  • master_create.d - работает при создании нового окружения;
  • remove.d - работает при уничтожении окружения;

Внутри каждого каталога находится выполняемый файл monit.sh, который и будет выполнять все действия.

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

для jail:

ln -sf /root/share/cbsd-monit/master_poststart.d/monit.sh ~cbsd/share/jail-system-default/master_poststart.d/monit.sh
ln -sf /root/share/cbsd-monit/master_prestop.d/monit.sh ~cbsd/share/jail-system-default/master_prestop.d/monit.sh
ln -sf /root/share/cbsd-monit/remove.d/monit.sh ~cbsd/share/jail-system-default/remove.d/monit.sh

для bhyve:

ln -sf /root/share/cbsd-monit/master_poststart.d/monit.sh ~cbsd/share/bhyve-system-default/master_poststart.d/monit.sh
ln -sf /root/share/cbsd-monit/master_prestop.d/monit.sh ~cbsd/share/bhyve-system-default/master_prestop.d/monit.sh
ln -sf /root/share/cbsd-monit/remove.d/monit.sh ~cbsd/share/bhyve-system-default/remove.d/monit.sh

При запуске контейнера, скрипт проверяет наличие темплейта в системном каталоге окружения: ~cbsd/jails-system/JNAME/monit/monitrc.tpl. При наличии такового, используется sed для реплейса сигнатуры %%JNAME%% и %%IPV4_FIRST%% в темплейте на значения переменных фактов ${jname} и ${ipv4_first}, создавая итоговый файл ~cbsd/jails-system/JNAME/monit/monitrc. Эотт файл обрабатывается через добавленный нами include из основного конфигурационного файла /usr/local/etc/monitrc. Конечно, вы можете захотеть добавлять и использовать другие факты при необходимости. Кроме генерации конфигурационного файла, скрипты выполняют reload сервиса для применения конфигурации.

На этом настройка monit и CBSD завершена! Нам остается создавать в системном каталоге конфигурацию для monit по проверке тех или иных событий, пользуясь стандартной документацией monit.

Пример

Давайте создадим контейнер с именем lb1, в котором предполагается использование WEB сервера на базе nginx в качестве load-balancer. monit настроим на проверку открытого 80/tcp порта и в случае, если сервис nginx по каким-то причинам не обслуживает этот порт, заставим monit перезагрузить контейнер.

Создадим контейнер с nginx:

 cbsd jcreate jname=lb1 pkglist=nginx sysrc=nginx_enable=YES
	

Скопируем пример для проверки и рестарта контейнера без каких-либо модификаций в каталог ~cbsd/jails-system/lb1/monit/:

 mkdir ~cbsd/jails-system/lb1/monit/
 cp -a /usr/local/cbsd/modules/monit.d/share/monitrc.tpl ~cbsd/jails-system/lb1/monit/
	

Запустим контейнер и проверим конфигурацию monit через monit status. Сервис должен иметь задачу с именем контейнера lb1:

 cbsd jstart lb1
 monit status
	

Теперь симулируйте отказ в ослуживании nginx, достаточно его просто остановить:

cbsd jexec jname=lb1 service nginx stop
	

и наблюдайте что произойдет дальше.

Удачи, попутного ветра и легких облаков!