#amazon-web-services #terraform
#amazon-web-services #terraform
Вопрос:
Я пытаюсь настроить некоторую автоматизацию вокруг инфраструктуры AWS. Только что столкнулся с одной проблемой, связанной с зависимостями модулей. Поскольку в terraform нет опции типа «Включить», поэтому достичь моей цели становится немного сложнее.
Вот краткое описание сценария:
В моем корневом каталоге у меня есть файл main.tf
который состоит из нескольких модульных блоков, например.
module mytest1
{
source = mymod/dev
}
module mytest2
{
source = mymod2/prod
}
у каждого разработчика и продукта есть много файлов tf
Некоторые из моих файлов .tf, которые существуют внутри prod
каталога, нуждаются в некотором выводе из ресурсов, которые существуют внутри dev
каталога
Поскольку модуль не имеет зависимости, я подумал, есть ли какой-либо способ запускать модули последовательно или какие-либо другие идеи?
Ответ №1:
Не совсем уверен в вашем варианте использования, когда prod и dev должны взаимодействовать так, как вы указали.
Я ожидал бы, что у вас может быть что-то вроде приведенной ниже структуры папок:
- Папка 1: Dev (содержит модули для разработчиков)
- Папка 2: Prod (содержит модули для prod)
- Папка 3: Ресурсы (содержит общие блоки ресурсов, которые используют как модуль разработки, так и модуль prod)
Затем, когда вы запустите terraform apply
для папки 1, он создаст вашу инфраструктуру разработки, передав переменные из ваших модулей в ресурсы (в папке 3).
И когда вы запустите terraform apply
для папки 2, он создаст вашу инфраструктуру prod, передав переменные из ваших модулей в ресурсы (в папке 3).
Если вы по какой-либо причине не можете этого сделать, то выходные переменные или источники данных потенциально могут помочь вам получить необходимую информацию.
Ответ №2:
У вас нет причин использовать разные модули для разных сред. Обычно разница между младшими окружениями и prod заключается в количестве и уровне для каждого ресурса, и вы могли бы просто использовать переменные для передачи этого внутри модулей.
Чтобы справиться с этим, вы можете использовать terraform workspaces
и создать одно рабочее пространство для каждой среды, например:
terraform worskspace new staging
Это создаст совершенно новое рабочее пространство со своим собственным состоянием. Если вам нужно определить количество создаваемых ресурсов, вы можете использовать переменную или само имя рабочей области terraform, например:
# Your EC2 Module
"aws_instance" "example" {
count = "${terraform.workspace == "prod" ? 3 : 1}"
}
# or
"aws_instance" "example" {
count = "${lenght(var.subnets)}" # you are likely to have more subnets for prod
}
# Your module
module "instances" {
source = "./modules/ec2"
subnets = "my subnets list"
}
И это все, вы можете заставить все свои модули работать в любой среде, просто создавая рабочие пространства и изменяя переменные для каждого из них в вашем конвейере и применяя план каждый раз.
Комментарии:
1. Просто чтобы понять, что это не имеет отношения к
environment
. Это просто имя каталога. Каждый каталог состоит из нескольких файлов .tf, и эти файлы .tf имеют зависимости. И я хочу запускать модули последовательно, чтобы второй модуль получал все ресурсы, выводимые из первого модуля. Поскольку функциональность типа include недоступна в terraform, поэтому я использую module. На самом деле модуль не имеет никакого отношения к. Внутри каждого каталога чертовски много файлов, поэтому я не хочу, чтобы они испортили мой корневой каталог. Поэтому я разместил их в разных каталогах, выполнив их через module
Ответ №3:
Я не слишком уверен в вашем требовании о том, чтобы производственная среда зависела от среды разработки, но, оставляя в стороне специфику, идиоматический способ создания последовательности между ресурсами и между модулями в Terraform заключается в использовании ссылочных выражений.
Вы не сказали, какой аспект среды разработки используется производственной средой, но для примера предположим, что производственной среде требуется идентификатор VPC, созданный в среде разработки. В этом случае модуль разработки экспортировал бы этот идентификатор VPC в качестве выходного значения:
# (this goes within a file in your mymod/dev directory)
output "vpc_id" {
value = "${aws_vpc.example.id}"
}
Тогда ваш производственный модуль, наоборот, будет иметь входную переменную для указания этого:
# (this goes within a file in your mymod2/prod directory)
variable "vpc_id" {
type = "string"
}
Установив их, ваш родительский модуль может затем передавать значение между ними, чтобы установить зависимость, которую вы ищете:
module "dev" {
source = "./mymod/dev"
}
module "prod" {
source = "./mymod2/prod"
vpc_id = "${module.dev.vpc_id}"
}
Это работает, потому что создает следующую цепочку зависимостей:
module.prod's input variable vpc_id depends on
module.dev's output value vpc_id, which depends on
module.dev's aws_vpc.example resource
Затем вы можете использовать var.vpc_id
любое место внутри вашего производственного модуля для получения этого идентификатора VPC, который создает еще одно звено в этой цепочке зависимостей, сообщая Terraform, что он должен дождаться создания VPC, прежде чем предпринимать какие-либо действия, зависящие от существования VPC.
В частности, обратите внимание, что в цепочке зависимостей участвуют отдельные переменные и выходные данные, а не модуль в целом. Это означает, что если у вас есть какие-либо ресурсы в модуле prod, которые не нуждаются в существовании VPC, то Terraform может приступить к их созданию немедленно, не дожидаясь, пока модуль разработки будет полностью завершен первым, при этом гарантируя, что создание VPC завершится, прежде чем предпринимать какие-либо действия, которые действительно в этом нуждаются.
Дополнительная информация об этом шаблоне содержится в разделе документации Состав модуля. Он написан с учетом синтаксиса и возможностей Terraform версии 0.12, но общий шаблон по-прежнему применим к более ранним версиям, если вместо этого вы используете синтаксис и возможности версии 0.11, как я делал в приведенных выше примерах.