在 Terraform 中将多个 AWS 帐户作为环境处理的最佳方式是什么?
What is the best way to handle multiple AWS accounts as environments in Terraform?
我们希望将我们的每个 Terraform 环境都放在一个单独的 AWS 账户中,这样可以防止意外部署到生产环境中。如何最好地实现这一点?
我们假设一个帐户专用于生产,另一个帐户专用于预生产,并且可能其他沙盒环境也有唯一的帐户,可能基于每个管理员。另一个假设是您在每个特定于您的环境的 AWS 账户中都有一个 S3 存储桶。此外,我们希望您的 AWS 帐户凭证在 ~/.aws/credentials 中进行管理(或者可能具有 IAM 角色)。
Terraform 后端配置
有两种状态。对于主要状态,我们使用 Partial Configuration 的概念。我们不能通过模块或其他方式将变量传递到后端配置中,因为它是在确定之前读取的。
Terraform 配置设置
这意味着我们在声明后端时缺少一些细节,然后将它们作为参数提供给 terraform init
。一旦初始化,它就会被设置,直到 .terraform
目录被删除。
terraform {
backend "s3" {
encrypt = true
key = "name/function/terraform.tfstate"
}
}
工作流程注意事项
我们只需要改变我们的初始化方式。我们在 terraform init
上使用 -backend-config
参数。这提供了配置的缺失部分。我在我的 ~/.bash_profile
中通过 bash 别名提供所有缺失的部分,就像这样。
alias terrainit='terraform init \
-backend-config "bucket=s3-state-bucket-name" \
-backend-config "dynamodb_table=table-name" \
-backend-config "region=region-name"'
意外错误配置结果
如果适当的必需 -backend-config
参数被省略,初始化将提示您输入它们。如果提供不正确,可能会因权限原因导致失败。此外,远程状态必须配置为匹配,否则它也会失败。为了部署到生产环境,必须在识别适当的帐户环境时出现多次错误。
Terraform 远程状态
下一个问题是远程状态也需要改变,无法通过后端配置拉取配置;但是,可以通过变量设置远程状态。
模块设置
为了简化帐户切换,我们设置了一个非常简单的模块,它接受一个变量 aws-account
和 return 远程状态可以使用适当值的一堆输出。我们还可以包含 environment/account 特定的其他内容。该模块是一个简单的 main.tf
,其映射变量具有键 aws-account
和特定于该帐户的值。然后我们有一堆输出,像这样简单地查找地图变量。
variable "aws-region" {
description = "aws region for the environment"
type = "map"
default = {
Production = "us-west-2"
PP = "us-east-2"
}
}
output "aws-region" {
description = “The aws region for the account
value = "${lookup(var.aws-region, var.aws-account, "invalid AWS account specified")}"
}
Terraform 配置设置
首先,我们必须将 aws-account 传递给模块。这可能会在 main.tf
.
的顶部附近
module "environment" {
source = "./aws-account"
aws-account = "${var.aws-account}"
}
然后将变量声明添加到您的 variables.tf
。
variable "aws-account" {
description = "The environment name used to identify appropriate AWS account resources used to configure remote states. Pre-Production should be identified by the string PP. Production should be identified by the string Production. Other values may be added for other accounts later."
}
现在我们已经从模块输出了账户特定变量,它们可以像这样用于远程状态声明。
data "terraform_remote_state" "vpc" {
backend = "s3"
config {
key = "name/vpc/terraform.tfstate"
region = "${module.environment.aws-region}"
bucket = "${module.environment.s3-state-bucket-name}"
}
}
工作流程考虑
如果像这样设置后工作流没有任何变化,每当 plan/apply 或类似的时候,将提示用户通过这样的提示提供 aws-account
变量的值执行。提示内容为variables.tf
.
中变量的描述
$ terraform plan
var.aws-account
The environment name used to identify appropriate AWS account
resources used to configure remote states. Pre-Production should be
identified by the string PP. Production should be identified by the
string Production. Other values may be added for other accounts later.
Enter a value:
您可以像这样在命令行中提供变量来跳过提示
terraform plan -var="aws-account=PP"
意外错误配置结果
如果未指定 aws-account
变量,将请求它。如果提供了 aws-account 模块不知道的无效值,它将 return 错误,包括字符串“指定的无效 AWS 帐户”多次,因为这是查找的默认值。如果正确传递了 aws-account,但它与 terraform init 中标识的值不匹配,它将失败,因为正在使用的 aws 凭据将无法访问所标识的 S3 存储桶。
我们遇到了类似的问题,我们(部分)解决了在 Jenkins 或任何其他 CI 工具中创建管道的问题。
我们有 3 个不同的环境(开发、暂存和生产)。相同的代码,不同的 tfvars,不同的 aws 帐户。
当 terraform 代码合并到 master 时,可以应用于登台,只有当登台为绿色时,才能执行生产。
没有人在 prod 中手动运行 terraform,aws 凭据存储在 CI 工具中。
此设置可以解决您描述的事故,但也可以防止不同的用户应用不同的本地代码。
我们希望将我们的每个 Terraform 环境都放在一个单独的 AWS 账户中,这样可以防止意外部署到生产环境中。如何最好地实现这一点?
我们假设一个帐户专用于生产,另一个帐户专用于预生产,并且可能其他沙盒环境也有唯一的帐户,可能基于每个管理员。另一个假设是您在每个特定于您的环境的 AWS 账户中都有一个 S3 存储桶。此外,我们希望您的 AWS 帐户凭证在 ~/.aws/credentials 中进行管理(或者可能具有 IAM 角色)。
Terraform 后端配置
有两种状态。对于主要状态,我们使用 Partial Configuration 的概念。我们不能通过模块或其他方式将变量传递到后端配置中,因为它是在确定之前读取的。
Terraform 配置设置
这意味着我们在声明后端时缺少一些细节,然后将它们作为参数提供给 terraform init
。一旦初始化,它就会被设置,直到 .terraform
目录被删除。
terraform {
backend "s3" {
encrypt = true
key = "name/function/terraform.tfstate"
}
}
工作流程注意事项
我们只需要改变我们的初始化方式。我们在 terraform init
上使用 -backend-config
参数。这提供了配置的缺失部分。我在我的 ~/.bash_profile
中通过 bash 别名提供所有缺失的部分,就像这样。
alias terrainit='terraform init \
-backend-config "bucket=s3-state-bucket-name" \
-backend-config "dynamodb_table=table-name" \
-backend-config "region=region-name"'
意外错误配置结果
如果适当的必需 -backend-config
参数被省略,初始化将提示您输入它们。如果提供不正确,可能会因权限原因导致失败。此外,远程状态必须配置为匹配,否则它也会失败。为了部署到生产环境,必须在识别适当的帐户环境时出现多次错误。
Terraform 远程状态
下一个问题是远程状态也需要改变,无法通过后端配置拉取配置;但是,可以通过变量设置远程状态。
模块设置
为了简化帐户切换,我们设置了一个非常简单的模块,它接受一个变量 aws-account
和 return 远程状态可以使用适当值的一堆输出。我们还可以包含 environment/account 特定的其他内容。该模块是一个简单的 main.tf
,其映射变量具有键 aws-account
和特定于该帐户的值。然后我们有一堆输出,像这样简单地查找地图变量。
variable "aws-region" {
description = "aws region for the environment"
type = "map"
default = {
Production = "us-west-2"
PP = "us-east-2"
}
}
output "aws-region" {
description = “The aws region for the account
value = "${lookup(var.aws-region, var.aws-account, "invalid AWS account specified")}"
}
Terraform 配置设置
首先,我们必须将 aws-account 传递给模块。这可能会在 main.tf
.
module "environment" {
source = "./aws-account"
aws-account = "${var.aws-account}"
}
然后将变量声明添加到您的 variables.tf
。
variable "aws-account" {
description = "The environment name used to identify appropriate AWS account resources used to configure remote states. Pre-Production should be identified by the string PP. Production should be identified by the string Production. Other values may be added for other accounts later."
}
现在我们已经从模块输出了账户特定变量,它们可以像这样用于远程状态声明。
data "terraform_remote_state" "vpc" {
backend = "s3"
config {
key = "name/vpc/terraform.tfstate"
region = "${module.environment.aws-region}"
bucket = "${module.environment.s3-state-bucket-name}"
}
}
工作流程考虑
如果像这样设置后工作流没有任何变化,每当 plan/apply 或类似的时候,将提示用户通过这样的提示提供 aws-account
变量的值执行。提示内容为variables.tf
.
$ terraform plan
var.aws-account
The environment name used to identify appropriate AWS account
resources used to configure remote states. Pre-Production should be
identified by the string PP. Production should be identified by the
string Production. Other values may be added for other accounts later.
Enter a value:
您可以像这样在命令行中提供变量来跳过提示
terraform plan -var="aws-account=PP"
意外错误配置结果
如果未指定 aws-account
变量,将请求它。如果提供了 aws-account 模块不知道的无效值,它将 return 错误,包括字符串“指定的无效 AWS 帐户”多次,因为这是查找的默认值。如果正确传递了 aws-account,但它与 terraform init 中标识的值不匹配,它将失败,因为正在使用的 aws 凭据将无法访问所标识的 S3 存储桶。
我们遇到了类似的问题,我们(部分)解决了在 Jenkins 或任何其他 CI 工具中创建管道的问题。
我们有 3 个不同的环境(开发、暂存和生产)。相同的代码,不同的 tfvars,不同的 aws 帐户。
当 terraform 代码合并到 master 时,可以应用于登台,只有当登台为绿色时,才能执行生产。 没有人在 prod 中手动运行 terraform,aws 凭据存储在 CI 工具中。
此设置可以解决您描述的事故,但也可以防止不同的用户应用不同的本地代码。