📝

Auto Scaling に対するデプロイが 2 回実行される事象について

に公開

Configure advanced options for a deployment group - AWS CodeDeploy

For example, if your EC2 instances are launched into an Auto Scaling group (ASG) while a CodeDeploy deployment is underway, those instances receive the older revision of your application instead of the latest one. To bring those instances up to date, CodeDeploy automatically starts a follow-on deployment (immediatedly after the first) to update any outdated instances.

デプロイ中にスケールアウトした場合、以下の挙動になります。

  1. スケールアウトしたインスタンスに古いリビジョンをデプロイ
  2. 古いリビジョンのデプロイ完了後、新しいリビジョンをデプロイ

上記の結果、スケールアウトしたインスタンスに対してデプロイが 2 回実行されます。

試してみた

Tutorial: Use CodeDeploy to deploy an application to an Auto Scaling group - AWS CodeDeploy
上記チュートリアルを参考に Auto Scaling グループと CodeDeploy リソースを作成しました。

1 つ目のインスタンスへのデプロイ

まずは Auto Scaling グループ内のインスタンス数を 1 にしてデフォルトのアプリケーションをデプロイしました。
デフォルトのアプリケーションはチュートリアル内の以下の URL からダウンロード可能です。

http://s3-ap-northeast-1.amazonaws.com/aws-codedeploy-ap-northeast-1/samples/latest/SampleApp_Linux.zip

デプロイ後に EC2 インスタンスにアクセスすると以下の画面が表示されます。

初回のデプロイに使用したリビジョン名は SampleApp_Linux.zip です。

アプリケーションの変更

デプロイ中のスケールアウトを実現するために、デフォルトアプリケーションに 3 分間の sleep 処理を追加しました。

scripts/start_server
#!/bin/bash
service httpd start
sleep 180 # 追記箇所

上記ファイルを含むアプリケーションファイル群を test.zip という名前で zip ファイル化し、S3 バケットにアップロードしておきました。

初回のデプロイに使用したリビジョンと zip ファイル名を変えたのはどのリビジョンがデプロイされたかをわかりやすくするためです。

デプロイ中にスケールアウトしてみる

最新のデプロイでは test.zip を指定してデプロイします。
デプロイ中に Auto Scaling の希望容量を 2 に変更してスケールアウトするよう設定しました。

デプロイ後、もともと起動していたインスタンスには test.zip がデプロイされました。

一方で、デプロイ中にスケールアウトしたインスタンスには、Auto Scaling グループアクションで SampleApp_Linux.zip がデプロイされました。

この状態では Auto Scaling グループ内の EC2 インスタンスにデプロイされているリビジョンが異なる状況になっています。

スケールアウトしたインスタンスへのデプロイが完了してから数分後、スケールアウトしたインスタンスに対して自動的に 2 回目のデプロイが実行されました。
2 回目のデプロイでは「CodeDeploy が古いインスタンスを更新します」という開始理由が表示されていました。
また、リビジョンには test.zip が使用されていることも確認できました。

以上より、スケールアウトしたインスタンスに対しては以下の挙動になることが確認できました。

  1. スケールアウトしたインスタンスに古いリビジョンをデプロイ
  2. 古いリビジョンのデプロイ完了後、新しいリビジョンをデプロイ

自動デプロイの設定について

ドキュメントに記載されている通り、自動デプロイするかどうかは AWS CLI の update-deployment-group コマンドで設定できます。

# 自動デプロイを有効にする例
$ aws deploy update-deployment-group --application-name "MyApp" \
--current-deployment-group-name "MyDG" \
--region us-east-1 \
--outdated-instances-strategy UPDATE

# 自動デプロイを無効にする例
$ aws deploy update-deployment-group --application-name "MyApp" \
--current-deployment-group-name "MyDG" \
--region us-east-1 \
--outdated-instances-strategy IGNORE

なお、現在のデプロイグループの設定については get-deployment-group で確認できます。

$ aws deploy get-deployment-group \
--application-name "MyApp" \
--deployment-group-name "MyDG"

get-deployment-group コマンドの実行結果のうち、outdatedInstancesStrategy の値によって自動更新するかどうかが決まります。

# 自動更新が有効
"outdatedInstancesStrategy": "UPDATE"

# 自動更新が無効
"outdatedInstancesStrategy": "IGNORE"

ユースケース

私見ですが、本番環境では自動更新を有効にすることで Auto Scaling 内のインスタンスで整合性のある状態を保てると思われます。
つまり、すべてのインスタンスで同じリビジョンのアプリケーションが実行されている状態を保つことができます。

一方で、検証段階で自動更新を無効にすることであえて不整合な状態を作りだすことで AB テストに使用できる可能性もあると思われました。

まとめ

今回は Auto Scaling に対するデプロイが 2 回実行される事象について紹介しました。
どなたかの参考になれば幸いです。

参考資料

Discussion