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 - 如何避免“强制使用新资源”的主要内容,如果未能解决你的问题,请参考以下文章

如何处理 terraform 进程崩溃并避免重试时资源泄漏?

避免更新 Terraform 中的资源

如何 Terraform 创建和验证 AWS 证书

如何使用 Terraform 配置 AWS EKS 自动扩缩器?

如何让 Terraform 读取 AWS 凭证文件?

如何使用 AWS Lambda 脚本通过 Terraform 部署 AWS 基础设施