Closed3

CodeDeployの不都合な挙動

mutaomutao

背景

CodeDeployを使用したB/GオンプレミスデプロイではAutoScalingが実行されると失敗することがある。

EC2 インスタンスが Amazon EC2 Auto Scaling を通じて起動され、その後で終了または再起動されると、そのインスタンスへのデプロイは、次の理由で失敗する場合があります。

進行中のデプロイで、スケールインイベントまたはその他の終了イベントにより、インスタンスは Amazon EC2 Auto Scaling グループからデタッチされた後に削除されます。デプロイは完了できないため、失敗します。

デプロイ中にBlue環境でスケールインが発生すると、インスタンスがTerminate状態になりトラフィックの切り替えに失敗するというもの。

インスタンスはTerminateされるものの、DeleteAutoScalingGroupはcallされないため、インスタンスが存在しないASGのみ残る。

なお、CodeDeployはASGをDetachしない。

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/troubleshooting-auto-scaling.html

mutaomutao

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 なら無効になっている。
 {省略}
}

https://docs.aws.amazon.com/codedeploy/latest/APIReference/API_GetDeploymentGroup.html

https://docs.aws.amazon.com/codedeploy/latest/userguide/deployment-groups-configure-advanced-options.html#auto-updates-outdated-instances

mutaomutao

じゃあどうすればいいの?

ドキュメントには、CodeDeployのAppSpecでスケールアウトプロセスを中断しなさい。と書いてある。

スケールアウトについてのみ言及されているが、 ScheduledActions もsuspendするため、動的スケーリングポリシーも対象となりスケールインも防げる。

デプロイ中に Amazon EC2 Auto Scaling スケールアウトプロセスを中断する場合は、のcommon_functions.shCodeDeploy での負荷分散に使用されるスクリプト。もしHANDLE_PROCS=trueの場合、デプロイ中に次の Auto Scaling イベントが自動的に中断されます。

  • AZRebalance
  • AlarmNotification
  • ScheduledActions
  • ReplaceUnhealthy

aws-sample にスクリプトが置いてあるのでこれを使う。

ただ、 CodeDeployDefault.OneAtATime でしかサポートされていないため注意が必要。

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/integrations-aws-auto-scaling.html#integrations-aws-auto-scaling-behaviors-mixed-environment

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-suspend-resume-processes.html

ちなみに

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環境でのスケーリングイベント停止はできないので注意が必要。

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html

このスクラップは2023/07/07にクローズされました