はじめに
Amazon ECS は、コンテナを動かしうまく管理するためのコンテナオーケストレーションサービスです。新たなバージョンのコンテナをデプロイするときに、いろいろなデプロイの方法が取れますが、ECS 側で用意されているデプロイ戦略が3種類あります
- Rolling Update : Service の中で稼働しているタスクを少しずつ順繰りアップデートする方式
- Blue/Green Deployment : 新たな環境である Green 環境を用意して、LB レイヤーで切り替える方式
- External Deployment : 外部のサードパーティの何かでデプロイをコントロールする方式
こちらの Document に記載があります。 : https://docs.aws.amazon.com/AmazonECS/latest/userguide/deployment-types.html
Blue/Green Deployment の中でも、更に詳細な方式があります。CodeDeploy 側で用意されている5つのデプロイ方式の中で自分たちに合うものをチョイスできます。
デプロイ設定 | 説明 |
---|---|
CodeDeployDefault.ECSLinear10PercentEvery1Minutes |
すべてのトラフィックを移行するまで、1 分ごとにトラフィックの 10% を移行します。 |
CodeDeployDefault.ECSLinear10PercentEvery3Minutes |
すべてのトラフィックを移行するまで、3 分ごとにトラフィックの 10% を移行します。 |
CodeDeployDefault.ECSCanary10percent5Minutes |
最初の増分でトラフィックの 10% を移行します。残りの 90% は 5 分後にデプロイします。 |
CodeDeployDefault.ECSCanary10percent15Minutes |
最初の増分でトラフィックの 10% を移行します。残りの 90 パーセントは 15 分後にデプロイされます。 |
CodeDeployDefault.ECSAllAtOnce |
すべてのトラフィックを同時に更新済み Amazon ECS コンテナに移行します。 |
今回は、この Blue/Green の中で CodeDeployDefault.ECSAllAtOnce
と CodeDeployDefault.ECSLinear10PercentEvery1Minutes
の動きを紹介していきます。
CodeDeployDefault.ECSAllAtOnce の動作について
まず、デプロイを行っていない、通常の状態の構成を見ていきます。細かい部分は正確ではない部分もありますので、詳細はぜひ触ってみてください。ALB と書いている Box は 正確には NLB も利用できますし、リスナーのポートは HTTPS も利用可能なので、細かい部分で違いがあるところもあります。
- ALB のリスナーについて
- 1個の ALB に、2つのリスナーがあります。
- 本番 Blue環境用のトラフィックが流れる Production リスナーと、バージョンアップ後の Green 環境用の Test リスナーです。
- Target Group について
- Blue と Green の環境をコントロールするために、Target Group が2つ用意されています
- 通常の構成では、Target Group 1 しか使いません
- Target Group 1 が、ECS で稼働している Task(コンテナ)に紐づいています
ここで、新たなバージョンをデプロイを開始し始めると、以下の構成になります。ECS 環境上に、新たなバージョンの Task が立ち上がり、Target Group 2 に紐づけられます。紐づけられただけだと、まだ本番環境でのトラフィックは流れないため、エンドユーザーは引き続き version 1 の Blue 環境を触っています。
次に、Green 環境が立ち上がったので、ALB の Test 用のリスナーが Green 環境に紐づけられます。
デフォルトの状態だとコンテナの中のアプリケーションが正常に稼働しているかは CodeDeploy は気にしていません。アプリケーションが異常状態であっても次のプロセスに進みます。ALB の Health Check の機能自体はありますが、ALB 側の Health Check は CodeDeploy は気にしていないように見えています。正しく稼働しているか自動的に確認するために、CodeDeploy のライフサイクルフックで AfterAllowTestTraffic
のフェーズで Lambda を動かす機能が使えますが、今回は取り上げません。気になる場合はこのあたりを確認してみましょう。
次に、本番用の Production 用のリスナーが Green 環境に紐づきます。このタイミングで、初めて本場利用のユーザーが新しいバージョンを利用し始めます。CodeDeployDefault.ECSAllAtOnce
の方式の場合は、全員のユーザーがこのタイミングで Green 環境に切り替わります。徐々に切り替えていきたい場合は、これ以外の方式を選択すると良いでしょう。
Blue 環境を削除するまで、CodeDeploy の画面上でロールバックボタンを押せます。1ボタン押すだけで Blue 環境に切り戻しもできるので、便利に利用できそうです。
その後、Blue 環境が不要になった Blue 環境を削除します。Blue 環境の削除は主に以下の2つのトリガーがあります
- 手動で削除
- 保存期間を超えたら削除。デフォルトは1時間まで平行稼働してくれる
CodeDeployDefault.ECSLinear10PercentEvery1Minutes の動作について
CodeDeployDefault.ECSAllAtOnce の動作について
との差分のみ記載します。
ALB の Production リスナーを、Green 環境に切り替える部分についてです。
ALB の重みづけの機能を活用して、本番環境にアクセスしにきたユーザーを徐々に Green 環境に寄せていきます。これにより、影響のでるユーザーを出来るだけ少ない状態にしておき、何か問題があればすぐに切り戻しを行うことが出来ます。CodeDeployDefault.ECSLinear10PercentEvery1Minutes
の名前にもある通り、1分おきに、10% ずつ Green 環境へのアクセスが増えていく形ですね。
初めは、Blue 環境へのアクセスが 100% で、Green 環境へのアクセスが 0% となっています。1分ごとにこの重みづけが 10% ずつ偏りが変わっていく形ですね。最終的には、Green 環境に完全に切り替わります。
- 100% : 0%
- 90% : 10%
- 80% : 20%
- 70% : 30%
more....
Blue/Green Deployment : 環境作成
ここまで概念的な話でした。これからは、実際に環境を作成してみる手順を紹介していきます。手順に興味がない場合は、この部分は無視してもらって大丈夫です。
ALB 作成
まず、ECS Service を作成する前に、紐づける ALB を作成しておく必要があります。
Create Load Balancer を押します。
ALB を選択します。
名前を指定
Listener は適当に指定しないといけないので、Dummy のものを指定
Create
ALB が作成できました。Dummy で作成した Listener は削除しておきます。
ECS Service 作成
次に、ECS Service を作成していきます。Blue/Green Deployment の方式は、2022年3月現在、旧コンソールでないと設定できませんでした。
Service Create
- Task Definition
- Service name
Deployment Type を指定可能
- Blue/green deployment を選択
VPC や Subnet を指定
連携する ALB を指定
Load Balancer に対して、2つのリスナーを用意する
- Blue 環境用の Production listener
- Green 環境用の Test listener
2 つの Target Group の指定。デフォルトのままにしておく。
Service の作成
Service が作成されました
自動設定 : ALB
ALB には 2 つの Listener が自動設定されています
ALB にアクセスすることも出来ます
自動設定 : Target Group
Target Group1 には、2つの Task が紐づいています
Target Group 2 には、なにも Task は居ません
自動設定 : CodeDeploy
CodeDeploy の Application の定義が1個作成されています
Application の中に、Deployment Group が作成されています
詳細な中身を確認するために、Edit を押します
2つの設定値を確認できます。
- Traffic rerouting : Blue 環境から Green 環境にトラフィックを切り替えるときの猶予時間についての設定。デフォルトの設定は、Reroute traffic immediately なので、すぐに切り替える設定になっている。
- Original revision termination : Blue 環境から Green 環境に切り替えたあとに、Blue 環境をどれくらいの時間残しておくかの指定。この指定した時間は手動でロールバックボタンを押すことが出来る。
なお、自動ロールバックについても設定があり、デプロイメントに失敗したときは自動的にロールバックされる
動作確認 : Blue/Green を試す
対象の Service を選択して、Update を押す
Task Definition を Revision 9 から 10 に変更します
CodeDeploy に対する動作を指定できます。このままデフォルトでいきます。Deployment configuration でデプロイ方式を選択できるので、そのときの状況に合わせて最適なものを選びましょう。
Next Step
Next Step
Update Service
Service のアップデートを開始したので、Blue/Green Deployment が始まりました。
ECS Task が 2 個から 4 個に増えている
CodeDeploy では、Deployment が進んでいることがわかる
Green 用の Target Group に新たな Task が登録される
CodeDeploy 上では、Reroute が切り替わっている。切り替わってから1時間は Blue 環境を残す設定にしているので、Blue 環境が残っている。Terminate original task set を手動で押すことで、Blue 環境の手動削除が可能。
ALB の HTTP 80 Listener の宛先 Target Group が切り替わっている
CodeDeploy 上では、何にどれくらいの時間が掛かっていたかを確認可能
わかったこと
-
CodeDeploy の Appllication 配下にある Deployment Group の設定
Original revision termination
は、Blue から Green に切り替え終わった後に、Blue の環境をどれだけ保持しておくかの設定となっている。 -
Blue の環境を保持している期間は、新たなデプロイが出来ない。新たにデプロイしたい場合は、手動で Terminate ボタンを押す必要がある
-
重みづけをした場合は、Target Group の重みづけが入る
-
Blue/Green Deployment の場合、ALB の Health Check にある Interval や、Healthy threshold など設定値は、影響しない。Interval をいくら伸ばしても、Healthy threshold の回数を増やしても、Deployment の時間には影響しなかった。CodeDeploy は、ALB の Health Check は無視しているのだと思われる。
-
CodeDeploy による Blue/Green デプロイは、Green 環境が正常に稼働しているかは気にしないで切り替えを行う。これを検証して、異常な場合は自動ロールバックするために、CodeDeploy のライフサイクルフックを利用可能
-
AfterAllowTestTraffic
のタイミングを利用することで、Lambda 上で Green 環境の正常性を確認できる - https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/deployment-steps-ecs.html#deployment-steps-what-happens
- https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html
-
参考URL