AWS on Terraform - 如何避免“强制使用新资源”

Posted

技术标签:

【中文标题】AWS on Terraform - 如何避免“强制使用新资源”【英文标题】:AWS on Terraform - How to avoid 'forces new resource' 【发布时间】:2020-04-06 02:52:27 【问题描述】:

我正在使用 Terraform 启动我的云环境。

似乎即使是很小的配置更改也会影响幕后的许多资源。

例如,在我创建 AWS 实例的情况下 - 一个小的更改将导致所有实例的自动生成:

-/+ aws_instance.DC (new resource required)
      id:   "i-075deb0aaa57c2d" => <computed> (forces new resource) <----- How can we avoid that?
      ami:  "ami-01e306baaaa0a6f65" => "ami-01e306baaaa0a6f65"
      arn:  "arn:aws:ec2:ap-southeast-2:857671114786:instance/i-075deb0aaa57c2d" => <computed>
      associate_public_ip_address: "false" => <computed>
      availability_zone: "ap-southeast-2a" => <computed>
      .
      .

我的问题专门与作为提供商的 AWS 有关:我们如何避免每次都破坏/创建资源?

可能是 Terraform 中的相关标志?


相关话题:

Terraform > ipv6_address_count: "" => "0" (forces new resource)

terraform > forces new resource on security group


编辑:

plan 输出中潜水,似乎其中一个资源发生了变化:

  security_groups.#: "0" => "1" (forces new resource)
  security_groups.837544107: "" => "sg-0892062659392afa9" (forces new resource)

从如何避免重新创造的角度来看,问题仍然是相关的。

【问题讨论】:

ID 更改是替换资源的结果。那里应该有另一个属性标记为forces new resource 一般来说,控制这种情况的最佳方法是使用lifecycle 块来指定您不想强制使用新资源的属性。 谢谢@Adrian 我找到了这个:hashicorp.com/blog/zero-downtime-updates-with-terraform。如果您想对此有所了解,那就太好了(: 正如@Adrian 提到的,您需要显示该资源的完整计划输出以显示为什么 Terraform 需要替换资源而不是就地修改它。通常这只是由于 API 不允许以这种方式修改该资源。 【参考方案1】:

只有在修改资源以匹配新配置时没有明确的升级路径时,Terraform 资源才会强制使用新资源。这是通过在参数上设置ForceNew: true 标志在提供者级别完成的。

ami parameter on the aws_instance resource 显示了一个示例:

        Schema: map[string]*schema.Schema
            "ami": 
                Type:     schema.TypeString,
                Required: true,
                ForceNew: true,
            ,

这告诉 Terraform,如果更改了 ami 参数,那么它不应该尝试执行更新,而是销毁资源并创建一个新资源。

您可以使用 create_before_destroy lifecycle configuration 块覆盖销毁然后创建行为:

resource "aws_instance" "example" 
  # ...

  lifecycle 
    create_before_destroy = true
  

如果您更改了 ami 或其他无法更新的参数,Terraform 将创建一个新实例,然后销毁旧实例。

您如何处理资源的零停机升级可能很棘手,并且很大程度上取决于资源是什么以及您如何处理它。在official blog 中有更多相关信息。


在您非常具体的用例中,security_groups 改变了这一点,aws_instance resource docs 中提到:

注意:如果您在 VPC 中创建实例,请改用 vpc_security_group_ids。

这是因为 Terraform 的 AWS 提供商和 Terraform 使用的 EC2 API 向后兼容早于 VPC 的旧 EC2 Classic AWS 账户。使用这些帐户,您可以在 VPC 之外创建实例,但在创建实例后您无法更改该实例的安全组。如果您想更改实例的入口/出口,您需要在已经附加到实例的组中工作。对于基于 VPC 的实例,AWS 允许用户在不替换实例的情况下修改实例安全组,因此在 API 中提供了一种不同的指定方式。

如果您转而使用 vpc_security_group_ids 而不是 security_groups,那么您将能够在不替换实例的情况下修改这些内容。

【讨论】:

以上是关于AWS on Terraform - 如何避免“强制使用新资源”的主要内容,如果未能解决你的问题,请参考以下文章