Terraform破坏 - 目标行为

时间:2018-04-20 16:51:19

标签: terraform

我只是在讨论terraform和terraform destroy参数。如果我 有三个节点,我用terraform destroy --target删除了一个节点我有以下内容:

$ terraform state list
packet_device.jenkins-node[0]
packet_device.jenkins-node[1]
packet_device.jenkins-node[2]
$ terraform destroy --target packet_device.jenkins-node[1]
....
....
....
$ terraform state list
packet_device.jenkins-node[0]
packet_device.jenkins-node[2]

如果我将节点数减少到2,则terraform销毁jenkins节点2和 创建一个新的(jenkins节点1)。计数仍然是两个,但是是terraform 销毁一台服务器并创建一台新服务器。有没有办法禁用它 行为?

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

packet_device.jenkins-node.2: Refreshing state... (ID: XXXX)
packet_device.jenkins-node.0: Refreshing state... (ID: XXXX)
The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed. Cyan entries are data sources to be read.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

  + packet_device.jenkins-node[1]
      access_private_ipv4:     "<computed>"
      access_public_ipv4:      "<computed>"
      access_public_ipv6:      "<computed>"
      always_pxe:              "false"
      billing_cycle:           "hourly"
      created:                 "<computed>"
      facility:                "sjc1"
      hardware_reservation_id: "<computed>"
      hostname:                "jenkins-eloy"
      locked:                  "<computed>"
      network.#:               "<computed>"
      operating_system:        "ubuntu_17_10"
      plan:                    "baremetal_0"
      project_id:              "ea13e749-0b1b-4c0d-9701-d0a3df7391f2"
      public_ipv4_subnet_size: "<computed>"
      root_password:           "<sensitive>"
      state:                   "<computed>"
      updated:                 "<computed>"

  - packet_device.jenkins-node[2]


Plan: 1 to add, 0 to change, 1 to destroy.

如果我用三个节点设置terraform计划,我得到以下内容:

$ export TF_VAR_nodes=3
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

packet_device.jenkins-node.0: Refreshing state... (ID: 02287fed-c281-4027-8603-bcad6db8b8e6)
packet_device.jenkins-node.2: Refreshing state... (ID: f35fa202-423d-4e02-9d18-1f1bd7f7a3ef)
The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed. Cyan entries are data sources to be read.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

  + packet_device.jenkins-node[1]
      access_private_ipv4:     "<computed>"
      access_public_ipv4:      "<computed>"
      access_public_ipv6:      "<computed>"
      always_pxe:              "false"
      billing_cycle:           "hourly"
      created:                 "<computed>"
      facility:                "sjc1"
      hardware_reservation_id: "<computed>"
      hostname:                "jenkins-eloy"
      locked:                  "<computed>"
      network.#:               "<computed>"
      operating_system:        "ubuntu_17_10"
      plan:                    "baremetal_0"
      project_id:              "ea13e749-0b1b-4c0d-9701-d0a3df7391f2"
      public_ipv4_subnet_size: "<computed>"
      root_password:           "<sensitive>"
      state:                   "<computed>"
      updated:                 "<computed>"


Plan: 1 to add, 0 to change, 0 to destroy.

有什么想法吗?

2 个答案:

答案 0 :(得分:5)

没有。但是,如果要销毁packet_device.jenkins-node[1],则应运行

terraform state mv packet_device.jenkins-node.2 packet_device.jenkins-node.1

因此节点2成为节点1

答案 1 :(得分:0)

更新基础结构的唯一安全方法是编辑文件,计划和应用。此处列出的所有其他方法仅应在非正常情况下使用。并及时导致您的状态从您正在运行和付费的实际基础架构中转移出来。


您的Terraform基础结构似乎在某处包含count

module "packet_device" "jenkins_node" {
    count = 3
    ...other configs using ${count.index}
}

如果确实如此,则在使用计数时有一个局限性,即您不能仅仅增加和减少计数就可以向上和向下缩放。

由于使用计数,terraform将以索引格式存储每个模块的状态。 [0:{module1},1:{module2},2:{module3}],当您将计数减少到2或删除单个实例时,它将导致索引发生变化,terraform会将其标记为更改。因为它将索引视为资源的身份。

因此,假设您删除了索引0,则最终会得到[0: {module2},1: {module3}]

module2的新索引为0,而module3的新索引为1。所以terraform将不得不销毁并重新创建这些模块,因为它不知道发生了什么。

不幸的是,您无法使用计数配置来阻止此行为。


您需要做的是使用映射或for_each,这样资源将通过键而不是索引进行匹配。因此,删除或添加其他资源(在同一块中)不会互相影响。

这只是一个例子...

module "packet_device" "jenkins_node" {
    for_each = toset(["key1", "key2", "key3"])
    ...other configs and access the value by ${each.value}
}

更多关于for_each的信息,请访问documentation