Есть такой тренд сейчас - работать с IT-инфраструктурой как с кодом. Хорошо цель этого метода описывается этой цитатой:
“Enable the reconstruction of the business from nothing but a source code repository, an application data backup, and bare metal resources”
– Jesse Robins
Я полностью поддерживаю эту идею, причем именно в этой трактовке.
Если говорить про парадигму, которую нам предлагает этот метод, то вот она:
Поддерживать модульную, легко поддающуюся автоматизации инфраструктуру, и описывать эту инфраструктуру с помощью языка высокого уровня.
Это означает для нас, как сисадминов, что мы должны пользоваться всеми наработками разработчиков ПО, такими как:
- версионирование описания инфраструктуры;
- полноценное тестирование описания с использованием нескольких стадий (dev, QA, staging, prod);
- внутренние стандарты “кодинга”;
- непрерывная интеграция (continuous integration).
Проблема же, на мой взгляд, заключается в том, что многие понимают “Инфраструктуру как код” в другом смысле - “Давайте писать описание нашей инфраструктуры с помощью Chef/Puppet, словно это обычный код”. Причем у Chef это выражено заметно сильнее, поскольку в качестве DSL используется чистый Ruby.
Конечно, программисты, каким-либо образом ставшие ответственными за администрирование серверов с помощью Chef, с радостью начинают использовать привычный инструмент (Ruby) привычным же образом, и получается ровно то, что они привыкли делать. Вместо декларативного описания инфраструктуры, на которое можно натравить какой-нибудь инструмент для управления конфигурациями и получить настроенную инфраструктуру, на выходе получаем программу с кучей хаков, с множественным ветвлением, с выполнением кода на Shell, которая может императивно привести систему к нужному состоянию.
Примером может являться практически любой стандартный кукбук Chef. Взять хотя-бы Nginx cookbook. Он умеет ставить Nginx несколькими способами, включая сборку из исходников, и содержит в себе тонну переменных, призванных заменить написание вменяемого шаблона конфига Nginx заданием значений этой кучи переменных.
Это уже сам по себе плохой подход - пытаться впихнуть все возможности Nginx (да еще и со сторонними модулями) в один мега-шаблон, и править только переменные.
Сборка из исходников в кукбуке тоже вызывает массу вопросов. Зачем это делать на боевом сервере? Собрать пакет на build-сервере, протестировать его, и распространить из своего репозитория по всем серверам - вот это нормальный подход.
И все это порождает столько сложностей, столько труда нужно для написания, тестирования и поддержания в актуальном состоянии этого кукбука, вместо того, чтоб разделить весь процесс на несколько простых шагов:
- Собрать пакет Nginx с нужными модулями на build-сервере, протестировать и поместить в репозиторий;
- Написать шаблон конфига Nginx под ваши задачи, учитывающий различия между имеющимися средами (staging/prod);
- Написать кукбук/манифест/роль, который будет ставить пакет из вашего репозитория, заполнять шаблон переменными, которые отличаются в ваших окружениях, и класть этот шаблон на сервер.
Вот и все, не нужны тонны кода на Ruby со вставками на Shell, не нужны сотни переменных. У нас есть описание процесса сборки пакета (spec-файл или Makefile), и декларативное описание требуемого состояния системы.
И это прекрасно подходит под один из принципов Экстремального Программирования, который звучит так:
Do The Simplest Thing That Could Possibly Work
То есть, надо сделать так, чтобы наш кукбук/манифест/роль был достаточно простым для того, чтобы удовлетворять нашим сегодняшним требованиям. Конечно, увлекаться и делать что-то “в лоб”, не думая, будет неверно, но и создавать псевдо-универсальных монстров точно не стоит. Во всем нужна мера.
Что самое плохое - люди, которые пишут сам Chef, и написали этот кукбук для Nginx. Написали хорошо, но написали как программисты, а не как системные администраторы. А когда сисадмины пишут кукбуки в таком стиле, на их творения вообще без слез не взглянешь.
Именно поэтому я выбрал для управления серверами Ansible, созданный Michael DeHaan, человеком, который работал в Puppet Labs, создал Func и Cobbler, а затем, имея большой опыт и видя ошибки предшественников, написал Ansible. Ansible заметно проще Chef или Puppet, и декларативный YAML-файл с описанием требуемого состояния системы ограничивает возможность выстрелить себе в ногу и наворотить лапшеобразного императивного кода.
Если эту заметку прочтут программисты, администрирующие сервера - перестаньте толковать “Инфраструктуру как код” неверно! Мы берем лучшие наработки из мира программирования, но это не традиционное программирование. Не надо переизобретать Bash-скрипты на Ruby.