我在 Terraform 的负载均衡器目标组中有几个aws_instance
节点。我做了一个更改,需要销毁每个实例并重新创建它。默认情况下,Terraform 将同时销毁并重新创建所有这些实例。一次销毁所有这些节点是不好的,因为这样负载均衡器中就不会有节点。
有没有办法配置 Terraform,以便在销毁/创建其他实例之前等待一个实例被完全销毁/重新创建?
您可以使用create_before_destroy
生命周期自定义来强制 Terraform 创建新资源,然后再在替换操作期间销毁旧资源。
不幸的是,如果您的实例需要一段时间才能启动所需的服务,那么您仍然会遇到问题,因为一旦 AWS API 返回实例正在运行,Terraform 就会认为它已完成工作并开始终止它想要替换的旧实例。
可以通过将实例放在自动缩放组中(即使不需要它们进行自动缩放,因此具有相同的最小和最大大小或不将自动缩放策略附加到组(并将health_check_type
设置为ELB
来解决此问题。这将确保实例在通过负载均衡器运行状况检查而不是默认 EC2 运行状况检查(即,如果它正在运行并且没有系统或实例状态检查失败(之前不会被视为运行状况良好。这样,Terraform 将等到新 ASG 具有通过负载均衡器运行状况检查的最小实例数(并附加到相关目标组或 ELB(,然后才会认为它已完成,然后开始删除旧 ASG。
有一个depends_on
属性,它允许设置显式依赖项并按顺序创建内容。它对您的方案是有限的,因为它不会等待刚刚创建的新实例"就绪"。
我在阅读您的方案时想到的一个想法是,您可以使用extermal
数据源。不是肯定的,它是为这种事情准备的,但我认为它可以工作。从本质上讲,您可以编写一个脚本,该脚本将使用 AWS CLI 以及查看实例是否已创建并准备就绪所需的任何其他内容。如果您使用 withdepends_on
或者将external
数据源的输出链接到下一个实例(使用输出设置标签?(,我认为它会达到您想要的效果。
不过,这个设计对我来说有点闻起来。还有其他AWS服务和功能可以为您做这种事情,例如带有负载均衡器运行状况检查的ECS滚动部署。
资源:
https://www.terraform.io/docs/providers/external/data_source.html
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-create-loadbalancer-rolling.html
编辑:
如果您坚持使用 EC2 实例,解决此问题的另一种原生 AWS 方法可能是使用生命周期挂钩。我已经将 EC2 用户数据脚本与调用 Lambda 函数的生命周期钩子结合使用,以执行自定义 Kafka 集群的滚动部署和配置(在 MSK 之前(。这要求我按顺序启动实例,并为每个实例分配一个唯一的代理 ID。听起来与您的方案类似。
资源: https://docs.aws.amazon.com/autoscaling/ec2/userguide/lifecycle-hooks.html