CodeDeployの不都合な挙動
背景
CodeDeployを使用したB/GオンプレミスデプロイではAutoScalingが実行されると失敗することがある。
EC2 インスタンスが Amazon EC2 Auto Scaling を通じて起動され、その後で終了または再起動されると、そのインスタンスへのデプロイは、次の理由で失敗する場合があります。
進行中のデプロイで、スケールインイベントまたはその他の終了イベントにより、インスタンスは Amazon EC2 Auto Scaling グループからデタッチされた後に削除されます。デプロイは完了できないため、失敗します。
デプロイ中にBlue環境でスケールインが発生すると、インスタンスがTerminate状態になりトラフィックの切り替えに失敗するというもの。
インスタンスはTerminateされるものの、DeleteAutoScalingGroupはcallされないため、インスタンスが存在しないASGのみ残る。
なお、CodeDeployはASGをDetachしない。
CodeDeploy実行中にスケールアウトが起きた場合
新しいインスタンスは、今回デプロイ中のアプリケーションリビジョンではなく、前回デプロイしたアプリケーションリビジョンで更新される。
その後、Register Targetの対象となるため、リビジョンが異なるインスタンスが登録され、異なるリビジョンが混在する状態となる。
しかしデプロイ終了後にCodeDeployがフォローオンデプロイを開始し、古いインスタンスを更新してくれる機能がある。
get-deployment-group APIを使用することで、自動でフォローオンデプロイが実行されるかを確認することができる。
> aws deploy get-deployment-group --application-name ${application-name} --deployment-group-name ${deployment-group-name}
"deploymentGroupInfo": {
{省略}
"outdatedInstancesStrategy": "UPDATE", # IGNORE なら無効になっている。
{省略}
}
じゃあどうすればいいの?
ドキュメントには、CodeDeployのAppSpecでスケールアウトプロセスを中断しなさい。と書いてある。
スケールアウトについてのみ言及されているが、 ScheduledActions
もsuspendするため、動的スケーリングポリシーも対象となりスケールインも防げる。
デプロイ中に Amazon EC2 Auto Scaling スケールアウトプロセスを中断する場合は、のcommon_functions.shCodeDeploy での負荷分散に使用されるスクリプト。もしHANDLE_PROCS=trueの場合、デプロイ中に次の Auto Scaling イベントが自動的に中断されます。
- AZRebalance
- AlarmNotification
- ScheduledActions
- ReplaceUnhealthy
aws-sample にスクリプトが置いてあるのでこれを使う。
ただ、 CodeDeployDefault.OneAtATime
でしかサポートされていないため注意が必要。
ちなみに
aws-sample のスクリプトを使用せずとも SuspendProcesses
はCodeDeployからGreen環境のAutoScalingGroupに対して実行されている。
CloudTrail で SuspendProcesses
のAPI実行履歴を見てみるとわかる。
以下のような履歴が発見できるはず。
"eventSource": "autoscaling.amazonaws.com",
"eventName": "SuspendProcesses",
"awsRegion": "region",
"sourceIPAddress": "codedeploy.amazonaws.com",
"userAgent": "codedeploy.amazonaws.com",
"requestParameters": {
"autoScalingGroupName": "ASG_NAME",
"scalingProcesses": [
"AddToLoadBalancer",
"AlarmNotification",
"AZRebalance",
"InstanceRefresh",
"ReplaceUnhealthy",
"ScheduledActions"
]
},
CloudTrailから「リソース名」を指定して、AutoScalingGroup名で検索すれば実行詳細が見える。
このため、CodeDeploy実行中にGreen環境でのスケーリングイベントを気にする必要はない。
つまり、真に気にする必要があるのは、 Blue環境 でのスケーリングイベントだということ。
aws-sample にある appspec.yaml では、 ApplicationStop
ApplicationStart
でスクリプトを実行するようになっているため、Blue環境でのスケーリングイベント停止はできないので注意が必要。