В DevOps слишком много специальных систем-снежинок. Один из способов увидеть это — распространение хранилищ данных DevOps: баз данных и поисковых систем, предназначенных специально для метрик и журналов. Другой способ — «инфраструктура как код» всегда оказывается чем-то, что не является кодом.

Большая часть бизнес-функций и программного обеспечения предоставляется через библиотеки. Сюда входят платежи, презентации, графика, анализ данных и даже облачные вычисления. Когда поставщик хочет предоставить функциональность, он собирает API и библиотеку для этого API, предлагая его на всех языках программирования — PHP, Java, Ruby, Python, Swift — из которых, по его мнению, любой захочет его использовать. Идея в том, что вы собираетесь использовать это из своего кода; поэтому, конечно, вам нужна библиотека, которую вы можете импортировать в свой код.

С инфраструктурным программным обеспечением происходит нечто иное. Когда мы получаем новые инструменты — Chef, Puppet, Terraform — мы также получаем новый способ программирования. Это может быть что-то близкое к существующему языку — как в случае с Chef — но обычно это отдельный язык, встроенный в YAML, с собственным подходом к управлению потоком, функциями, модулями и экранированием строк. Нет системы управления конфигурацией, предназначенной для использования в качестве импортируемой библиотеки — require “chef” — из вашего кода, как и любая другая библиотека.

Это делается во имя «декларативности»; но это благовидное обещание. Развертывания и другие операционные задачи являются частью рабочих процессов. Наличие декларативного API не означает, что нам нужен декларативный язык. Обычный рабочий процесс, который я реализовывал много раз, таков:

  • Пользователь хочет развернуть определенную версию кода.
  • Проверьте сервер сборки, чтобы убедиться, что эта версия проходит тесты.
  • Если нет, сообщите пользователю.
  • Если это так, выполните развертывание в бета-среде.
  • Проверьте частоту ошибок в бета-среде, чтобы убедиться, что она остается ниже порогового значения. (Вызов API к балансировщику нагрузки облачного провайдера.)
  • Если нет, откатите бета-среду. Если это так, перейдите на канал разработчиков в IRC и сообщите разработчикам, что развертывание идет в производство. (Это включает обращение к базе данных, чтобы узнать, какой это канал.)
  • Развертывание в производственной среде, привязанной к этой бета-среде. (Это снова включает в себя обращение к базе данных, чтобы узнать соответствующую среду.)
  • Проверьте производство на повышенный уровень ошибок. (Вызов API к балансировщику нагрузки облачного провайдера.)
  • Если все выглядит плохо, откат.
  • Сообщите разработчикам в IRC в любом случае.

Какие части этого являются декларативными? Спецификация деплойментов — где деплоить, какие SHA — бесспорно есть; но в остальном он явно императивен по своей природе. (Это не значит, что мы не можем моделировать императивные программы на декларативных языках, но поскольку мы этим занимаемся, мы не должны притворяться, что перед нами стоит декларативная задача.)

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

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