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 API модуль

Введение

CBSD позволяет пользователю создавать окружения на разных уровнях абстрации, предоставляя большое количество методов по созданию окружений - CBSDfile, команды [jb]create, которые работают как по конфигурационному файлу, так и через аргументы командной строчки. Наконец, вы можете использовать интерактивные диалоговые меню ([jb]construct-tui). Несмотря на разнообразность, все эти варианты требуют заходить на сервер каждый раз через ssh и вводить соответствующие команды. RestAPI сервис добавляет для вас еще одну опцию по управления окружениями, позволяя отказаться от необходимости использовать ssh, где вы взаимодействуете с CBSD фреймворком через HTTP/RestAPI запросы.

Архитектура API сервиса поддерживает работу как на одной ноде, так и позволяет охватывать несколько нод, предоставляя вам возможность легким образом построить частное программируемое облако для запуска виртуальных окружений, что выводит CBSD на новый уровень управления окружениями. Помимо классического запроса через HTTP (например через утилиту curl), API поддерживается файлом CBSDfile, что дает очень мощный и в некоторых случаях, еще более комфортный деплой сервисов в частном облаке. Но об этом ниже.


private FreeBSD multi-node bhyve/jail cloud via API demo:

Давайте зафиксируем терминологию, которая будет использована в этой статье.

  • CBSD - набор скриптов, реализующий управление виртуальными машинами на самом низком уровне. Вам потребуется CBSD не ниже 13.0.1. Если версия ниже, пожалуйста, обновитесь перед тем как вы начнете.
  • ZPOOL - ZFS пул, в котором проинициализировано рабочее окружение CBSD. По-умолчанию, рабочий каталог CBSD инициализируется в /usr/jails.
  • Broker - основная шина данных общения между сервисом cbsd-mq-api (один) и cbsd-mq-router (может быть в любых количествах). В текущей статье роль брокера выполняет beanstalkd.
  • Tube - труба (в терминологии beanstald) - FIFO-очередь в брокере, в которую пишет (publish) cbsd-mq-api, а cbsd-mq-router - читает (subscribe).
  • Hypervisor (не путать с bhyve hypervisor) - физическая нода под управлением FreeBSD OS. Количество нод неограничено. Каждый гипервизор имеет как минимум 1 ZPOOL. Каждый пул обслуживается процессом cbsd-mq-router, подписывающийся на персональную pool-очередь для обработки инструкций CBSD.
  • API - сервис (public), предоставляющий RestAPI или json-rpc для взаимоимодействия конечных пользвателей ( curl/UI frontend ). В нашем случае простейшей реализацией будет сервис cbsd-mq-api.

Начнем с рассмотрения самой простой однонодовой инсталляции.

Standalone API

Установка и настройка CBSD API в режиме standalone.

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

1) Установим брокер сообщений

pkg install -y beanstalkd

Укажите через флаг в rc.conf, на каком адресе будет ожидать подключения beanstalkd. Поскольку у нас все-в-одном, все подключения не будут выходить за границу localhost, поэтому указываем 127.0.0.1 в качестве адреса для прослушивания:

sysrc beanstalkd_flags="-l 172.16.0.5 -p 11300"

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

service beanstalkd enable
service beanstalkd start

2) На момент публикации статьи, cbsd-mq-api не присутствует в системе портов FreeBSD и его нет в pkg репозитории. Получим сервис через исходные коды. Для этого нам потребуется установить пакет git (достаточно git-lite) и go:

Либо из GitHub:

pkg install -y git-lite go

Склонируем репозиторий, соберем и проинсталлируем сервис:

git clone https://github.com/cbsd/cbsd-mq-api.git /root/cbsd-mq-api
/root/cbsd-mq-api/build.sh
cp -a /root/cbsd-mq-api/cbsd-mq-api /usr/local/bin
cp -a /root/cbsd-mq-api/etc/cbsd-mq-api.json /usr/local/etc/
cp -a /root/cbsd-mq-api/rc.d/cbsd-mq-api /usr/local/etc/rc.d/

3) Установим дополнительные файлы в CBSD через модуль api:

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

4) Выполняем настройку API:

Создадим необходимую структуру каталогов для API:

mkdir -p /var/db/cbsd-api ~cbsd/var/db/api/map
chown -R cbsd:cbsd /var/db/cbsd-api ~cbsd/var/db/api/map

Отредактируйте конфигурационный файл /usr/local/etc/cbsd-mq-api.json:

