Auto-Scaling 组不会在启动配置更改时更新

Posted

技术标签:

【中文标题】Auto-Scaling 组不会在启动配置更改时更新【英文标题】:Auto-Scaling Groups Don't Update on Launch Configuration Change 【发布时间】:2017-04-20 11:44:38 【问题描述】:

我有一个 AWS Auto-Scaling 组、一个启动配置和一个在 Terraform 中定义的 Auto-Scaling 组策略,如下所示:

resource "aws_autoscaling_group" "default" 
  name = "..."

  health_check_type = "EC2"
  vpc_zone_identifier = ["$..."]

  min_size = "$var.asg_capacity"
  max_size = "$var.asg_capacity * 2"
  desired_capacity = "$var.asg_capacity"

  launch_configuration = "$aws_launch_configuration.default.id"

  termination_policies = ["OldestInstance"]


resource "aws_autoscaling_policy" "default" 
  name = "..."
  autoscaling_group_name = "$aws_autoscaling_group.default.name"

  scaling_adjustment = "$var.asg_capacity"
  adjustment_type = "ChangeInCapacity"
  cooldown = 300


resource "aws_launch_configuration" "default" 
  name_prefix = "..._"

  image_id = "$var.coreos_ami_id"
  instance_type = "$var.ec2_instance_type"
  iam_instance_profile = "$aws_iam_instance_profile.default.arn"
  key_name = "..."

  security_groups = ["$aws_security_group.default.id"]

  user_data = "$data.template_file.cloud_init.rendered"

  lifecycle 
    create_before_destroy = true
  

当我更改我的用户数据时,会创建一个新的启动配置,然后将其附加到自动缩放组。我假设这会导致自动缩放组按var.asg_capacity 实例扩展,等待 300 秒,然后按照OldestInstance 拆除旧的。

当我在 CloudFormation 中做过类似的事情时,我使用了the following configuration options:

ASG:
  Type: AWS::AutoScaling::AutoScalingGroup
  UpdatePolicy:
    AutoScaleRollingUpdate:
      # during a scale, 6 instances in service
      MaxBatchSize: 3
      MinInstancesInService: 3
      PauseTime: PT5M
  Properties:
    ...

Terraform 中有类似的东西吗?当我更改启动配置时,我真的希望我的自动缩放组能够更改。

【问题讨论】:

【参考方案1】:

从 AWS 预置程序 3.22.0 版开始,您可以将 instance_refresh 配置块添加到您的 aws_autoscaling_group 资源。可能可行的最简单配置是:

instance_refresh 
  strategy = "Rolling"

【讨论】:

【参考方案2】:

我假设这会导致自动扩展组按 var.asg_capacity 实例扩展,等待 300 秒,然后根据 OldestInstance 拆除旧的。

不幸的是,这个假设是不正确的。当您更改启动配置时,唯一发生的事情是在您的 AWS 账户中创建新的启动配置并与 Auto Scaling 组 (ASG) 关联。这意味着该 ASG 中的所有未来实例都将使用新的启动配置启动。但是,仅更改启动配置不会触发任何实例的启动,因此您不会看到您的更改。

要强制启动新实例,您必须做几件事:

    将 ASG 的 name 参数配置为直接依赖于启动配置的名称。这样,每次启动配置发生变化(更新 AMI 或用户数据时也会发生变化),Terraform 将尝试替换 ASG。 将 ASG 的 create_before_destroy 参数设置为 true,因此 Terraform 每次尝试替换它时,都会在销毁原始文件之前创建替换。 将 ASG 的 min_elb_capacity 参数设置为集群的 min_size,这样 Terraform 将至少等待来自新 ASG 的许多服务器在 ELB 中注册,然后才会开始销毁原始 ASG。

以下是 Terraform 代码的粗略概念:

resource "aws_launch_configuration" "example" 
  image_id        = "$var.ami"
  instance_type   = "$var.instance_type"

  user_data = "$data.template_file.user_data.rendered"

  lifecycle 
    create_before_destroy = true
  


resource "aws_autoscaling_group" "example" 
  name                 = "$var.cluster_name-$aws_launch_configuration.example.name"
  launch_configuration = "$aws_launch_configuration.example.id"
  availability_zones   = ["$data.aws_availability_zones.all.names"]

  min_size         = "$var.min_size"
  max_size         = "$var.max_size"
  min_elb_capacity = "$var.min_size"

  lifecycle 
    create_before_destroy = true
  

对于一个完整的工作示例,请查看本书 Terraform: Up & Running 中的 zero-downtime deployment example code。

【讨论】:

感谢您的回答。令人震惊的是,Terraform 仍然没有提供一种内置的方法来做到这一点,而无需在每个配置上启动和拆除自动缩放组。 @NaftuliKay 是的,不幸的是,这在 Terraform 社区中仍然是一个未解决的问题:github.com/hashicorp/terraform/issues/1552。目前,使用上面的 create_before_destroy 方法是使用纯 Terraform 代码的最佳解决方案。它接近于蓝/绿部署,因此它不是一个糟糕的选择,但它并不适用于所有人,而且至关重要的是,它不适用于动态大小的 ASG。 另一种可能的方法是将 ASG 放入封装在总体 Terraform 配置中的 CloudFormation 模板中,并允许它处理对每个主机的滚动更新,因为 Terraform 本身无法做到这一点。 @Yevgeniy Brikman 在github.com/hashicorp/terraform/issues/… 中提出了这种方法。 至少,用启动配置的名称更新自动缩放组的名称以触发整个重新部署流程是否足够? @PatrikIselind:当然可以,但是原来的 ASG 会在创建新的 ASG 之前被删除,所以在这之间会有停机时间。

以上是关于Auto-Scaling 组不会在启动配置更改时更新的主要内容,如果未能解决你的问题,请参考以下文章

Ansible:将正在运行的 EC2 实例添加到 Auto-scaling 组

在 Terraform 销毁期间,terraform 在销毁 Auto-scaling 组之前尝试销毁 ECS 集群并且失败了

如何在不使用 Auto-scaling 的情况下在一个区域的 3 个不同 AZ 中启动三个相同的 EC2 实例

在 pine 脚本中使用循环时更改元组值

Auto Scaling Group 启动配置更改

Capistrano 和 Auto-Scaling AWS