【问题标题】:AWS AutoScalingGroup HealthCheckType 'ELB' considers instance "InService" prematurelyAWS AutoScalingGroup HealthCheckType 'ELB' 过早地考虑实例“InService”
【发布时间】:2015-01-23 02:31:39
【问题描述】:

我正在尝试让AutoScalingRollingUpdate 在我的自动缩放组上工作,方法是使新实例联机,然后仅在新实例接受流量时,终止旧实例。 AutoScalingRollingUpdate 似乎就是为此目的而设计的。

我将 AutoScalingGroup 的 HealthCheckType 设置为“ELB”。我还将 ELB 上的 HealthCheck 设置为要求:

  • 3 次成功的“健康”请求
  • 10 次针对“不健康”的不成功请求
  • 无宽限期(零,0)

现在,从 ELB 的角度来看,当新实例上线时,它们会在几分钟内不处于 InService 状态,这是我所期望的。但是,从 AutoScalingGroup 的角度来看,它们几乎立即被视为 InService,因此,我的 AutoScalingGroup 在新实例实际准备好接收流量之前将健康的实例停止服务。当 HealthCheckType 显式设置为“ELB”时,为什么 ASG 认为实例在 ELB 之前是健康的,我对此感到困惑。

我尝试过设置宽限期,但这并没有改变任何东西。事实上,我删除了 300 秒的宽限期,因为我认为实例在宽限期内可能是隐含的“InService”。

我知道我可以在滚动更新策略上设置 PauseTime,但这很脆弱,因为有时会在实例上线时发生故障,并且它们在完成配置之前就被删除和替换,所以 有时 ,可能会超出 PauseTime 窗口。另外,我想尽量减少我的应用同时运行两个不同版本的时间。

    ... ELB stuff ...

    "HealthCheck": {
      "HealthyThreshold": "3",
      "UnhealthyThreshold": "10",
      "Interval": "30",
      "Timeout": "15",
      "Target": {
        "Fn::Join": [
          "",
          [
            {"Fn::Join": [":", ["HTTP", {"Ref": "hostPort"}]]},
            {"Ref": "healthCheckPath"}
          ]
        ]
      }
    },

   ... ASG Stuff ...

  {
    ... snip ...

    "HealthCheckType": "ELB",
    "HealthCheckGracePeriod": "0",
    "Cooldown": "300"
  },
  "UpdatePolicy" : {
    "AutoScalingRollingUpdate" : {
      "MinInstancesInService" : "1",
      "MaxBatchSize" : "1"
    }
  }

【问题讨论】:

  • 查看您的代码,我认为问题不在 ASG AutoScalingGroup 设置中,而在您的 ELB 设置中。` "HealthCheckGracePeriod": "0",` 给我一种奇怪的感觉,你能改变吗到300。之后,ELB 将负责可用性,而不是 ASG。 ASG 将根据 ELB 状态进行扩展和缩减。
  • 即使有宽限期,ASG 也会在 ELB 之前考虑实例 InService。对我来说,这似乎是 CloudFormation 中的一个错误。为了解决这个问题,我实际上将时间设置为零。
  • 您确定负载均衡器将实例报告为“不健康”吗?您在哪里看到这种状态?控制台有时不会立即更新。 AWS CLI 是否为您提供相同的状态?您的应用程序启动时的 HTTP 状态代码是什么?它是否返回 HTTP 200 OK ?您可以使用 'curl -I ...' 进行检查
  • 是的,我很肯定。 ELB 的实际措辞是“OutOfService”,而 ASG 说的是“InService”。该应用程序实际上只是一个使用 Apache 在 Docker 中运行的静态网站。 “几分钟”只是拉下 Docker 映像所需的时间。在那段时间里,80 端口甚至都没有打开。

标签: amazon-web-services autoscaling amazon-elb amazon-cloudformation


【解决方案1】:

我意识到这有点晚了,但也许它可以节省一些时间和精力。

