Автоматизация рабочих процессов была горячей темой примерно всегда. Как только появляется возможность решать какую-либо задачу более эффективным способом, сразу же возникает идея об оптимизации этого самого, казалось бы, уже совершенного способа.
Серверная виртуализация, как и zVirt в частности, не стала исключением среди других рабочих процессов. Пользователи желают решать задачи быстрее, операторы хотят уменьшать количество шагов и ручных операций, время доставки виртуальной машины потребителю — основная функция серверной виртуализации — должно уменьшаться. И снижение влияния человеческого фактора — благодатная почва для оптимизации.
Меня зовут Михаил Фучко, я технический продакт-менеджер SDN и Terraform в команде zVirt. В этой серии статей я расскажу о пути, который проделала наша команда в процессе разработки собственного провайдера инфраструктуры для Terraform. Поговорим об успехах и трудностях, о том, всегда ли можно положиться на решение с открытым исходным кодом, и о том, как запущенные десять лет назад «бумеранги» возвращаются, но не тем, кто их запустил.
Это первая часть цикла статей. В ней мы определимся с объектом автоматизации, обсудим ее основные концептуальные подходы и попытаемся сформировать глобальное видение результата. Для новичков в применении Ansible и Terraform данная статья может служить еще и небольшим введением в тематику. В последующих статьях сосредоточимся на инфраструктуре провайдера, поддержке ресурсов и их жизненных циклов и т.п.
Объект автоматизации
Для начала определимся с тем, что именно мы хотим оптимизировать. В нашем случае — процесс эксплуатации с��стемы виртуализации. Определим его цель как «размещение полезных пользовательских нагрузок в формате виртуальных машин с организацией сопутствующей инфраструктуры для их функционирования».
Действия в ходе этого процесса выполняет оператор системы виртуализации — по своему замыслу и плану. Заметим, что могут быть разные способы реализации замысла оператора, а следовательно и разные планы.
На примере zVirt схематично рассмотрим, с помощью каких инструментов (в широком смысле этого слова) пользователь может реализовать свой план для достижения замысла:

Итак, в базе своей, «из коробки» zVirt управляется с помощью следующих механизмов:
Web UI, графический пользовательский интерфейс. Построен на основе RPC-эндпоинтов по технологии GWT;
REST API, традиционный (уже) программный интерфейс, на основе HTTP-запросов и JSON \ XML объектов.
Внимательный читатель заподозрит неладное. Почему графический интерфейс использует отдельную ветку вызовов, а не опирается на REST API? Здесь и пришло время рассмотреть первый увесистый «бумеранг», отправленный разработчиками в будущее. При внедрении изменений нельзя останавливаться на половине, фарш нужно проворачивать до конца.
Суть проблемы — первые появления oVirt как гипервизора датируются 2008 годом, когда до полного доминирования концепции REST было еще далеко и она зародилась в oVirt как альтернативный доступ к внутренним функциям, тогда как UI использовал более оптимальные (с точки зрения разработчика на тот момент) и глубоко интегрированные с Java инструменты разработки интерфейса на основе GWT-RPC. Таким образом, с момента появления REST API в 2012 году в oVirt эти две ветки продолжали существовать параллельно, что критическим образом сказалось на качестве REST API. Если инструментом не пользоваться, по нему не будет накапливаться опыт эксплуатации, непонятно, как его чинить и куда улучшать.
Плохо скрываемая боль от необходимости активной борьбы с унаследованным API oVirt будет пронизывать все статьи этого цикла, можете мне поверить. Немного спойлеров, для затравки, пока без примеров:
Иногда что-то нельзя сделать через REST API, но можно через UI. Просто нет такого поля, его нельзя задать;
Иногда через REST API можно сделать что-то, что нельзя посмотреть в UI. Аналогично — ��росто нет таких полей;
Иногда сделанное через API вызывает «пятисотые» ошибки при чтении результата через UI;
Иногда пустой вызов REST API вызывает весьма серьезные изменения в нетривиальных местах.
Разработчики оригинального oVirt не стали доводить процесс до конца, так что мы в команде zVirt выполняем эту задачу сами. Сетевая оснастка, начиная с версии 4.5, уже полностью использует REST API и реализует модернизированный подход к менеджменту сетей. В процессе мы чиним баги оригинального API и делаем альтернативные реализации там, где это требуется. Если вам известно другое необычное поведение oVirt API, дайте знать.
«Сценарий» и «манифест»
Современная ИТ-автоматизация опирается на экосистему общепризнанных инструментов, у каждого из которых своя логика работы. Вендоры ПО добавляют поддержку продуктов через разработку плагинов. Ответственность за их качество лежит на разработчике (впрочем, иногда и на сообществе).
Средства автоматизации — это инструменты, с помощью которых оператор описывает сценарии, а система их выполняет. Они упаковывают рутинные операции в блоки и инструкции высокого уровня, которые оператор (уже как автор плана автоматизации) комбинирует в зависимости от ситуации. Инструкции обычно представлены в согласованной нотации, скриптовом языке высокого уровня, которые система автоматизации понимает и готова исполнять.
В автоматизации сложилось два принципиальных подхода к решению задач:
«Сценарий» — описание действий, необходимых для достижения результата. Оператор фиксирует желаемый результат, замысел, и описывает план действий на языке системы автоматизации, после чего запускает его на исполнение;
«Манифест» — описание результата, которого необходимо достигнуть. Оператор описывает результат на языке системы автоматизации, запускает его в работу, и система самостоятельно формирует план для достижения данного результата.
Первый подход дает больше контроля в моменте, но заставляет все продумывать самостоятельно. Второй позволяет сразу описывать желаемое целевое состояние, но заставляет мириться с выработкой плана автоматическими алгоритмами.
Ярким представителем «сценарного» подхода является проект Ansible. Это программный комплекс, который позволяет реализовывать заложенный сценарий через обращения к у��равляемым хостам по SSH и исполнения команд на месте. В основе лежит концепция плейбуков — наборов четких процедур («задач», «tasks»), из которых пользователь, как из кубиков, собирает итоговое решение. Разработчики ПО несут ответственность за эти «кубики».
Например, процедура создания виртуальной машины — она на вход принимает нужные параметры, а уже внутри Python-реализация делает все необходимые валидации, вызовы API и так далее. Задачи строятся вокруг модулей, наборы задач называются плейбуками, «пьесами».
В основном Ansible решает задачи управления программным обеспечением внутри готовой инфраструктуры (хотя тот же oVirt имеет Ansible-модули, пассатижами тоже можно забивать гвозди). Ansible проходит по готовому набору виртуальных машин («инвентарь») и исполняет высокоуровневые команды — установку ПО, создание конфигов, запуск контейнеров и т.п.

