Многие новички пропускают настройку модулей Terraform, чтобы облегчить процесс настройки. По крайней мере, они так думают, что облегчили себе задачу. Рассмотрим что такое модули Terraform и как они работают. Я предполагаю, что вы уже знаете некоторые основы Terraform и даже пытались использовать его раньше. Если нет, ознакомьтесь с этим обзором Terraform и этим видеоуроком, прежде чем продолжить чтение. Обратите внимание: я намеренно не использую реальные примеры кода с некоторыми конкретными поставщиками, такими как AWS или Google для простоты понимания. Даже если вы не создаете модуль намеренно, если вы используете Terraform, вы уже пишете модуль — так называемый «корневой» модуль. Любой файл конфигурации Terraform (.tf) в каталоге, даже один, образует модуль. Модуль Terraform позволяет вам создавать логическую абстракцию поверх некоторого набора ресурсов. Другими словами, модуль позволяет вам группировать ресурсы вместе и повторно использовать эту группу позже, возможно, много раз. Предположим, у нас есть виртуальный сервер с некоторыми функциями, размещенными в облаке. Какой набор ресурсов может описывать этот сервер? Например: сама виртуальная машина, созданная из некоторого образа подключенное блочное устройство указанного размера для дополнительного хранилища статический общедоступный IP-адрес, сопоставленный с виртуальным сетевым интерфейсом сервера набор правил брандмауэра, который будет прикреплен к серверу другие вещи, такие как другое блочное устройство, дополнительный сетевой интерфейс и т. д.  Теперь предположим, что вам нужно создать этот сервер с набором ресурсов много раз. Именно здесь модули действительно полезны. Вы же не хотите повторять один и тот же код конфигурации снова и снова, не так ли? Вот пример, показывающий, как может быть вызван наш «серверный» модуль. «Вызвать модуль» означает использовать его в файле конфигурации. Здесь мы создаем 5 экземпляров «сервера», используя единый набор конфигураций (в модуле): Terraform поддерживает "счетчик" для модулей, начиная с версии 0.13. Конечно, вы, вероятно, захотите создать более одного модуля. Вот несколько распространенных примеров: сеть, подобная виртуальному частному облаку (VPC) хостинг статического контента (т.е. bucket) балансировщик нагрузки и связанные с ним ресурсы конфигурация журналирования или что-то еще, что вы считаете отдельным логическим компонентом инфраструктуры Допустим, у нас есть два разных модуля: «серверный» модуль и «сетевой» модуль. В модуле под названием «сеть» мы определяем и настраиваем нашу виртуальную сеть и размещаем в ней серверы: Два разных дочерних модуля, вызываемые в корневом модуле Когда у нас есть несколько настраиваемых модулей, мы можем называть их «дочерними» модулями. А файл конфигурации, в котором мы вызываем дочерние модули, относится к корневому модулю.  Дочерний модуль может быть получен из нескольких мест: локальные пути официальный реестр Terraform — если вы знакомы с другими реестрами, такими как реестр Docker, то вы уже понимаете идею репозиторий Git (пользовательский или GitHub/BitBucket) HTTP URL-адрес архива .zip с модулем Но как передать сведения о ресурсах между модулями? В нашем примере серверы должны быть созданы в сети. Итак, как мы можем сказать «серверному» модулю создавать виртуальные машины в сети, которая была создана в модуле «сеть»? Вот тут и появляется инкапсуляция. Инкапсуляция в Terraform состоит из двух основных концепций: области модуля и явного доступа к ресурсам. Все экземпляры ресурсов, имена и, следовательно, видимость ресурсов изолированы в области действия модуля. Например, модуль «A» по умолчанию не видит и не знает о ресурсах в модуле «B». Видимость ресурсов, иногда называемая изоляцией ресурсов, гарантирует, что ресурсы будут иметь уникальные имена в пространстве имен модуля. Например, с нашими 5 экземплярами модуля «сервер»: Адреса ресурсов модуля, созданные с помощью мета-аргумента count С другой стороны, мы могли бы создать два экземпляра одного и того же модуля с разными именами: Обратите внимание на аргумент источника — он остается прежним, это тот же исходный модуль В этом случае имя или адрес ресурсов будет следующим: Если вы хотите получить доступ к некоторым сведениям о ресурсах в другом модуле, вам необходимо настроить это. По умолчанию наш модуль «сервер» не знает о сети, которая была создана в модуле «сеть».  Поэтому мы должны объявить значение output в «сетевом» модуле, чтобы экспортировать его ресурс или атрибут ресурса в другие модули. Модуль «сервер» должен объявить variable, которая будет использоваться позже в качестве входных данных:  Имена output и variable могут отличаться, но для ясности я предлагаю использовать одни и те же имена. Это явное объявление вывода — это способ предоставить некоторый ресурс (или информацию о нем) извне — в область видимости «корневого» модуля, чтобы сделать его доступным для других модулей. Обратите внимание на выходной адрес 'network_id' здесь — мы указываем, где он находится Вот как будет выглядеть окончательный код для вызова наших дочерних модулей: В этом примере конфигурации будет создано 5 экземпляров одного и того же сервера со всеми необходимыми ресурсами в сети, которую мы создали как отдельный модуль. Теперь вы должны понять, что такое модули и для чего они нужны. Если вы находитесь в самом начале пути к Terraform, вот несколько советов по дальнейшим действиям. Я рекомендую вам ознакомиться с этим коротким руководством от HashiCorp, создателя Terraform, о модулях: "Organize Configuration". Кроме того, есть отличное комплексное учебное пособие, охватывающее все, от новичка до продвинутых понятий о Terraform: "Study Guide — Terraform Associate Certification". Модульная структура кода делает вашу конфигурацию более гибкой и простой для понимания другими. Последнее особенно полезно для команды. Если вам понравилась статья, подпишитесь на меня в Twitter (@vasylenko), где я иногда делюсь своими выводами и советами по Terraform, AWS, Ansible и другим технологиям, связанным с DevOps. Немного рекламы: На платформе https://rotoro.cloud/ вы можете найти курсы с практическими занятиями: DevOps-инженер