MyBee — FreeBSD ОС и гипервизор bhyve как частное облако
В этой статье будет описано применение ОС FreeBSD в качестве платформы для запуска облачных гостевых ОС с использованием простого API на примере дистрибутива MyBee и тот DevOPS, который мне по нраву.
Введение
Периодически возникают мысли: 'не застоялся ли я' и руки сами открывают hh.ru с целью поискать что-нибудь эдакое вместо приевшихся технологий. Однако при перелистывании devops вакансий названия компаний меняются, а список технологий остается неизменным — осточертевшие: Linux, OpenStack, Docker, Kubernetes/Openshift, GitLab, Ansible, Terraform, с небольшими вариациями. Продукты коммерческих компаний с большими оборотами и инвестициями в разработку и раскрутку.
Это тот набор инструментов, среди которых любой почувствует себя как дома, если находится в современной devops индустрии хотя бы 2–3 года. Однако отсутствие альтернативных решений приводит к профессиональному выгоранию, работа вызывает чувство отвращения, усталость и потерю мотивации от однообразной деятельности.
Это терпимо, когда вы не настоящий IT-гик, но неприемлемо, если информационные технологии — это не только работа, но еще и хобби и вы ловите с IT фан. В этом случае вы не обращаете внимания на то, как именуется тот или иной кусок кода, в тренде он или нет, что пишет и думает о нем Анонимус. Интереснее самому попробовать, познакомиться с кодом/сервисами/архитектурой и если у вас имеется конкретная задача, на решение которой продукт ориентирован — попробовать решить на практике.
Подобная неудовлетворенность частично компенсируется экспериментами во вне рабочее время и участием в различных не апстримовых, малоизвестных и маргинальных проектах. Например, если говорить об ОС — всегда интересно поэкспериментировать c Minix, ReactOS, SmartOS, KolibriOS, MinocaOS, Haiku.
Особую нишу занимают дистрибутивы семейства BSD: они не только находятся в актуальном состоянии, заключающееся в том, что разработчики оперативно закрывают уязвимости, если таковые обнаруживаются. Но и регулярно выпускаются драйвера, обеспечивая работу систем на новом оборудовании. И если часть вышеупомянутых ОС заработает только в VirtualBox, то с BSD системами вы можете отдохнуть от линукс и с использованием физических мощностей.
Кроме того, эти системы достаточно 'чисты' в плане захламленности: нет переизбытка функциональностей базовых обязательных компонент, за ними не замечен постоянный deprecation-цикл всего и вся — чехарда, когда каждый год вместо доработки одной утилиты ей на смену приходит другая, полностью несовместимая с предыдущей. Верность традициям и следованию принципу KISS высоко ценят 'горячие головы', которые поднимают какой-либо сервис в промышленной эксплуатации на BSD платформах в стиле 'поставил и забыл'.
Любую деятельность, связанную с R&D в отношении ОС и прочего ПО удобно проводить с использованием виртуальных машин, ввиду наличия снапшотов (быстрый откат изменений) и возможности оперативно запускать и уничтожать любое количество экземпляров. В своей практике в промышленной эксплуатации мне приходилось использовал наверное все решения: начиная с облаков AWS, DO, Azure до self-hosted решений на базе OpenStack, OpenNebula, Proxmox, Triton Compute, Nutanix, XEN Orchestra. Использовал также и несколько отечественных разработок (как правило — это OpenStack с другим логотипом, либо Django-based приложения над virsh/kvm), не говоря уже про большое количество легковесных нашлепок к virsh/kvm, вроде Kimchi, virt-manager, nemu и другими фронтендами. Не смотря на обилие решений, я не мог найти инструмент с максимально простым и быстрым механизмом создания облачных ВМ. Кроме того, поддержка ZFS (высокий интерес к ней из-за качественного механизма снапшотов) есть у небольшого количества продуктов, а стабильность и надежность снапшотов на базе QCOW2 меня не удовлетворяли. В некоторых системах под 'снапшотом' и вовсе подразумевалась операция отправки образа диска на S3 хранилище с аналогичным восстановлением.
Поэтому для своих целей я использовал выделенный сервер под управлением FreeBSD ОС, в которой через командную строку и утилиту cbsd (аналог qm в Proxmox CLI) запускались облачные виртуальные машины на базе гипервизора bhyve и посредством ZFS происходила работа со снапшотами. (Для справки: bhyve является open-source BSD-licensed гипервизором второго типа и входит в базовую поставку ОС FreeBSD начиная с версии 10.0. В настоящее время портирован на платформы MacOS (xhyve) и SmartOS.) В какой-то момент времени ресурсы одного физического сервера были исчерпаны. Кроме того, исторически (примерно с таким слоганом:»ну у тебя же есть сервер — можешь мне ВМ дать? ») часть ресурсов была отдана знакомым под какие-то их сервисы, которые не смотря на 'да мне ненадолго! ' быстро заполонили мои сервера и время от времени по просьбам трудящихся приходилось с ними что-то сделать (снапшот, ресет…).
Путь пчелы
Передо мной встал выбор поиска системы, которая:
Бесплатная и без раздражающих 'я — бесплатная, но все же — оформите платную подписку, иначе тыкайте эту кнопочку все время!';
Прозрачное (не требующее с моей стороны дополнительных действий) масштабирование на несколько физических хостов;
Наличие какого-то элементарного RBAC, чтобы разделить свои ВМ от чужих;
Обязательное наличие API: да, у многих проектов очень приятный и развесистый UI, однако этот, безусловно хороший козырь нивелируется, когда речь заходит про автоматизацию и/или интенсивные циклы запуска-уничтожения;
ZFS-based, для снапшотов (не знаю пока ничего лучше 'zfs snapshot');
В связи с тем, что у CBSD несколько лет назад уже были описаны варианты и демонстрационный код для работы на нескольких серверах с API, CBSD, FreeBSD и гипервизор bhyve были оставлены в качестве основы. Требовалось изолировать свои виртуальные машины от чужих 'гостей' и гарантировать отсутствие коллизий в именовании серверов между нашими 'namespace'-ами.
Второе решалось элементарно — система должна выдавать всегда уникальную последовательность для новых ВМ, что можно имплементировать на sh одной строкой:
id=$(( id + 1 ))
и сохранить к этому ID маппинг к имени, которое запросил клиент.
Погружаясь в проблему RBAC, хотелось избежать создания учетных записей на сервере и при этом попытаться не усложнять API или логику.
При работе с API и заказом облачных (cloud-init) ВМ, пользователь оперирует базовыми: «число виртуальных ядер», «оперативная память», «объем диска», «образ ВМ», к которым не придраться, однако пятый параметр — это «public key» пользователя, который будет сохранен в качестве ключа пользователя (имя которого также может быть произвольным). Таким образом, «pubkey» оказался единственным параметром, который можно использовать для разделения и идентификации пользователей. Решение образовалась само собой — при запросе на создание ресурса, API подсчитывает md5(pubkey) и в дальнейшем оперирует этой суммой как ключем для контроля ВМ. Решение не годится, если API предоставляется незнакомым сомнительным личностям, однако не является проблемой при предоставлении доступа знакомым или коллегам, где в тестовой среде каждый и так может удалить все.
Доработка API с учетом требований заняла 1 полный день и работа выгружена на всеобщее обозрение. Что получилось на выходе:
Единая точка взаимодействия — API, который отправляет и принимает задачи на гипервизор (физические сервера) через брокер сообщений (в моем случае на эту роль был взят минималистичный beanstalkd), где каждый физический сервер подписывается на одну очередь именем себя. Добавление ноды в кластер производится запуском консумера на брокер и добавлением сервера в список серверов и их количество не ограничено.
У пользователей отсутствуют операции по логину, паролям или любым другим экстра-шагам для получения jwt/токена, каждый работает только со своими виртуальными окружениями, не боясь пересечений в именах ВМ с соседями.
Унифицированный интерфейс, где клиенту не обязательно знать что-нибудь о какой-то FreeBSD ОС.
Цена решения: потерянный 1 день на разработку, но это было время, проведенное с удовольствием.
Некоторые выводы
вывод номер 1: не смотря на обилие решений и перенасыщенность рынка, иногда бывает сложно найти продукт, который бы вас удовлетворил. И дело здесь вовсе не в том, что в трендовых продуктах отсутствует необходимая вам функциональность. Наоборот, хороший маркетинг и продакт оунеры никогда не спят: пытаясь получить максимально широкую пользовательскую базу, заставляют разработчиков реализовать все больше и больше самых разнообразных фич. Особенно это характерно для проприетарных коммерческих решений. Посмотрите на такие решения как VMware или kubernetes — их возможности сейчас сложно осознать и при этом многим 99% этих возможностей просто не требуется и не используются. Однако, используя 1%, зачастую вам приходится оплачивать наличие 99% остальных функций — речь не только о стоимости продукта или подписки: вы также получаете несколько томов документации по возможностям и конфигурациям продукта, плавать в которых можно месяцами. Иногда такие инструменты не кажутся инструментами, облегчающими вам жизнь. Не говоря уже о высоких требованиях к ресурсам, на которых они работают.
Вывод номер 2: в точечных и узких задачах, с помощью далеко не трендовых и маргинальных технологиях можно получить ту же эффективность дорогих и раскрученных трендовых решений и при этом потратить усилий в разы меньше.
вывод номер 3: (без относительно NIH-синдрома) — зачастую гораздо выгоднее имплементировать то, что вам нужно самим. Хороший пример — kubernetes. Чего от него хотят пользователи? Обычно требуется шедулер/супервизор сервисов и возможность скейлинга для вашего приложения. Можно купить OpenShift/Rancher, к нему нанять отдел из 10+ девопсов, которые изо дня в день 365 дней в году будут писать и переписывать ямлы, огребать проблемы и deprecate-ешены с каждым обновлением. Уверен что kubernetes нужен Google и он его использует правильно, однако все те компании где я работал, использовали его лишь чтобы запустить контейнер. Можно просто написать реализацию скейлинга и отказоустойчивости самому в своем приложении — благо, сегодня со Stack overflow и прочими https://copilot.github.com/ заниматься разработкой может каждый, а с тем объемом библиотек для репликаций, RAFT-алгоритмов и сопутствующими инструментами (брокеры, etcd, zookeeper), написать тот самый необходимый вам 1% возможностей VMware/K8S несложно, но при этом для вас это выйдет более увлекательным и захватывающим времяпрепровождением.
Кто знает — может быть постепенно настает время бойкотировать движение yaml-девопс, которое стало чересчур дорогим, раздутым и совершенно тупиково неповоротливым по сравнению с разработкой, поскольку сегодня должность DevOPS в большинстве компаний деградировала в «оператор kubernetes».
вывод номер 4: не смотря на то, что KVM/QEMU являются «золотым стандартом» среди open-source гипервизоров, а Linux платформы — мейнстримом, альтернативные ОС и решения продолжают появляться и развиваться. С учетом универсальности Linux/KVM нет никаких сомнений, что в случае проблем, я всегда смогу перенести работу на Linux, однако минимализм, где конструируете систему все еще вы, а не система вас — подкупает.
Встречайте: MyBee
В качестве сайд-эффекта и бонуса, а также для знакомства с работой гипервизора bhyve для людей, далеких от FreeBSD, работа была оформлена в виде отдельного дистрибутива под названием MyBee: https://myb.convectix.com, для работы с которым все что вам нужно — это curl (но также есть и тонкий клиент). Возможно, кто-то найдет эту работу полезной и для себя.
Что может MyBee и как с нею работать.
Установите утилиту «curl» (для работы с API) и «jq» (для более читабельного json при ответах). После установки MyBee на сервер, откройте в броузере IP адрес хоста для получения общей информации по возможностям:
http://IP
В базовой установке есть ссылки для следующих образов виртуальных машин:
«centos7»
«centos8» (CentOS Stream)
«ubuntu» (Ubuntu 20.x)
«debian» (Debian 10)
«freebsd_ufs» (FreeBSD 13.0, UFS FS)
«freebsd_zfs» (FreeBSD 13.0, ZFS FS)
«openbsd» (OpenBSD 6.x)
«netbsd» (NetBSD 9.x)
Но при желании список легко расширяем.
Определившись с конфигурацией желаемой виртуальной машины, создайте json файл (например: centos7.json) следующего вида:
{
"type": "bhyve",
"imgsize": "10g",
"ram": "1g",
"cpus": "2",
"img": "centos7",
"pubkey": "ssh-ed25519 AAAA..XXX your@localhost"
}
строка 3 и параметр »imgsize»: отвечает да объем первого/системного диска. Обычно он не меньше 3–4 GB.
строка 4 и параметр »ram»: отвечает за объем оперативной памяти ВМ.
строка 5 и параметр »cpus»: число vCPU виртуальной машины, ядер процессора.
строка 6 и параметр »img»: любое имя образа из списка выше.
строка 7 и параметр »pubkey»: ваш публичный ключ, который будет добавлен к пользователю гостя по-умолчанию.
curl -X POST -H "Content-Type: application/json" -d @centos7.json http://IP/api/v1/create/vm1 | jq
Если вы не делали предварительный «прогрев» образа виртуальной машины или создаете ВМ указанного профиля (img) впервые, пройдет некоторое время (зависит от скорости Internet в сети, где работает MyBee), прежде чем ВМ запустится и будет доступна. Все последующие операции по созданию этого образа будут происходить мгновенно. Если вы хотите с первых же запросов гарантировать моментальное создание, зайдите в консоль MyBee (ssh через непривилегированного пользователя с переходом в root: «sudo -s» либо «su -», либо через терминал/консоль) и введите соответствующее именование образа для прогрева:
При обращении на /create endpoint с корректным payload, система вернет вам список ресурсов для дальнейшей работы с API с использованием вашего токена (cid). Если вы пропустили или забыли его, не отчаивайтесь — получить cid можно, вычислив MD5 от вашей строчки публичного ключа. Этот cid является одновременно неким namespace, в котором группируются ваши ресурсы. Если вы пошлете аналогичный запрос, но с другим публичным ключем, ВМ будут созданы в другой группе. Список всех хостов в кластере и кусок cid вы можете увидеть, открыв dashboard MyBee по адресу http://IP/status:
После создания ВМ, дальнейшие операции которые могут быть вам интересны в первую очередь, это:
curl -H "cid:" http://IP/api/v1/cluster | jq
Статус индивидуального ресурса, где среди прочего вы можете найти строку для соединения в гостя посредством SSH:
curl -H "cid:" http://IP/api/v1/status/vm1 | jq
curl -H "cid:" http://IP/api/v1/destroy/vm1 | jq
Установка MyBee
Вам подойдет любой физический сервер на базе AMD/Intel x86–64 с поддержкой виртуализации (VT-x).
Установка MyBee может происходить с использованием ISO образа (https://myb.convectix.com/download/) или, если вы пользуетесь услугами Hetzner — запустить инсталлятор непосредственно из Hetzner rescue, инструкция для которого описана на отдельной странице: https://myb.convectix.com/hetzner/ .
В целом, процесс установки — это работа обычного FreeBSD installer, с которым не должно возникать много вопросов. Если же таковые возникли, вам поможет официальная документация по установке FreeBSD: https://docs.freebsd.org/en/books/handbook/bsdinstall/
Примечание
Небольшая вишенка на торте: если вы используете окружения FreeBSD, с помощью этого же API и методов вы можете создавать для себя jail вместо виртуальной машины. Для этого, в json при создании используйте значение «jail» в качестве «type», например:
{
"type": "jail",
"imgsize": "10g",
"pubkey": "ssh-ed25519 AAAA..XXX your@localhost"
}
Также, существует отдельный тонкий клиент для работы с MyBee API, билды которого доступны под все современные ОС, если вы сочтете взаимодействие через curl не дружелюбным (или используете ограниченные ОС, где curl и jq так просто не поставить). Например, вы можете работать с MyBee из Windows ОС следующим образом:
nubectl-windows status --cloudkey="c:\authorized_keys" --cloudurl=http://IP
nubectl-windows create vm --cloudkey="c:\authorized_keys" --cloudurl=http://IP
nubectl-windows ssh vm --cloudkey="c:\authorized_keys" --cloudurl=http://IP [--sshkey=c:\id_ed25519]
Благодарю за внимание и интерес, находите радость в работе, даже если эта работа — DevOPS;-)