概要
CodeDeployを使用せずECS自体の機能としてBlueGreenデプロイできるようになったため試してみた。
今まではCodeDeployを使っていたが、CodeDeployを使うとECSサービスのDeploymentControllerがCODE_DEPLOYとなって、ECSサービス更新時に Unable to update task definition on services with a CODE_DEPLOY deployment controller. Use AWS CodeDeploy to trigger a new deployment.
エラーになってしまうなど扱いにくい点があった。ECS自身でのデプロイになることでTerraformでの管理を取り扱いやすくなることを期待する。
構築
terraformではaws provider 6.4.0から利用できる。VPC、ALB、ECSだけつくるコードを作成した。
https://github.com/octop162/basic_vpc_and_ecs
- 特徴
- ALBを2つ用意し1つのECSに紐づけている
- defauct_actionのルールをARNで取り出す方法がわからなかったので、default_actionは403エラーを個体で返し、別途ECSに紐づけるルールを作成した
気になったところ
ターゲットグループ
CodeDeployではテストリスナー、メインリスナーに1つずつターゲットグループを設定していたが、この方法ではうまくいかなかったため、リスナーそれぞれに両方のターゲットグループを指定した。この方法であっている?
切り替え中は本番環境のターゲットグループの重みが100%となり、テストリスナーからはもう片方のターゲットグループの重みが100%となる。切り替えが完了すると画像のように片方のターゲットグループが両リスナーで100%となる。
Lambdaのフック
CodeDeployでは再ルーティングまでの時間を自由に決められボタンポチで即座に切り替えもできたが、ECSでは即座に切り替えが始まった。
これについてはHookを使うことで一応対応はできそうだった。切り替え寸前にLambdaを設定する。
HOOKは以下で設定できる。
- スケールアップ前
- スケールアップ後
- テストトラフィック移行
- テストトラフィック移行後
- 本番トラフィック移行
- 本番トラフィック移行後
LambdaはhookStatusを返す。
- SUCCEEDEDを返すと次に進む
- FAILEDを返すとロールバック
- IN_PROGRESSを返すと30秒後に再度Lambda実行
なので、切り替えフラグを外部で用意しておいて手動で切り替えフラグを立てるまではIN_PROGRESSを返すといった方法で任意の時間で切り替えができそう。
以下はAM2時5分を超えているかを元にSUCCEEDEDを返却するLambda関数の例で、2時5分を超えると切り替えが実施される(TZ=Asia/Tokyo)。
from datetime import datetime
def lambda_handler(event, context):
current_time = datetime.now()
current_hour = current_time.hour
current_minute = current_time.minute
current_total_minutes = current_hour * 60 + current_minute
HOUR = 2
MINUTE = 5
target_minutes = HOUR * 60 + MINUTE
is_after = current_total_minutes >= target_minutes
if is_after:
print("SUCCEEDED")
return {
"hookStatus": "SUCCEEDED"
}
else:
print("IN_PROGRESS")
return {
"hookStatus": "IN_PROGRESS"
}
複数ALBに対応できる
ECS管理になり最大5台までのロードバランサを設定できた。ロードバランサそれぞれをBlue/Greenデプロイしてくれるので、別経路からECSにアクセスする用途でも利用できそう。
terraformではALBを2台用意して紐づけるようにしたが問題なく切り替えできた。
ECSサービス変更もterraformで管理できる
デプロイをCodeDeployに委任するとECSサービスの設定変更はterraformでできなくなってしまうが、この方法だとできる。
例えばpublic_ipを割り当てたいとなったときに、terraform側で設定変更するとECSとしてデプロイを開始し新しいタスクにはpublic_ipを割り当てることができた。台数なども固定であれば変更できるようになった。
参考