a) Параметр server_url должнен указывать на имя или IP адрес вашего API сервиса, доступный для внешних подключений. Этот URL as-is будет подставляться в качестве рабочего endpoint. В нашем случае, в окружении рабочий внешний IP адрес - 172.16.0.5, поэтому полная строка настройки будет выглядеть так:

"server_url": "http://172.16.0.5:65531",

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

service cbsd-mq-api enable
service cbsd-mq-api start

Скопируйте конфигурационный файл для сервиса и укажите хотя бы один CBSD хостер в параметре server_list=

cp -a /usr/local/cbsd/modules/api.d/etc/api.conf ~cbsd/etc/
chown cbsd:cbsd ~cbsd/etc/api.conf
vi ~cbsd/etc/api.conf

Параметр server_list должен содержать участников кластера (обычно это имена хостов), разделенные пробелом. Сервис использует эти имена в качестве адресатов для рассылки задач через beanstalkd.

Например, в нашем случае имя ноды с CBSD - cloud1.my.domain, поэтому api.conf будет содержать строку:

server_list="cloud1.my.domain"

Вы можете проверить корректность отработки выдачи рекомендаций хоста, на котором запускать новое окружение, запустив скрипт /usr/local/cbsd/modules/api.d/misc/recomendation.sh: он должен вернуть имя сервера.

5) Настройка cbsd-mq-router.

Установите сервис:

pkg install -y cbsd-mq-router

Или из портов:

env BATCH=no make -C /usr/ports/sysutils/cbsd-mq-router install

Отредактируем файл /usr/local/etc/cbsd-mq-router.json, указав корректный адрес нашего beanstalkd брокера в параметре "uri" в секции beanstalkd, в нашем случае это:

    "uri": "127.0.0.1:11300",

Нам также необходимо зафиксировать имя трубы в брокере, на которую будет подписан сервис cbsd-mq-router настраевомого хоста. Для этого, измените параметры tube и reply_tube_prefix в cbsd_<имя_сервера> и cbsd_<имя_сервера>_result_id соответственно, где в имени сервера символы '-' и '.' преобразуются в '_'.

Так, имея CBSD хост с именем cloud1.my.domain, в файле /usr/local/etc/cbsd-mq-router.json должны быть записи:

      "tube": "cbsd_cloud1_my_domain",
      "reply_tube_prefix": "cbsd_cloud1_my_domain_result_id",

Если ваше рабочее окружение CBSD имеет отличное от стандартного /usr/jails, откорректируйте путь в параметре cbsdenv.

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

service cbsd-mq-router enable
service cbsd-mq-router start

Ваш первый standalone кластер готов вас обслуживать!

API: jail

Работа с JAIL через API

Создадим простейший payload для создания контейнера, например файл jail.json

jail.json:


{
  "type": "jail",
  "imgsize": "10g",
  "pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILdzM3pm65J28zNt/YcRWSw4NXa8PKU8MhrbA/CShuEm olevole@jhoster1.olevole.ru"
}

Разумеется, в качестве pubkey подставив свой публичный ключ. Отправим его в endpoint по созданию контейнера, где /jail в конце означает имя окружения (произвольное)

curl -X POST -H "Content-Type: application/json" -d @jail.json http://172.16.0.5:65531/api/v1/create/jail

При этом API подсчитает md5 хеш от вашего pubkey и результат чек-суммы автоматичеки станет вашим токеном, который вы можете использовать для контроля окружений и одновременно будет неким namespace-ом в кластере, в котором вы будете видеть все ресурсы, создававемые с вашим публичным ключем.

Так, если потребуется уничтожить окружение, используйте GET запрос на ендпоинт /destroy, используя ваш хеш. Получите md5 сумму вашего ключа, если вы его все еще не знаете ;)

md5 -qs "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILdzM3pm65J28zNt/YcRWSw4NXa8PKU8MhrbA/CShuEm olevole@jhoster1.olevole.ru"

используйте его в запросе:

curl -H "cid:678851e352136726da5e6c52126eb906" http://172.16.0.5:65531/api/v1/destroy/jail

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

Еще пара слов о конфигурации API для jail. Скрипт работающий с jail через API может использовать конфигурационный файл с именем jail-api.conf, который должен быть расположен в каталоге ~cbsd/etc. Пример этого файла вы можете посмотреть здесь: /usr/local/cbsd/modules/api.d/etc/jail-api.conf

