CodeDeploy の Blue/Green デプロイを利用して、CodePipeline でいい感じに自動化されたデリバリを実装する

2017.02.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、藤本です。

ちょっと前から、AWS の Code◯◯ をベースにデリバリの自動化を勉強しています。

今回は今までブログエントリしてきたデリバリ方法に、先日リリースされた CodeDeploy の Blue/Green デプロイを組み合わせた実装を試すとともに、リリースプロセスを今一度整理してみました。

今までのエントリは下記をご参照ください。

CodeDeploy の Blue/Green デプロイは下記をご参照ください。

復習

現在、AWS の Developer Tools のカテゴリに、ソースコードリポジトリの CodeCommit、ビルドサービスの CodeBuild、デプロイ自動化サービスの CodeDeploy、デリバリの一連のプロセスを繋げて自動化する CodePipeline があります。ちなみに CodeCommit の代わりに Github を利用することもできます(Github を利用している方は CodeCommit に移行する必要はありません)

リリースプロセス

これらを組み合わせることでソースコードリポジトリへのプッシュをトリガーに、ビルド、ユニットテスト、デプロイまでを自動化し、リリースプロセスのトラッキングを行うことができます。

AWSでのデプロイ(2)

ただこれはあくまで単純なデリバリであり、多くのシステムにおいて、リリースプロセスはこれだけではありません。Webシステムであれば UI チェック、システムの 1コンポーネントであれば他コンポーネントとのインテグレーションテスト、大規模な修正であれば、ペネトレーションテスト、パフォーマンステストが必要となるかと思います。

リリースプロセス(現実案)

そこで CodePipeline の承認プロセスを設けることで、一つのリリースパイプラインでありながら、ステージング環境での各種テストを実行することができるようになりました。

AWSでのデプロイ(承認プロセス)

ただこれだけでも満足がいくものではありません。リリースにおいて、バグ内在は付きものです。バグが発覚したら、より早く切り戻す必要があります。より早く切り戻すにはインプレイスデプロイよりも Blue/Green デプロイです。先日以前は CodeDeploy はインプレイスデプロイしか対応していなかったため、CodePipeline + CodeDeploy を利用する時は、Blue/Green デプロイすることができませんでした。(どうにか Blue/Green デプロイしたくて CodePipeline の間に Lambda 挟んで Route 53 書き換え、CodePipeline の変更など頑張りましたが、うまく行かなかった。。。)

今回お伝えすること

それが先日の CodeDeploy の Blue/Green デプロイ対応で CodePipeline + CodeDeploy でも簡単に Blue/Green デプロイを実現できるようにしました!!(EB で言う URL swap、Route 53 書き換えの対応が待たれる!)そして、いい感じにデリバリを自動化できるようになりました。

AWSでのデプロイ(BlueGreen)(2)

自動化されたデリバリフローの整理

  1. リリースするソースコードをソースコードリポジトリへプッシュ(特定のブランチに限定可)
  2. (自動)ソースコードが S3 に zip 化されて配置
  3. (自動)CodeBuild がユニットテスト、ビルドしたパッケージを再度 zip 化して、S3 に配置
  4. (自動)パッケージをステージングインスタンスにデプロイ
  5. ステージング環境にデプロイされたアプリケーションを自動化できないテストを手動で実施
  6. リリース判定により、
    6-a. リリースできると判断した場合、承認(リリースプロセスの継続、7.へ)
    6-b. バグが見つかったなどリリースできないと判断した場合、中止
  7. (自動)Green 環境のデプロイ
  8. (自動)ELB へ Green 環境追加・Blue 環境削除 による切り替え
  9. (自動)任意のタイミングで Blue 環境の削除

実質、ほとんどのリリースプロセスが自動化されていて、切り戻しも簡単にできます!

やってみた

前回の実装から CodeDeploy の Blue/Green デプロイ化を(こっそり AutoScaling 化も)実施しています。

CodeDeploy の設定変更

CodeDeploy のインプレイスデプロイから Blue/Green デプロイへの設定変更は設定画面から簡単に切り替えられます。CodeDeploy のアプリケーション設定画面から変更したいデプロイメントグループを選択し、[Actions] -> [Edit] を選択します。今回は prd(本番環境)を変更します。

screenshot_2017-02-13_9_42_36

Deployment type を In-place Deployment から Blue/green Deployment に変更します。

AWS_CodeDeploy_Management

設定変更はこれだけです。

動作確認

Django で作った Web API アプリケーションをデプロイしています。ソースコード変更して、リリースプロセスの動作を確認します。

事前確認

「今回お伝えすること」の章で貼ったものと同じ構成です。ステージング、プロダクション分かれていて、それぞれ ELB をエンドポイントとしています。ヘルスチェック URL を叩くと JSON が返ってきます。

