如何部署具有多个角色的Terraform模块?

时间:2019-07-23 08:36:17

标签: amazon-web-services module terraform

我目前正在一个AWS terraform项目中,在该项目中,我有一个用于不同账户的ROLE ID(作为变量)的数组。

variable "slave_account_id" {
 default = ["5686435678", "9889865446"]
}

每个角色都允许我当前的AWS账户(与terraform链接)在这些账户上部署模块(假设每个账户的角色ID)

因此,我想基于变量数组“ slave_account_id”为每个角色创建不同的提供程序。

我试图这样做:

provider "aws" {
  counter = "${length(var.slave_account_id)}"

  alias  = "aws-assume-${counter.index}"
  region = "eu-west-1"

  assume_role {
    role_arn     = "arn:aws:iam::${var.slave_account_id[counter.index]}:role/slave_role_for_master"
    session_name = "${var.slave_session_name[counter.index]}"
    external_id  = "EXTERNAL_ID"
  }
}

这样,我本可以计划在模块中使用以下代码:

module "my_super_module" {
 counter = "${length(var.slave_account_id)}"
 providers = {
   aws = "aws.aws-assume-${counter.index}"
 }

 [...]
}

但这是行不通的(据我了解,我无法在提供者的别名内“连接”变量,因为必须在定义插值之前定义提供者)。 这是执行结果(提供程序别名部分出现错误):

Error: Invalid provider configuration alias

An alias must be a valid name. A name must start with a letter and may contain
only letters, digits, underscores, and dashes.


Error: Duplicate provider configuration

  on main.tf line 5:
   5: provider "aws" {

A default (non-aliased) provider configuration for "aws" was already given at
main.tf:1,1-15. If multiple configurations are required, set the "alias"
argument for alternative configurations.


Error: Unsuitable value type

  on main.tf line 8, in provider "aws":
   8:   alias  = "aws-assume-${counter.index}"

Unsuitable value: value must be known


Error: Variables not allowed

  on main.tf line 8, in provider "aws":
   8:   alias  = "aws-assume-${counter.index}"

Variables may not be used here.


Error: Invalid provider configuration reference

  on main.tf line 33, in module "my-lambda":
  33:     aws = "aws.aws-assume-${counter.index}"

A provider configuration reference must not be given in quotes.

因此我有点迷路了...

如何部署带有角色ID列表的模块(每个帐户一个模块)?

1 个答案:

答案 0 :(得分:1)

Terraform中的提供程序配置不是动态可构造的(也就是说,根据值决定要创建哪个),因为Terraform需要在生命周期的早期,在图形构造期间以及在可能进行表达式评估之前,将提供程序与资源相关联。

相反,我们可以重构问题,以便每个模块采用固定数量的AWS提供程序(通常是一个,但是在某些情况下为两个,如果该模块的目的是例如在两个区域或两个帐户之间建立对等关系),然后在根目录中多次实例化模块:

provider "aws" {
  alias = "eu-west-1_5686435678"

  region = "eu-west-1"
  assume_role {
    role_arn     = "arn:aws:iam::acct5686435678:role/admin"
    session_name = "whatever_session_name"
    external_id  = "EXTERNAL_ID"
  }
}

provider "aws" {
  alias = "eu-west-1_9889865446"

  region = "eu-west-1"
  assume_role {
    role_arn     = "arn:aws:iam::acct9889865446:role/admin"
    session_name = "whatever_session_name"
    external_id  = "EXTERNAL_ID"
  }
}

module "acct5686435678" {
  source = "./modules/aws-account"

  providers = {
    aws = aws.eu-west-1_5686435678
  }
}

module "acct9889865446" {
  source = "./modules/aws-account"

  providers = {
    aws = aws.eu-west-1_9889865446
  }
}


module "peering_5686435678_9889865446" {
  source = "./modules/aws-account-peering"

  providers = {
    aws.from = aws.eu-west-1_5686435678
    aws.to   = aws.eu-west-1_9889865446
  }
}

对于必须在多个AWS帐户或多个AWS区域上创建相同基础架构的情况,多次实例化同一模块是一种常见的技术。

话虽如此,如果多个AWS账户代表的是单独的环境,而不是一个环境中的单独的组件,那么通常最好在仍共享模块的同时为每个环境使用单独的根配置,以使对每个环境的更新完全分开,每个环境都有自己的状态,等等。