【问题标题】:What is the best way to handle multiple AWS accounts as environments in Terraform?在 Terraform 中将多个 AWS 账户作为环境处理的最佳方式是什么?
【发布时间】:2018-12-29 06:27:04
【问题描述】:

我们希望将我们的每个 terraform 环境都放在一个单独的 AWS 账户中,以防止意外部署到生产环境。这如何最好地完成?

【问题讨论】:

    标签: amazon-s3 terraform terraform-provider-aws


    【解决方案1】:

    我们假设一个帐户专用于生产,另一个帐户用于 PreProduction,并且可能其他沙盒环境也有唯一的帐户,可能是基于每个管理员的。另一个假设是,您在每个 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 并返回一组远程状态可以使用适当值的输出。我们还可以包含其他特定于环境/帐户的内容。该模块是一个简单的main.tf,其映射变量具有aws-account 的键和特定于该帐户的值。然后我们有一堆输出,可以像这样简单地查找 map 变量。

    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}"
      }
    }
    

    工作流程考虑

    如果在这样设置后工作流没有发生任何变化,则每当执行计划/应用等时,都会通过这样的提示提示用户提供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 模块不知道的无效值,它将多次返回错误,包括字符串“指定的无效 AWS 账户”,因为这是查找的默认值。如果正确传递了 aws-account,但它与 terraform init 中标识的值不匹配,则会失败,因为正在使用的 aws 凭证将无法访问正在标识的 S3 存储桶。

    【讨论】:

    • 我正在清理这个。当这不涉及您的用例或您发现一些令人困惑的地方时,请发表评论。我们真的很难将这个工作流程整齐地组合在一起。我们没有使用工作区,因为很容易错过您所在的工作区,并且 Hashicorp 的文档不建议将它们用于多个 AWS 账户情况。
    【解决方案2】:

    我们遇到了类似的问题,我们解决了(部分)在 Jenkins 或任何其他 CI 工具中创建管道。

    我们有 3 个不同的环境(dev、staging 和 prod)。相同的代码、不同的 tfvar、不同的 aws 帐户。

    当 terraform 代码合并到 master 时,可以应用到 staging 并且只有当 staging 为绿色时,才能执行生产。 没有人在 prod 中手动运行 terraform,aws 凭据存储在 CI 工具中。

    此设置可以解决您描述的事故,但也可以防止不同的用户应用不同的本地代码。

    【讨论】:

      猜你喜欢
      • 2020-12-14
      • 1970-01-01
      • 1970-01-01
      • 2011-02-26
      • 2014-04-11
      • 2011-09-30
      • 2016-05-26
      相关资源
      最近更新 更多