Декларирование инфраструктуры

Что это такое

Конфигурация Terraform — это набор файлов, объявляющих ресурсы, значения, которые им нужны, и значения, которые стоит сделать доступными. Ресурс — это реальная вещь у провайдера: сеть, машина, база данных, — описанная своими настройками. Переменные параметризуют конфигурацию, чтобы одно определение могло описывать несколько окружений, а выходные значения открывают то, что нужно другой конфигурации или человеку.

Почему это важно

Консоль делает любое изменение лёгким и ни одно из них — записанным. Объявление превращает изменение в diff: вы видите, что будет создано, изменено или удалено, до того как это случится, и это единственный момент, когда опасное изменение дёшево поймать. Поскольку конфигурация живёт в системе контроля версий, история окружения просматриваема, а пересборка после аварии — это применение тех же файлов, а не попытка вспомнить последовательность кликов.

Ключевые идеи

Ресурс — это объект с жизненным циклом

Объявление ресурса задаёт ему тип, локальное имя и настройки. Terraform создаёт его, записывает в состояние, а позже изменяет или удаляет по мере изменения объявления. Локальное имя — это то, как другие части конфигурации ссылаются на ресурс, поэтому переименование блока ресурса не косметика: для инструмента это может выглядеть как новый ресурс и старый, подлежащий удалению.

resource "network" "main" { ... }
resource "subnet" "app"  { network = network.main.id }

План — это контракт, и его нужно читать

План перечисляет каждое действие и помечает разрушительные. Его чтение и есть весь механизм безопасности: неожиданное удаление — это момент остановиться, а не деталь, которую надо одобрить. В конвейере план стоит прикладывать к изменению для просмотра, потому что человек, который его одобряет, — последняя точка перед тем, как ресурс исчезнет.

Переменные параметризуют, выходные значения открывают

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

Модуль упаковывает приём, и ему нужна версия

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

Провайдеры — это граница с реальным миром

Каждый провайдер поставляет типы ресурсов и вызовы API за ними, а версии провайдера меняют поведение. Фиксация версии провайдера и осознанное обновление — вот что не даёт несвязанному изменению поменять то, как создаётся каждый ресурс.

Применение, упавшее на середине, оставляет реальные ресурсы

В отличие от программы, применение — не транзакция. Часть ресурсов существует, часть — нет, и состояние может потребовать приведения в порядок, прежде чем можно будет продолжить. Ответ — внимательно прочитать состояние и план и осознанно вернуть объявление и реальность в соответствие, а не запускать заново в надежде.

Практика

Соберите небольшое окружение из объявления

Объявите сеть и один инстанс с переменной для региона и выходным значением для адреса. Примените, затем измените регион и прочитайте план, прежде чем решать, применять ли.

Готово, когда: вы можете объяснить, что именно уничтожит изменение и почему, и остановились до его применения.

Выделяйте модуль только там, где есть повтор

Напишите второе окружение, использующее то же объявление с другими значениями, и определите, оправдан ли уже переиспользуемый модуль.

Готово, когда: вы можете назвать хотя бы двух реальных потребителей до создания модуля — или оставляете дублирование на месте.

Частые ошибки

  • Применение без чтения плана — разрушительное изменение проходит незамеченным; исправить: читайте каждый план и прикладывайте его к ревью.
  • Переименование блока ресурса — оно трактуется как замена, ресурс уничтожается и создаётся заново; исправить: при переименовании используйте команду переноса в состоянии.
  • Незафиксированные версии провайдеров — несвязанное применение меняет то, как строятся ресурсы; исправить: фиксируйте версию и обновляйте осознанно.
  • Создание модуля для одного применения — косвенность без переиспользования; исправить: выделяйте модуль, когда появился второй потребитель.
  • Убеждение, что применение атомарно — частичный провал оставляет реальные ресурсы; исправить: осознанно согласуйте состояние и объявление.

Что читать дальше

  • Terraform (06-cloud-devops/07-terraform) — инструмент, для которого написано это объявление.
  • Состояние и планирование (06-cloud-devops/07-terraform/02-state-and-planning) — что делает план надёжным и файл, который при неаккуратном обращении приносит больше всего ущерба.