我无法使用aws_volume_attachment
通过aws_instance
定位单个-target
。
问题是aws_instance
是使用count.index
从列表中获取的,这会强制terraform刷新该列表中的所有aws_instance
资源。
在我的具体案例中,我正在尝试管理带有terraform的consul集群。
目标是能够通过aws_instance
标志重新启动单个-target
资源,这样我就可以逐节点地升级/更改整个集群,而无需停机。
我有以下代码:
### 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)}"
}
这适用于初始化群集。
现在我在consul节点的user_data
init脚本中进行了更改,并希望逐个节点地推出。
我运行terraform plan -target=aws_volume_attachment.consul_data[0]
重新启动节点0。
这是当我遇到上述问题时,由于aws_instance
,terraform会呈现所有instance_id = "${element(aws_instance.consul.*.id, count.index)}"
资源。
有没有办法强迫"强迫"如果只针对单个aws_volume_attachment
,只有相应的aws_instance
资源?
答案 0 :(得分:1)
在撰写本文时,由于正如您所见,aws_instance.consul.*.id
这样的表达式会对所有实例产生依赖性,因此无法使用这种用法,在应用element
函数之前。
-target
选项不适合日常使用,而是仅在特殊情况下提供,例如小心地从意外更改中恢复。
对于这种特定情况,使用ignore_changes
生命周期设置可以更好地防止在user_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_data
属性的更改。然后,您可以通过一次手动污染资源来获得所需的逐步替换行为:
$ terraform taint aws_instance.consul[0]
在下一个计划中,Terraform将看到此资源实例受到污染并生成替换它的计划。这使您可以直接控制何时更换资源,因此您可以确保例如consul leave
步骤有机会先运行,或者需要进行其他任何清理。
建议使用此工作流程而不是-target
,因为它会使替换步骤显式化。 -target
在协作环境中可能会造成混淆,因为没有证据表明它的使用,因此没有明确解释当前状态是如何达成的。另一方面,taint
在其他团队成员可以看到的状态下明确标记您的意图,然后通过正常的计划/应用步骤替换资源。