Новые опции жизненного цикла и возможности рефакторинга в Terraform 1.1 и 1.2

В этом блоге я хотел бы рассказать вам о новых замечательных возможностях, которые появились в Terraform 1.1 и 1.2. Такое ощущение, что после выхода версии 1.0 Terraform удвоил скорость предоставления новых функций. 🤩

Все примеры кода основаны на провайдере AWS Terraform ⛅️💛

Прошло всего несколько месяцев с момента выхода Terraform 1.1 с блоком moved, который расширяет возможности рефакторинга кода.

Теперь Terraform 1.2 почти готов (сейчас, когда я пишу этот блог в начале мая 2022 года), чтобы привнести три новых эффективных элемента управления в жизненный цикл ресурсов.

Это три новых выражения: precondition, postcondition и replace_triggered_by.

Рефакторинг кода Terraform с помощью блока Moved

Начиная с версии 1.1, пользователи Terraform могут использовать блок moved для описания изменений в адресах ресурсов или модулей (или ресурсов внутри модуля) в виде кода.

После такого описания Terraform выполняет перемещение ресурса внутри состояния во время первого применения.

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

По мере развития вашего кода ресурс или модуль может иметь несколько блоков moved, связанных с ним, и Terraform будет тщательно воспроизводить всю историю его перемещения в пределах состояния (т.е. переименования).

Давайте рассмотрим несколько примеров, иллюстрирующих, как это работает.

Перемещение ресурса

В модуле у меня есть политика bucket, которая имеет общее, бессмысленное имя. Она используется в модуле, который создает дистрибутив CloudFront с ведром S3.

Вполне нормально назвать ресурс подобным образом, если в вашем коде есть только один экземпляр такого типа.

Позже, когда мне понадобится добавить в модуль еще одну политику, я не хочу называть ее “так”. Вместо этого я хочу, чтобы мои политики уже сейчас имели осмысленные имена.

Например, я могу переименовать старую политику командой terraform state mv, но другие пользователи моего модуля не будут знать об этом.

Вот тут-то и оказывается полезным блок moved: Я могу задокументировать изменение имени, и позже все остальные, кто использует мой модуль, получат такое же переименование.

Terraform следует инструкциям внутри блока module для планирования и применения изменений. Хотя обновление адреса ресурса не учитывается как изменение в выводе Plan, Terraform выполнит это обновление во время применения.

Перемещение модуля

Тот же подход можно применить к модулю.

Здесь я использую два модуля для создания статического хостинга для веб-сайта с пользовательским сертификатом TLS: комбинация сервисов CloudFront + S3 + ACM.

Опять же, если мне понадобится добавить еще пару модулей CDN+Certificate, я хотел бы иметь в коде осмысленные имена, чтобы четко отличать один от другого.

Поэтому я бы добавил два блока moved – по одному на вызов модуля.

И, кстати, поскольку я переименовал модуль (с cert на example_com_cert), мне нужно обновить и все ссылки на выходы этого модуля в коде.

Однако есть один нюанс: когда вы переименовываете модуль и объявляете это в блоке moved, вам необходимо выполнить terraform init перед применением изменений, поскольку Terraform должен сначала инициализировать модуль с новым именем.

Есть несколько более сложных действий, которые можно выполнить с помощью блока moved:

  • Внедрить мета-аргументы count и for_each для ресурсов и модулей.
  • Разбейте один модуль на несколько Проверьте следующее подробное руководство от HashiCorp, которое объясняет, как это сделать – Рефакторинг

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

Поэтому вот несколько советов о том, как с этим справиться:

💡 Долго держите блоки moved в коде. Например, при удалении блока moved из кода, Terraform больше не будет рассматривать новое имя объекта как переименование. Вместо этого Terraform будет планировать удаление ресурса или модуля со старым именем вместо его переименования.
💡 Сохраняйте полные цепочки переименования объектов (последовательность перемещений). Вся история перемещения объектов гарантирует, что пользователи с разными версиями модулей получат последовательное и предсказуемое поведение рефакторинга.

Выражения жизненного цикла: предусловие, постусловие и replace_triggered_by

Terraform 1.2 кардинально улучшает мета-аргумент lifecycle, добавляя три новых опции конфигурации с широкими возможностями.

Предусловие и постусловие

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

Условие здесь – это некоторые данные или информация о ресурсе, которые необходимо подтвердить для применения кода.

Вот несколько примеров таких условий:

  • Подтвердить некоторые атрибуты Источника данных, которые вы не можете проверить с помощью фильтров или других доступных аргументов;
  • Подтвердить аргумент ресурса, который может состоять из нескольких переменных (например, списка);

💡 Предусловие работает как ожидание или предположение о некотором внешнем (но внутри модуля) значении, от которого зависит ресурс.
💡 Постусловие работает как гарантия того, что ресурс выполняет определенное условие, поэтому другие ресурсы могут полагаться на него. Если постусловие не выполняется для ресурса, это предотвращает изменения всех других ресурсов, которые зависят от него.

Давайте рассмотрим эту новую возможность на примере использования postcondition.

Рассмотрим следующий случай: наш модуль получает AMI ID в качестве входной переменной, и этот AMI должен быть использован в шаблоне запуска; у нас также есть требование к экземпляру EC2, созданному на основе этого шаблона запуска – размер корневой EBS должен быть равен или больше 600 ГБ.

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

Аргумент condition в блоке принимает любую из встроенных функций Terraform или операторов языка.

Специальный объект self доступен только для блока postcondition, поскольку он предполагает, что проверка может быть выполнена после того, как объект создан и его атрибуты известны.

В дальнейшем, если пользователь модуля укажет AMI с размером EBS менее 600 ГБ, Terraform не сможет создать шаблон запуска, поскольку он зависит от источника данных, который не прошел проверку постусловия.

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

Проверка вывода модуля с помощью предусловия

Блок precondition также доступен для выходов модуля.

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

Вот пример: модуль, создающий сертификат ACM, должен предотвратить использование определенного доменного имени в общем имени сертификата или его SAN.

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

Триггерная замена ресурсов с помощью replace_triggered_by

Иногда необходимо указать зависимость таким образом, чтобы пересоздать ресурс при изменении другого ресурса или его атрибута.

Это полезно, когда два (или более) ресурса не имеют явной зависимости.

Рассмотрим следующий случай: у вас есть два экземпляра EC2, A и B, и вам нужно воссоздать экземпляр B, если частный IP-адрес экземпляра A изменится.

Это чрезвычайно полезно, когда вы имеете дело с логическими абстракциями над набором ресурсов.

Замена срабатывает, когда:

💡 обновляется любой из ресурсов, на которые ссылается replace_triggered_by.
💡 Любое значение устанавливается в атрибут ресурса, на который ссылается replace_triggered_by.

Начало работы с Terraform 1.1 и 1.2

Если вы все еще используете старые версии Terraform, эти новые возможности могут стать для вас хорошим стимулом для обновления!

Перед обновлением обязательно прочитайте заметки по обновлению для конкретной версии на странице релизов.

Кроме того, отличный инструмент поможет вам быстро переключаться между различными версиями Terraform во время экспериментов – tfswitch.

И если вам понравилась эта статья, вам также могут понравиться другие статьи о Terraform: Terraform Proficiency


Сергей Василенко

Я инженер из Украины. Мне нравится астрономия и все, что связано с DevOps. Я стремлюсь к разработке отличных продуктов, созданию отличных людей и отличных команд.

Оцените статью
Procodings.ru
Добавить комментарий