Terraform 是“地形”吗;“循环”;没用?还是我遗漏了什么?

Terraform 是“地形”吗;“循环”;没用?还是我遗漏了什么?,terraform,Terraform,我今天写了一些使用“循环”的配置,但直到后来我才想知道这是否是正确的路径,因为terraform将资源作为列表/数组保存在状态文件中 考虑以下配置: locals { users_list = [ "ab", "cd", "ef" ] } resource "aws_iam_user" "users" { count = "${length(local.users_list)}" name = "${local.users_list["${count.index}"]}

我今天写了一些使用“循环”的配置,但直到后来我才想知道这是否是正确的路径,因为terraform将资源作为列表/数组保存在状态文件中

考虑以下配置:

locals {
    users_list = [ "ab", "cd", "ef" ]
}

resource "aws_iam_user" "users" {
    count = "${length(local.users_list)}"
    name = "${local.users_list["${count.index}"]}"
    path = "/"
}
运行“terraform apply”将创建用户,并在状态文件中创建以下资源:

  • aws_iam_用户。用户[0]
  • aws_iam_用户。用户[1]
  • aws_iam_用户。用户[2]
但是,例如,如果我删除前两个用户中的一个,如下所示:

locals {
        users_list = [ "cd", "ef" ]
}
然后terraform将尝试更改状态文件([0]-->“cd”、[1]-->“ef”)中的资源以及AWS中的用户本身,这可能是灾难性的,因为每个用户都有自己的密钥,这样做会造成混乱。这也与其他资源类型相关,尽管有些资源删除并再次创建不会造成如此混乱,但这仍然是错误的


所以,对于我的问题,就像在标题中一样——也许我完全弄错了?或者这就是它的工作方式?(使整个“循环”机制毫无用处)

v0.11.x之前的terraform实际上并不正式支持循环。使用
count.index
as循环的方法来自博客

从版本0.12开始(目前仍处于beta测试阶段),它支持使用新关键字的循环,但我仍然不能保证它是否解决了您问题中的问题

因此,我将详细说明问题所在,以及如何解决问题,像@Aniket Chopade这样的人可以理解这个问题的来源

在改变了当地人之后

$ terraform apply -auto-approve
aws_iam_user.users[0]: Refreshing state... (ID: ab)
aws_iam_user.users[1]: Refreshing state... (ID: cd)
aws_iam_user.users[2]: Refreshing state... (ID: ef)
aws_iam_user.users[2]: Destroying... (ID: ef)
aws_iam_user.users[1]: Modifying... (ID: cd)
  name: "cd" => "ef"
aws_iam_user.users[0]: Modifying... (ID: ab)
  name: "ab" => "cd"
aws_iam_user.users[2]: Destruction complete after 2s

Error: Error applying plan:

2 error(s) occurred:

* aws_iam_user.users[0]: 1 error(s) occurred:

* aws_iam_user.users.0: Error updating IAM User ab: EntityAlreadyExists: User with name cd already exists.
    status code: 409, request id: 24853da7-452c-11e9-a853-bf4c89d8ebba
* aws_iam_user.users[1]: 1 error(s) occurred:

* aws_iam_user.users.1: Error updating IAM User cd: EntityAlreadyExists: User with name ef already exists.
    status code: 409, request id: 24839027-452c-11e9-b3d5-3deb12943195
我必须将这些资源标记为已销毁并再次应用

$ terraform taint aws_iam_user.users.1
The resource aws_iam_user.users.1 in the module root has been marked as tainted!

$ terraform taint aws_iam_user.users.0
The resource aws_iam_user.users.0 in the module root has been marked as tainted!

$ terraform apply -auto-approve
...
aws_iam_user.users[0]: Destroying... (ID: ab)
aws_iam_user.users[1]: Destroying... (ID: cd)
aws_iam_user.users[0]: Destruction complete after 2s
aws_iam_user.users[0]: Creating...
  arn:           "" => "<computed>"
  force_destroy: "" => "false"
  name:          "" => "cd"
  path:          "" => "/"
  unique_id:     "" => "<computed>"
aws_iam_user.users[1]: Destruction complete after 2s
aws_iam_user.users[1]: Creating...
  arn:           "" => "<computed>"
  force_destroy: "" => "false"
  name:          "" => "ef"
  path:          "" => "/"
  unique_id:     "" => "<computed>"

$terraform污染aws\u iam\u用户。用户。1
模块根目录中的资源aws_iam_user.users.1已标记为受污染!
$terraform taint aws_iam_用户。用户。0
模块根目录中的资源aws_iam_user.users.0已标记为受污染!
$terraform应用-自动批准
...
aws\u iam\u用户。用户[0]:正在销毁。。。(ID:ab)
用户[1]:正在销毁。。。(ID:cd)
aws_iam_用户。用户[0]:2秒后销毁完成
aws\u iam\u用户。用户[0]:正在创建。。。
arn:“”=>“”
强制销毁:“”=>“假”
名称:“”=>“cd”
路径:“”=>“/”
唯一\u id:“”=>“”
aws_iam_用户。用户[1]:2秒后销毁完成
用户[1]:正在创建。。。
arn:“”=>“”
强制销毁:“”=>“假”
名称:“”=>“ef”
路径:“”=>“/”
唯一\u id:“”=>“”

我的结论是,在当前情况下,
污染
资源,如果您更改列表中的顺序,则强制terraform创建新资源

在上述情况下,删除ab用户导致的确切问题是什么?是否也在数组中创建密钥?谢谢您的回答。作为一种解决方法,我更愿意在状态中更改阵列(使用
地形状态mv
),这样其他用户将保持不变,只有我删除的用户将被销毁。但这当然太乱了。另外,如果资源仍然是状态文件中的数组,我不确定版本0.12中的
for_each
(或
for
)循环是否有帮助。您提供的链接中的示例是资源中的动态时钟。我认为实现这一目标的唯一方法是两种方法之一:(在下一条评论中)1。Terraform应该将状态文件中的资源保存为资源映射/散列,而不是数组,以便知道哪个用户属于哪个位置。2.资源仍将保存为数组,但terraform将进行一些计算,以了解我是否刚刚从列表中删除了一项。也许我会为此打开一个功能请求,但我不确定terraform的内部以及这些选项是否有意义。@roeezab否,
terraform state mv
根本无法解决这个问题
terraform state rm
仅用于清除tfstate文件中的指定资源,而不是真正清除aws帐户中的资源
taint
将标记要销毁的资源,因此,
terraform apply
将始终首先销毁这些受污染的资源,然后应用其余的更改。同意为此直接向GitHub中的terraform团队提出功能/错误请求。严格来说,这不是真的
count
始终被正式用于创建多个资源(否则它的意义是什么),这包括API没有要传递给它的count概念的地方(例如,EC2实例允许您在单个API调用中指定在保留中创建的多个实例)。0.12确实在资源中添加了额外的循环功能,它最终将取代
count
语法,但
count
对资源仍然有效。此外,0.12将正确处理自动删除
count
资源中的非最后一个元素。