Terraform 未部署到多个帐户
Terraform not deploying into multiple accounts
我在 terraform/terragrunt 部署到多个帐户时遇到问题。我想在我的 "master" 帐户中管理 DNS 和 KMS,并将其他一切部署到我的 dev/uat/prod 环境中。
我使用提供商配置了多个 AWS 账户。一个是通过 terragrunt 自动创建的,另一个是在我的 main.tf 文件中创建的。
我尝试了很多不同的方法来让它发挥作用。为两个提供者设置别名,只为一个提供者设置一个别名,并从等式中完全删除 terragrunt。在每种情况下,terraform 都应用于我的 "master" 帐户的所有资源..
下面是我的代码示例:
backend = "s3"
# generate = {
# path = "backend.tf"
# if_exists = "overwrite"
# }
config = {
bucket = "arm-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-west-2"
dynamodb_table = "arm-terraform-state-lock"
}
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
}
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
provider "aws" {
alias = "main"
region = "${local.aws_region}"
profile = "${local.account}"
}
EOF
}
locals {
region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl"))
aws_region = local.region_vars.locals.aws_region
account = local.account_vars.locals.aws_profile
}
以上是我的 Terragrunt 代码。
这是我的模块:
resource "aws_iam_role_policy" "logging_role_policy" {
provider = aws.main
name = format("aws-sftp-logging-policy-%s-%s",var.product_name,var.env)
role= aws_iam_role.logging_role.id
policy = data.aws_iam_policy_document.sftp_logging.json
}
############
# Route 53 #
############
resource "aws_route53_record" "sftp_record" {
provider = aws.master
zone_id = data.aws_route53_zone.facteus.zone_id
name = format("%s-%s",var.product_name,var.env)
type = "CNAME"
ttl = "30"
records = [aws_transfer_server.aws_transfer_service.endpoint]
}
您应该首先创建一个反映您所需帐户结构的目录结构。根据你的问题,听起来你可能想要这样的东西:
├── dev
│ ├── terragrunt.hcl
│ └── us-east-1
├── master
│ ├── _global
│ │ └── dns
│ ├── terragrunt.hcl
│ └── us-east-1
│ └── kms
├── prod
│ ├── terragrunt.hcl
│ └── us-east-1
└── uat
├── terragrunt.hcl
└── us-east-1
这里的master
账号有两个其他人没有的目录:
_global/dns
- 由于 AWS 中的 Route 53 是一个全球实体(而非区域),您不希望将其嵌套在 us-east-1
下。它仅存在于 master
帐户中,因为您声明要从主机控制 DNS。 (我还建议将其命名为 route53
而不是 dns
,但我离题了。)
us-east-1/kms
- 这包含 KMS 配置,也仅适用于 master
.
现在,在 master/terragrunt.hcl
中设置您的 remote_state
配置:
remote_state {
backend = "s3"
config = {
encrypt = true
bucket = "master-terraform-state" # Just for example - must be a globally unique
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
}
}
您还可以选择包含 iam_role
attribute:
iam_role = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
请注意,这是可选的,因为您也可以使用主帐户的凭据简单地执行 Terragrunt,或者您可以使用 --terragrunt-iam-role
CLI 选项,或者您可以设置 TERRAGRUNT_IAM_ROLE
env var .在所有情况下,您将使用具有主帐户权限的角色执行 terragrunt。
现在,对于 dev/uat/prod 个帐户,您可以使用类似的 remote_state
配置,为每个帐户替换不同的存储桶名称。然后,您可以使用适合每个账户的 IAM 角色,方法是在每个账户的 terragrunt.hcl
中将其定义为 iam_role
,或者使用我提到的其他方法。
TL;DR 您不需要为此生成提供程序,也不需要在提供程序配置中命名配置文件。您只需为每个账户使用正确的 IAM 角色执行 terragrunt。 Terragrunt 将在调用 Terraform 之前承担该角色。将提供程序配置放入您的 Terraform 模块中,关闭配置文件。
我在 terraform/terragrunt 部署到多个帐户时遇到问题。我想在我的 "master" 帐户中管理 DNS 和 KMS,并将其他一切部署到我的 dev/uat/prod 环境中。
我使用提供商配置了多个 AWS 账户。一个是通过 terragrunt 自动创建的,另一个是在我的 main.tf 文件中创建的。
我尝试了很多不同的方法来让它发挥作用。为两个提供者设置别名,只为一个提供者设置一个别名,并从等式中完全删除 terragrunt。在每种情况下,terraform 都应用于我的 "master" 帐户的所有资源..
下面是我的代码示例:
backend = "s3"
# generate = {
# path = "backend.tf"
# if_exists = "overwrite"
# }
config = {
bucket = "arm-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-west-2"
dynamodb_table = "arm-terraform-state-lock"
}
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
}
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
provider "aws" {
alias = "main"
region = "${local.aws_region}"
profile = "${local.account}"
}
EOF
}
locals {
region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl"))
aws_region = local.region_vars.locals.aws_region
account = local.account_vars.locals.aws_profile
}
以上是我的 Terragrunt 代码。 这是我的模块:
resource "aws_iam_role_policy" "logging_role_policy" {
provider = aws.main
name = format("aws-sftp-logging-policy-%s-%s",var.product_name,var.env)
role= aws_iam_role.logging_role.id
policy = data.aws_iam_policy_document.sftp_logging.json
}
############
# Route 53 #
############
resource "aws_route53_record" "sftp_record" {
provider = aws.master
zone_id = data.aws_route53_zone.facteus.zone_id
name = format("%s-%s",var.product_name,var.env)
type = "CNAME"
ttl = "30"
records = [aws_transfer_server.aws_transfer_service.endpoint]
}
您应该首先创建一个反映您所需帐户结构的目录结构。根据你的问题,听起来你可能想要这样的东西:
├── dev
│ ├── terragrunt.hcl
│ └── us-east-1
├── master
│ ├── _global
│ │ └── dns
│ ├── terragrunt.hcl
│ └── us-east-1
│ └── kms
├── prod
│ ├── terragrunt.hcl
│ └── us-east-1
└── uat
├── terragrunt.hcl
└── us-east-1
这里的master
账号有两个其他人没有的目录:
_global/dns
- 由于 AWS 中的 Route 53 是一个全球实体(而非区域),您不希望将其嵌套在us-east-1
下。它仅存在于master
帐户中,因为您声明要从主机控制 DNS。 (我还建议将其命名为route53
而不是dns
,但我离题了。)us-east-1/kms
- 这包含 KMS 配置,也仅适用于master
.
现在,在 master/terragrunt.hcl
中设置您的 remote_state
配置:
remote_state {
backend = "s3"
config = {
encrypt = true
bucket = "master-terraform-state" # Just for example - must be a globally unique
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
}
}
您还可以选择包含 iam_role
attribute:
iam_role = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
请注意,这是可选的,因为您也可以使用主帐户的凭据简单地执行 Terragrunt,或者您可以使用 --terragrunt-iam-role
CLI 选项,或者您可以设置 TERRAGRUNT_IAM_ROLE
env var .在所有情况下,您将使用具有主帐户权限的角色执行 terragrunt。
现在,对于 dev/uat/prod 个帐户,您可以使用类似的 remote_state
配置,为每个帐户替换不同的存储桶名称。然后,您可以使用适合每个账户的 IAM 角色,方法是在每个账户的 terragrunt.hcl
中将其定义为 iam_role
,或者使用我提到的其他方法。
TL;DR 您不需要为此生成提供程序,也不需要在提供程序配置中命名配置文件。您只需为每个账户使用正确的 IAM 角色执行 terragrunt。 Terragrunt 将在调用 Terraform 之前承担该角色。将提供程序配置放入您的 Terraform 模块中,关闭配置文件。