如果使用 elbv2,则命令如下所示。请注意"=""==",因为这让我绊倒了好几个小时。 Ubuntu 16 以 /bin/sh 而不是 /bin/bash 运行命令,这意味着 [ \"$state\" == \"\\\"healthy\\\"\" ] 永远不会导致 true。至少这是我的理解。

"commands": {
  "ELBHealthCheck": {
    "command": {
      "Fn::Join": ["", [
        "until [ \"$state\" = \"\\\"healthy\\\"\" ]; do ",
        "state=$(aws elbv2 describe-target-health ",
        "--region ", {
          "Ref": "AWS::Region"
        },
        " ",
        "--target-group-arn ", {
          "Ref": "ELBRestPublicTargetGroup"
        },
        " ",
        "--targets Id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) ",
        "--query TargetHealthDescriptions[0].TargetHealth.State); ",
        "echo $(date): [$state] >> /tmp/health.log; ",
        "sleep 10; ",
        "done"
      ]]
    }
  }
}

【讨论】:

  • 迟到总比永远好!你刚刚救了我两天的困惑/沮丧。全部归结为==。谢谢!
  • 我也遇到了类似的问题,可以分享一下完整的cloudformation模板吗?谢谢
  • 我也遇到了类似的问题,可以分享一下完整的cloudformation模板吗?谢谢
【解决方案2】:

首先,根据我们使用 CloudFormation 的经验,ASG HealthCheckType 和 HealthCheckGracePeriod 主要在 CloudFormation 事件范围之外使用。只要将新实例添加到 ASG,这些属性就会发挥作用。这可以在 CloudFormation 更新期间,也可以在 Auto Scaling 事件期间或自我修复事件期间。在后一种情况下,将 HealthCheckGracePeriod 设置为一个值非常重要,该值可以让新实例有足够的时间在考虑 ELB 运行状况检查之前上线。

您最感兴趣的功能似乎是当您使用修改后的启动配置运行 CloudFormation 更新时调用的 UpdatePolicy。神奇的属性是 WaitOnResourceSignals,它强制 ASG 在考虑更新成功之前等待成功信号。

  "UpdatePolicy" : {
    "AutoScalingRollingUpdate" : {
      "MinInstancesInService" : "1",
      "MaxBatchSize" : "1",
      "PauseTime" : "PT15M",
      "WaitOnResourceSignals" : "true"
    }
  },

当 WaitOnResourceSignals 属性设置为 true 时,PauseTime 属性变为超时。如果 ASG 在 15 分钟的 PauseTime 内没有收到信号,则认为更新失败并终止新实例。一旦 ASG 收到成功信号,ASG 健康检查就会开始发挥作用,除非 HealthCheckGracePeriod 尚未到期。我们通常将 HealthCheckGracePeriod 设置为与 PauseTime 相同的值。这确保了在实例有机会发送信号或达到 PauseTime 超时之前,我们永远不会开始使用 ELB 健康检查。 http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html

通常,成功信号会在 cfn-init 引导脚本之后从 ASG 启动配置的 UserData 发送到 ASG。

"UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
     "#!/bin/bash -xe\n",
     "yum update -y aws-cfn-bootstrap\n",

     "/opt/aws/bin/cfn-init -v ",
     "         --stack ", { "Ref" : "AWS::StackName" },
     "         --resource LaunchConfig ",
     "         --configsets full_install ",
     "         --region ", { "Ref" : "AWS::Region" }, "\n",

     "/opt/aws/bin/cfn-signal -e $? ",
     "         --stack ", { "Ref" : "AWS::StackName" },
     "         --resource WebServerGroup ",
     "         --region ", { "Ref" : "AWS::Region" }, "\n"
]]}}

这对于许多情况来说已经足够了,但有时当我们将成功信号发送回 ASG 时,实例可能还没有准备好。例如,我们可能希望等待后台进程加载数据或等待我们的应用程序服务器启动。如果我们的 ELB 健康检查针对需要我们的应用程序运行的 URL,则尤其如此。在这些情况下,我们希望延迟成功信号,直到我们的实例准备好。下面是一个示例,说明如何创建启动配置 configSet 以延迟信号,直到 ELB API 返回实例的“InService”状态。

  "verify_instance_health" : {
    "commands" : {
      "ELBHealthCheck" : {
        "command" : { "Fn::Join" : ["", [ 
          "until [ \"$state\" == \"\\\"InService\\\"\" ]; do ",
          "  state=$(aws --region ", { "Ref" : "AWS::Region" }, " elb describe-instance-health ",
          "              --load-balancer-name ", { "Ref" : "ElasticLoadBalancer" }, 
          "              --instances $(curl -s http://169.254.169.254/latest/meta-data/instance-id) ",
          "              --query InstanceStates[0].State); ",
          "  sleep 10; ",
          "done"
        ]]}
      }
    }
  }

有关更多信息和使用 ELB 健康检查的完整示例,请参阅此论坛 - https://forums.aws.amazon.com/ann.jspa?annID=2741

注意:这些示例还要求您使用 ASG CreationPolicy 属性在 ASG 创建期间接收信号。过去,WaitCondition 和 WaitConditionHandle 资源用于接收信号,但不再推荐使用这些资源。 Count 属性是在创建时应接收的信号数。此值应等于 ASG MinSize 数。

  "CreationPolicy" : {
    "ResourceSignal" : {
      "Timeout" : "PT15M",
      "Count"   : "2"
    }
  },

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-creationpolicy.html

【讨论】:

  • 非常有帮助,谢谢。遗憾的是 AutoScalingRollingUpdate 不能与 ELB 健康检查类型“正常工作”,因为它会极大地清理它。 99% 的情况下,如果您的运行状况检查类型是“ELB”,这就是将实例视为“InService”的重要因素。
  • 感谢您的出色指导。使HealthCheckGracePeriodPauseTime 一致的建议至关重要。我们的HealthCheckGracePeriodPauseTime 短,结果是ELB 会过早开始检查健康状况,将某些实例标记为不健康,强制部署新实例,并使整个滚动更新变得不可预测且耗时.通过使两个超时相同,这些问题就消失了。
猜你喜欢
  • 2016-08-05
  • 2015-05-25
  • 2019-01-10
  • 2012-03-14
  • 2017-08-03
  • 1970-01-01
  • 1970-01-01
  • 2021-11-15
  • 2017-03-24
相关资源
最近更新 更多