はじめに
本記事はAWSのCodePipelineを利用している環境で、Blue/Green デプロイ時にエラーが発生した際の勘所について記載しています。
DevOpsの一環として、CodePipelineを用いてECS環境(ECS on EC2)におけるBlue/Green デプロイの導入を行う機会がありました。
CodePipelineの仕様に対する理解不足が多く、デプロイ時にエラーが発生してトライアンドエラーを繰り返したのでナレッジとしてまとめました。
アップデート方式
クラウド上に構築したシステムに対するアップデート方式は、一括でアップデートを行うAll at onceを除くと、以下のようなデプロイ戦略があります。
- Rolling
- Bule/Green
- Canary
目的に応じてソフトウェアの新しいバージョンや変更を本番環境に展開するためのデプロイ戦略を選択することが重要です。アップデート頻度やコストに対してリターンが見込めない場合は、最適でない場合もあると思います。
ECSのデフォルトは、Rollingによるアップデートです。
Rollingによるアップデートは、追加リソースが不要なため、コストがからないことがメリットです。デメリットは、切り戻しが困難なことです。
Blue/Green
Blue/Greenデプロイメントは、システムの可用性を最大化し、ダウンタイムを最小限に抑えることができます。
以下に、Blue/Greenデプロイメントのメリット及びデメリットについて記載します。
-
メリット
- 高可用性と信頼性向上:Blue/Greenデプロイメントは、新しいバージョンのアプリケーションを現在の環境(Blue)とは別の環境(Green)に展開し、任意のタイミングでトラフィックを切り替えることができます。
- 切り戻しが容易:新しいバージョンに問題が発生した場合、本番環境を別の環境(Green)から現在の環境(Blue)に切り替えることで、簡単にロールバックできます。
- テストプロセスの強化: Blue/Greenデプロイメントはテストプロセスを強化します。新しいバージョンは現在の環境(Blue)とは別の環境(Green)でテスト可能なため、現在の環境となる本番環境に影響を与えずにテストが可能です。
- デメリット
基本的にRolling、Bule/Green、Canaryはサービス停止なしでアップデートが可能です。
Blue/Green方式と、Canaryの違いについては、Blue/Green方式が一括で切り替わるのに対して、Canary方式は徐々に環境が切り替わるのが特徴です。
Blue/Green デプロイ時にエラーが発生した際の勘所
Blue/Green デプロイ時にエラーが発生した際の勘所について以下に記載します。
コンソールの注意事項
AWSではサービスによってコンソールの新旧画面が存在する場合があります。
コンソールの新旧を切り替える場合は、EC2を例にすると画面左上の「New EC2 Experience」を操作することで、切り替えができます。
コンソールの新旧を切り替えた場合は、表示内容が大きく変わるため、設定項目が変化することから注意が必要です。
デプロイメントタイプでBlue/Green デプロイメントが選択できない場合
ECSでBlue/Green デプロイに対応するための設定を行う場合、コンソール画面の新旧によって表示内容が異なります。
例えば、新しいコンソール画面からECSを開いて新規にサービスを作成する場合、デプロイオプションのデプロイタイプを確認すると、ローリングアップデートがグレー表示になっていて操作することができません。
最初は起動タイプがEC2環境の場合、対応していないのかと勘違いしましたが、そんなことはありませんでした。
AWSのサポートにも確認しましたが、新しいコンソールの仕様とのことで、旧コンソール画面に切り替えることで選択できると回答いただきました。(将来的には改善されるのではないかと思います)
taskdef.jsonの作成
タスク定義ファイルとしてtaskdef.json
ファイルを作成する場合、新コンソール画面から作成します。
旧コンソール画面の場合はJSONの形式が異なっているため、optionの項目がnull
になることから注意が必要です。
サービスを更新したがデプロイできない場合
検証を行っている中、サービスを更新したがデプロイが開始されない事象が発生しました。
確認したところ、公式ドキュメントのコンソールを使用したサービスの更新を参考にサービスの設定から新しいデプロイの強制をチェックしたら動きました。
更新されたコンテナイメージをタスクに使用する場合は、そのイメージを使用して新しいタスク定義リビジョンを作成し、コンソールで [新しいデプロイの強制] オプションを使用して、サービスにデプロイできます。
CodePipelineのアクセスエラー
CodePipelineのDeployステージで、AWSCodePipelineServiceRole
に対するアクセスエラーが発生しました。
AWSCodePipelineServiceRole
はデフォルトで作成されるロールですが、Blue/Green デプロイを行うには権限が不足しています。
必要な権限については、公式ドキュメントのAWS CodePipeline のためのアイデンティティおよびアクセス管理からCodePipeline サービスロールにアクセス許可を追加するの7をご確認ください。
{
"Effect": "Allow",
"Action": [
"codedeploy:CreateDeployment",
"codedeploy:GetDeployment",
"codedeploy:GetApplication",
"codedeploy:GetApplicationRevision",
"codedeploy:RegisterApplicationRevision",
"codedeploy:GetDeploymentConfig",
"ecs:RegisterTaskDefinition",
"ecs:TagResource"
],
"Resource": "resource_ARN"
},
BuildArtifactの例外発生
CodePipelineのDeployステージで、BuildArtifactの例外が発生しました。
CodePipelineはbuildspec上でアーティファクトを出力する必要があるため、buildspec.yml
ファイルに以下に示すような設定の記述が存在するか確認しましょう。
files:
- appspec.yml
- taskdef.json
AppSpecファイルの拡張子
ymlファイルの拡張子は.yaml
とyml
があります。
CodePipelineの設定と、buildspec.yml
ファイル及びappspec.yml
間で整合が取れてない場合は、ファイルが認識できないため、Exception while trying to read the AppSec artifact file from: BuildArtifact.
のようなエラーが出力されます。
files:
- appspec.yml
- taskdef.json
1タスクで複数コンテナが稼働する場合
公式ドキュメントのイメージ定義ファイルのリファレンスを参考にしながら複数のコンテナイメージのペアをリストするようにファイルを構築することもできます。
1タスクで複数コンテナが稼働する場合はtaskdef.json
で指定するimage
に対する考慮が必要です。
以下はtaskdef.json
で指定するimage
に不備があったため、出力されたエラーメッセージです。
Container.image contains invalid characters.
端的に言うと、buildspec.yml
ファイルのビルドプロセスでtaskdef.json
を出力するようにすることで、1タスクで複数コンテナの設定が可能です。
CodePipelineのビルド時に実行するコマンドで注意すべきこと
上記に関連して、例えばbuildspec.yml
ファイルのビルドプロセスでsed
コマンドを使用する場合、ECRのリポジトリは/
が含まれるため、sed
コマンドを使用する場合はデリミタに対する注意が必要です。
対応として、sed
コマンドで使用するデリミタを/
から@
に変更することで解消できます。
Tags can not be empty.
デプロイ時にTags can not be empty.
のようなエラーメッセージが出力された場合は、taskdef.json
ファイルの以下行を削除します。
"tags": []
参考:AWS pipeline, code deploy 'Tags cannot be empty'."
タイムアウト
「トラフィックを再ルーティングするタイミングを指定する」を有効にしている場合、CodeDeployは時間が過ぎても自動的にルーティングを実行してくれません。
後で確認すると、以下のようなエラーメッセージが出力されます。
The deployment timed out while waiting for a notification to continue. This time out period is 1440 minutes.
エラーを発生させないためには、指定した時間までにトラフィックの再ルーティングを実行するとが必要です。
おわりに
デプロイを開始してビルドは成功したものの、デプロイでエラーが発生し、原因を究明してトライアンドエラーを繰り返す。
本記事を書くにあたり、他にもまだエラーが出ていたたと思います。
同じような事象が発生した方のご参考になれば幸いです。
参考
- チュートリアル:Amazon ECR ソースと ECS to-デプロイを使用してパイプラインを作成する CodeDeploy
- ブルーグリーン・デプロイメントとは
- カナリアリリースとブルーグリーン・デプロイメント: ダウンタイム短縮に最適なデプロイ戦略は?
- Blue-Green デプロイメント、ローリング・デプロイメント、およびカナリア・デプロイメントのモデル化