Terraform-模块的资源已存在时,EntityAlreadyExists错误(409)

时间:2019-11-16 13:33:39

标签: amazon-web-services terraform amazon-iam

我编写了一个模块,该模块应可在不同环境中重用。

为了简化操作,下面是一个从环境根模块之一调用模块的基本示例:

##QA-resources.tf

module "some_module" {
  source = "./path/to/module" 
}

some_variable = ${module.some_module.some_output}

问题是当模块已经创建时Terraform会引发以下错误:

  

创建[资源类型] [资源名称]时出错:EntityAlreadyExists:具有[资源名称]的[资源类型]已经存在。           状态码:409,请求ID:...

当在外部terraform.tfstate范围内创建模块并且其中一个资源具有唯一的字段(例如“名称”)时,就会发生这种情况。

就我而言,它是在尝试使用已经使用该特定名称创建角色的IAM模块时发生的,但在其他情况下也可能发生(我不希望讨论专门针对我的用例) 。

我希望如果该模块的资源之一存在,则不会发生任何故障,并且该模块的输出可用于root模块

关于如何管理此问题的任何建议(也许使用特定的命令或标志)?


我发现了一些相关的线程:

Terraform doesn't reuse an AWS Role it just created and fails?

what is the best way to solve EntityAlreadyExists error in terraform?

Terraform error EntityAlreadyExists: Role with name iam_for_lambda already exists


编辑

对于@Martin Atkins请求,这里是导致错误的资源。

它是附加了2条策略(通过var.policies传递)的AWS EKS集群的基本角色:

resource "aws_iam_role" "k8s_role" {
  name = "k8s-role"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "eks.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}


resource "aws_iam_role_policy_attachment" "role-policy-attach" {
  role  = "${aws_iam_role.k8s_role.name}"
  count = "${length(var.policies)}"
  policy_arn = "${element(var.policies, count.index)}"
}

此角色被包装为模块,并传递给根模块。
发生上面在块引用中提到的错误是因为在根模块尝试创建该角色时该角色已经存在。

1 个答案:

答案 0 :(得分:1)

在Terraform的视图中,每个对象都由Terraform管理或不由Terraform管理。 Terraform避免隐式获取现有对象的所有权,因为如果这样做,那么当您随后运行terraform destroy时,您可能最终会无意间破坏了您不想由Terraform管理的内容。

在您的情况下,这意味着您需要确定名为k8s-role的角色是否由Terraform管理,并且如果您具有多个Terraform配置,则需要选择一种配置来管理该角色对象。

在将用于管理对象的Terraform配置中,可以使用resource "aws_iam_role"进行指定。如果需要访问任何其他配置,或者根本无法使用Terraform对其进行管理,则可以在需要时直接引用角色名称k8s-role。如果您需要除角色名称以外的其他信息,则可以使用the aws_iam_role data source获取该信息,而无需声明您要管理该对象:

data "aws_iam_role" "k8s" {
  name = "k8s-role"
}

例如,如果您需要使用此角色的ARN,则可以使用arn访问此数据资源的data.aws_iam_role.k8s.arn属性。

最后,如果您的角色当前不是由Terraform管理,但您希望将其置于Terraform的所有权下,则可以明确地告诉Terraform通过导入它来创建该关联,从而开始管理该现有对象在现有对象和您的resource块之间:

terraform import aws_iam_role.k8s_role k8s-role