На данный момент файл регулирует, позволять ли пользователю указывать в payload версию FreeBSD базы для контейнера, пул IP адресов и внешний IP адрес для доступа в контейнер, выдаваемый пользователю. По-умолчанию версию FreeBSD base для контейнера не пропускаем, какое бы значение не прислал пользователь: API будет создавать контейнер под версию вашего гипервизора ( ver=native ). Поскольку на выдачу адресов пользователь облака не влияет и этим занимается CBSD, вы можете назначать любой пул,как внешних адресов, так и частных.

API: bhyve

Работа с виртуальными машинами bhyve через API

Работа с виртуальными машинами имеет аналогичный интерфейс и endpoint, как и в случае с jail, но имеет немного другой payload для создания окружения. Кроме этого, вы должны провести настройку по соответствию имени запрашиваемого образа с профилем CBSD. Как и у скрипта для jail, скрипт работающий с bhyve также имеет конфигурационный файл. Скопируйте пример конфигурационного файла:

cp -a /usr/local/cbsd/modules/api.d/etc/bhyve-api.conf ~cbsd/etc/
chown cbsd:cbsd ~cbsd/etc/bhyve-api.conf

Как и в случае с jail, вы также можете регулировать правила выдачи IP адресов виртуальным машинам. И вы можете регулировать, какой IP адрес будет выдан пользователю для доступа SSH на создаваемый ресурс - либо будет отдан прямой IP адрес виртуальной машины, либо CBSD создаст expose правило для SSH на любом свободном порту. В этом случае, пользователь получит IP адрес гипервизора и порт, который будет форвардить запросы на 22/ssh порт виртуальной машины.

Пример payload, например centos7.json:

{
  "type": "bhyve",
  "imgsize": "10g",
  "ram": "1g",
  "cpus": "2",
  "img": "centos7",
  "pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILdzM3pm65J28zNt/YcRWSw4NXa8PKU8MhrbA/CShuEm olevole@jhoster1.olevole.ru"
}

И создается аналогичным запросом что и jail:

curl -X POST -H "Content-Type: application/json" -d @centos7.json http://172.16.0.5:65531/api/v1/create/cent7

CBSDfile + API

CBSDfile + API

И на закуску, в качестве ягодки на торте

В некоторых случаях curl и RestAPI - намного удобнее ssh + `cbsd bcreate/bconstruct-tui`. Если вам приходится много и часто деплоить виртуальные окружения, вам не избежать необходимость изучить и использовать какой-нибудь язык высокого уровня. Curl и HTTP запросы хорошо подходят, если вы разрабатываете на базе CBSD программируемое облако, однако для людей это не очень удобно. В качестве промежуточного варианта, существует еще один гибридный и неявный вариант использования API - через CBSDfile. Если вы не знакомы с этой возможностью CBSD - непременно ознакомьтесь. Для того, чтобы использовать CBSDfile в вашем частном облаке, вам достаточно добавить в начало CBSDfile всего два параметра - это Endpoint вашего API и ключ. Наличие этих двух параметров заставит CBSD переключиться при создании с локальной инсталляции CBSD на облако. А это может предоставлять уже совершенно нового уровня возможности (пример взаимодействия с multi-node кластером)!

Multinode API

Мультинодовый API/CBSD кластер

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

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

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

Здесь дается любой полет фантазии для имплементации логики на любом удобном для вас языке программирования и использования любых алгоритмов. Так, например, если часть ваших серверов имеет высокопроизводительные но небольшого объема NVME диски и часть серверов - емкие, но медленные hdd, вы можете легким образом реализовать простую логику вида

Если запрашивается виртуальная машина с объемом диска > 500GB - выбирать из списка серверов с hdd.

Вместе с модулем API поставляются два скрипта на sh, которые в качестве примеров дают уникальный ID в качестве имени виртуальной машины и выдающий сервера по алгоритму round-robin. Что должно хватать для запуска полноценного мультинодового кластера за 10 минут. Давайте сделаем это.

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

Начнем с настройки API сервиса. По отношению к standalone конфигурации, в файле ~cbsd/etc/api.conf мы расширяем список на необходимое количество участников в кластере, напрмер:

server_list="srv-01.olevole.ru srv-02.olevole.ru srv-03.olevole.ru bob.your-server.de"

Вы можете проверить, что скрипт рекомендаций ( /usr/local/cbsd/modules/api.d/misc/recomendation.sh )по-умолчанию предлагает хосты в round-robin:

WIP...