12

我試圖讓AutoScalingRollingUpdate在我的自動縮放組的工作,通過將在線新實例,然後只有一次的新實例(一個或多個)正在接受交通,終止舊的實例。看起來像AutoScalingRollingUpdate是爲此目的而設計的。AWS AutoScalingGroup HealthCheckType「ELB」認爲實例「在職」過早

我將AutoScalingGroup的HealthCheckType設置爲'ELB'。我也對ELB集健康檢查要求:

  • 3成功的請求/爲「健康」
  • 10個不成功的請求/爲「不健康」
  • 沒有寬限期(零,0)

現在,從ELB的角度來看,當新實例上線時,它們不是幾分鐘的InService,這正是我所期望的。但是,從AutoScalingGroup的角度來看,它們幾乎立即被視爲InService,因此,我的AutoScalingGroup在新實例準備好接收流量之前將正常運行的實例退出服務。我很困惑,爲什麼ASG在ELB之前認爲這些實例是健康的,當時HealthCheckType被明確設置爲'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" 
    } 
    } 
+0

評論你的代碼,我認爲這個問題是不是在ASG'AutoScalingGroup'設置,它是在你ELB setting.'「HealthCheckGracePeriod」:「0」,'讓我奇怪的感覺,你可以改變' 300'。之後,ELB將負責處理可用性,而不是ASG。 ASG將根據ELB狀態進行升級和降級。 – BMW 2014-11-28 07:23:04

+0

即使在寬限期內,ASG在ELB執行之前也會考慮實例InService。這看起來像是CloudFormation中的一個bug。爲了解決這個問題,我實際上把時間設置爲零。 – d11wtq 2014-12-01 01:13:34

+0

您確定Load Balancer報告實例是「不健康的」嗎?你在哪裏看到這個狀態?有時控制檯不會立即更新。 AWS CLI是否給予您相同的狀態?您的應用在啓動時的HTTP狀態碼是什麼?它返回HTTP 200好嗎?您可以使用'curl -I ...'來檢查此問題。 – 2014-12-08 15:56:19

回答

17

首先,從我們的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相同的值。這確保了在實例有機會發送信號或達到暫停時間超時之前,我們從不開始使用ELB健康檢查。 http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html

通常,ASG啓動配置的UserData中的cfn-init引導腳本之後,會向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資源用於接收信號,但不再推薦這些資源。計數屬性是在創建時應該接收的信號的數量。該值應該等於ASG MinSize數字。

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

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

+6

非常有幫助,謝謝。 AutoScalingRollingUpdate不能用ELB運行狀況檢查類型「正常工作」,這很遺憾,因爲它會大大地清理這個問題。 99%的時間,如果您的健康檢查類型是'ELB',那麼這對於一個實例被視爲「InService」至關重要。 – d11wtq 2014-12-14 00:27:46

+0

感謝您的指導。使'HealthCheckGracePeriod'與'PauseTime'一致的建議非常重要。我們的'HealthCheckGracePeriod'比'PauseTime'短,其結果是ELB會開始過早地檢查健康狀況,將一些情況標記爲不健康,迫使新部署進行部署,並使整個滾動更新成爲不可預測,耗時的混亂。通過使這兩個超時相同,這些問題就消失了。 – 2016-03-03 06:35:41

4

我意識到這是一個有點晚,但也許它可能會節約一些時間和精力。

如果使用elbv2,那麼該命令如下所示。請注意0​​與"==",因爲這使我絆倒了幾個小時。 Ubuntu 16運行的命令爲/bin/sh,而不是/bin/bash,這意味着[ \"$state\" == \"\\\"healthy\\\"\" ]永遠不會成立。至少這是我的理解。

"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" 
     ]] 
    } 
    } 
} 
+0

更晚,那麼永遠不會!你剛剛救了我兩天的困惑/挫折。所有來到'=='。謝謝! – grep 2017-03-09 15:12:26

+0

我也面臨類似的問題,你能分享你完整的cloudformation模板嗎?謝謝 – Umer 2017-12-20 16:03:28

+0

我也面臨類似的問題,你可以分享你完整的cloudformation模板嗎?謝謝 – Umer 2017-12-20 16:04:17