Ну а доминирующим представителем подхода «Манифест» является программный комплекс Terraform. Он как раз реализует концепцию «Инфраструктура как код». Здесь фокус уже на создание самих объектов инфраструктуры — виртуальных машин, дисков, сетей — а также их взаимоинтеграцию и регистрацию.
Пользователь описывает, что он желает видеть: «Три виртуальных машины, пять дисков, все это в одну сеть, на нее — правила межсетевого экрана, разрешить SSH на всех, RDP — только до этого сервера…» — а система уже формирует набор шагов, реализуя описанную разработчиком логику взаимосвязей:
Виртуальные машины, согласно манифесту, должны иметь подключенные диски. Видимо, сначала создадим диски;
Виртуальные машины при старте должны быть подключены к сети — значит, сначала создадим сеть;
Правила межсетевого экрана у нас применяются к портам виртуальных сетевых карт — ну, пора создавать виртуальные машины…
Таким образом Terraform, запуская разработанные поставщиком инфраструктурного ПО механизмы, строит граф зависимостей и принимает решение, что нужно создать раньше, что позже, а что можно создавать параллельно. Пользователь может немного влиять на его поведение, но в общем случае принимает его как данность.

Инфраструктура как код
Желание оптимизировать рутину и сэкономить пару минут вылилось в формирование полноценного подхода к управлению инфраструктурой — «Инфраструктуру как код». Действительно, если отдельные операции мы можем выполнять в формате, близком к кодовому (скрипты по сути те же программы), то почему бы не автоматизировать все, что только можно?
Что если вся инфраструктура управляется с помощью кода? А для создания виртуальной машины достаточно, чтобы в соответствующем файле было ее описание и данный файл прочел некий «компилятор»?
Разумеется, это светлый идеал, к которому стоит стремиться, но которого вряд ли можно достичь (вера в условный terraform и качество его логики принятия решений должна быть запредельной, а мы еще поговорим о необходимости «доверять, но проверять» в следующих статьях цикла).
Тем не менее концепция имеет право на жизнь: она применяется в очень гибких и динамичных инфраструктурах. Ключевое преимущество в том, что мы используем все лучшее из мира разработки: многолетние практики и целый класс вспомогательного ПО. Что бы мы могли от такого подхода получить:
Код можно выполнить сразу и массово — вместо ручной работы операторов;
Код выполняется с высокой степенью повторения и с минимизацией человеческого фактора — машины реже ошибаются;
Если инфраструктура — это код, то его можно положить в репозиторий! А значит версионирование, ветки, MRы, коммиты, полная история изменений, переключение на состояние инфраструктуры в нужный момент — все то, что программисты делают рутинно и постоянно, — теперь можно получить в свое пользование;
Самодокументирование: код уже документ, коммит кто-то выполнил, кто-то его принял — все в условном gitlab будет отражено, там же и вся инфраструктура согласований и проверок;
Метапрограммирование: программу могут писать другие программы. Код инфраструктуры может генерироваться самыми разнообразными средствами без необходимости вводить поддержку API вручную в каждое из них.
И все прочее, что можно придумать. Среди наших заказчиков есть опытные команды, которые уже используют подход на базе Terraform, поэтому от них и прозвучал справедливый вопрос: «А где?».
Резюме
Стремление вендоров добавить поддержку Terraform понятно и логично. Популярность концепции IaC растет, требования к скорости развертывания и доставки изменений растут, инфраструктура становится все более динамичной. Возможность продукта работать в такой парадигме может стать решающим преимуществом. Для zVirt это важно еще и в связи с необходимостью импортозамещать решения на базе VMWare — у них с работой в IaC все прекрасно. И в один прекрасный момент появился заказчик, которому «или так, или никак». Есть компоненты инфраструктуры, живущие по принципам IaC, и замещение виртуализации не должно привести к откату в развитии.
В следующей статье цикла мы чуть детальнее рассмотрим, что же такое Terraform и куда конкретно нам надо добавить свой код, чтобы обеспечить его полноценную поддержку. Если у вас появились вопросы — пишите в комментариях.
