Terraform目标aws_volume_附件,仅包含列表中相应的aws_实例资源

Terraform目标aws_volume_附件,仅包含列表中相应的aws_实例资源,terraform,Terraform,我无法通过-target以单个aws\u卷\u附件及其相应的aws\u实例为目标。 问题在于,aws\u实例是通过使用count.index从列表中获取的,这迫使terraform刷新该列表中的所有aws\u实例资源 在我的具体案例中,我试图用terraform管理一个领事集群。 目标是能够通过-target标志重新加载单个aws\u实例资源,这样我就可以逐个节点升级/更改整个集群,而不会停机 我有以下tf代码: ### IP suffixes variable "subnet_cidr" {

我无法通过
-target
以单个
aws\u卷\u附件及其相应的
aws\u实例
为目标。 问题在于,
aws\u实例
是通过使用
count.index
从列表中获取的,这迫使terraform刷新该列表中的所有
aws\u实例
资源

在我的具体案例中,我试图用terraform管理一个领事集群。 目标是能够通过
-target
标志重新加载单个
aws\u实例
资源,这样我就可以逐个节点升级/更改整个集群,而不会停机

我有以下tf代码:

### IP suffixes
variable "subnet_cidr" { "10.10.0.0/16" }

// I want nodes with addresses 10.10.1.100, 10.10.1.101, 10.10.1.102
variable "consul_private_ips_suffix" {
  default = {
    "0" = "100"
    "1" = "101"
    "2" = "102"
  }
}

###########
# EBS
#
// Get existing data EBS via Name Tag
data "aws_ebs_volume" "consul-data" {
  count = "${length(keys(var.consul_private_ips_suffix))}"

  filter {
    name   = "volume-type"
    values = ["gp2"]
  }

  filter {
    name   = "tag:Name"
    values = ["${var.platform_type}.${var.platform_id}.consul.data.${count.index}"]
  }
}

#########
# EC2
#
resource "aws_instance" "consul" {
  count      = "${length(keys(var.consul_private_ips_suffix))}"

  ...

  private_ip = "${cidrhost(aws_subnet.private-b.cidr_block, lookup(var.consul_private_ips_suffix, count.index))}"
}

resource "aws_volume_attachment" "consul-data" {
  count       = "${length(keys(var.consul_private_ips_suffix))}"

  device_name = "/dev/sdh"
  volume_id   = "${element(data.aws_ebs_volume.consul-data.*.id, count.index)}"
  instance_id = "${element(aws_instance.consul.*.id, count.index)}"
}
这在初始化集群时非常有效。 现在,我在concur节点的
user_data
init脚本中做了一个更改,并希望逐节点展开。 我运行
terraformplan-target=aws\u volume\u attachment.consul\u data[0]
以重新定义节点0。 这就是当我遇到上述问题时,terraform呈现所有
aws\u实例
资源,因为
instance\u id=“${element(aws\u instance.consul.*.id,count.index)}”


有没有一种方法可以“强制”tf将单个
aws\u卷\u附件
与其对应的
aws\u实例
资源作为目标,在应用
元素
函数之前,类似于
aws\u instance.concur.*.id的表达式会在所有实例上创建依赖关系

-target
选项不适用于日常使用,仅在特殊情况下提供,例如从意外更改中小心恢复

对于这种特定情况,使用
ignore\u changes
生命周期设置可以更好地防止在
user\u data
更改时自动替换实例,如下所示:

resource "aws_instance" "consul" {
  count      = "${length(keys(var.consul_private_ips_suffix))}"

  ...

  private_ip = "${cidrhost(aws_subnet.private-b.cidr_block, lookup(var.consul_private_ips_suffix, count.index))}"

  lifecycle {
    ignore_changes = ["user_data"]
  }
}
通过此设置,Terraform将检测但忽略对
user\u data
属性的更改。然后,您可以通过一次手动污染一个资源来获得所需的逐步替换行为:

$ terraform taint aws_instance.consul[0]
在下一个计划中,Terraform将看到这个资源实例被污染,并生成一个计划来替换它。这使您可以直接控制何时更换资源,因此您可以确保例如,
consor leave
步骤有机会首先运行,或者您需要执行的任何其他清理

建议将此工作流置于
-target
之上,因为它使替换步骤更加明确<代码>-目标
在协作环境中可能会令人困惑,因为没有证据表明它的使用,因此没有明确说明如何达到当前状态<另一方面,代码>污染
,在其他团队成员可以看到的状态下明确标记您的意图,然后通过正常的计划/应用步骤替换资源