$ curl stg-clb-769141208.us-east-1.elb.amazonaws.com/app/health
{"status": "ok", "instance_id": "i-09dc2fe1d5ae9608d", "version": "blue"}

$ curl prd-clb-866491571.us-east-1.elb.amazonaws.com/app/health
{"status": "ok", "instance_id": "i-081048996730c9a9e", "version": "blue"}
1. リリースするソースコードをソースコードリポジトリへプッシュ(特定のブランチに限定可)

今回はソースコードの変更として、version を blue から green に変更します。

$ sed -ie 's/blue/green/' project/app/views.py

$ git diff
diff --git a/project/app/views.py b/project/app/views.py
index 446f32b..68caa61 100644
--- a/project/app/views.py
+++ b/project/app/views.py
@@ -14,6 +14,6 @@ def health(request):
         instance_id = 'not found'
     return HttpResponse(json.dumps({
         'status': 'ok',
-        'version': 'blue',
+        'version': 'green',
         'instance_id': instance_id,
         }), content_type="application/json")

$ git commit -am "green deploy"
[master 0af4bf4] green deploy
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git push origin master
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 799 bytes | 0 bytes/s, done.
Total 9 (delta 7), reused 0 (delta 0)
To https://git-codecommit.us-east-1.amazonaws.com/v1/repos/django-fujimoto
   aabcc59..527ecb1  master -> master
2. ソースコードが S3 に zip 化されて配置

ソースコードリポジトリ(今回は CodeCommit)への master ブランチのプッシュをトリガーに CodePipeline のデリバリプロセスが開始します。まずはソースコードをクローンして、S3 にアップロードします。

AWS_CodePipeline_Management_Console

3. CodeBuild がユニットテスト、ビルドしたパッケージを再度 zip 化して、S3 に配置

続いて、CodeBuild を起動し、ビルドプロセスが開始します。今回は Django アプリケーションで特にビルドはしていないので、ユニットテストのみが実行されます。

AWS_CodePipeline_Management_Console_2

ユニットテストに NG がある場合、ビルドプロセスが NG となり、デリバリプロセスは中断されます。詳しくはこちらをご参照ください。

4. パッケージをステージングインスタンスにデプロイ

ビルドが完了するとステージング環境へのデプロイが開始されます。

AWS_CodePipeline_Management_Console_3

ステージング環境へのデプロイが完了すると、承認待ちとなり、デリバリプロセスは停止します。

AWS_CodePipeline_Management_Console_5

5. ステージング環境にデプロイされたアプリケーションを自動化できないテストを手動で実施

それではこの状態でステージング、本番それぞれにアクセスして、デプロイ状況を確認してみます。

$ curl stg-clb-769141208.us-east-1.elb.amazonaws.com/app/health
{"status": "ok", "instance_id": "i-09dc2fe1d5ae9608d", "version": "green"}

$ curl prd-clb-866491571.us-east-1.elb.amazonaws.com/app/health
{"status": "ok", "instance_id": "i-081048996730c9a9e", "version": "blue"}

ステージング環境の version が green を返すようになりました。正常にデプロイが実行されています。当たり前ですが、本番環境は blue のままです。

6. リリース承認

ステージング環境の動作確認に問題がないようであれば、本番環境へデプロイします。CodePipeline の画面から承認します。「Review」ボタンをクリックします。コメントを入力し、「Approval」ボタンをクリックします。

AWS_CodePipeline_Management_Console 6

7. Green 環境のデプロイ

承認すると、本番環境へのデプロイが開始されます。

AWS_CodePipeline_Management_Console 7

8. ELB へ Green 環境追加・Blue 環境削除 による切り替え

「Details」リンクをクリックすると CodeDeploy の画面に遷移し、デプロイ状況を眺めることができます。

AWS_CodeDeploy_Management 4

デプロイが完了するのを待ちます。

AWS_CodeDeploy_Management 5

デプロイが完了しました。1時間は Blue 環境を保持する設定にしていますので、この時点では CodePipeline は完了にはなりません。

AWS_CodePipeline_Management_Console 8

本番環境の動作確認

それでは本番環境にアクセスして、デプロイ状況を確認してみます。

$ curl prd-clb-866491571.us-east-1.elb.amazonaws.com/app/health
{"status": "ok", "instance_id": "i-08baaba854fa5917a", "version": "green"}

本番環境も version が green を返すようになりました。更にインスタンス ID も変わっていて、別インスタンス(Green面)がデプロイされていることがわかります。

9. 任意のタイミングで Blue 環境の削除

1時間経過後に確認してみます。

AWS_CodePipeline_Management_Console 9

CodePipeline のリリースが完了しています。

まとめ

いかがでしたでしょうか?

待望の CodeDeploy の Blue/Green デプロイ対応によって、ようやく安心して CodePipeline を活用できるようになったのではないでしょうか。CodePipeline は昨年12月に東京リージョンで利用可能になりました。ぜひ、利用してみてはいかがでしょうか。