CodeDeploy を使ってみた

はじめに

AWS でのデプロイ方法について気になっていたので CodeDeploy のチュートリアルを試してみました。

チュートリアル: WordPress を Amazon EC2 インスタンス (Amazon Linux または Red Hat Enterprise Linux および Linux, macOS, or Unix) にデプロイする - AWS CodeDeploy

上のページのチュートリアルの内容を主にやってみました。

AWS Black Belt Online Seminar 2017 Deployment on AWS

AWS でのデプロイについては上のスライドが参考になりました。

サービスの選択肢もデプロイ方法の選択肢も色々とあってなかなか選ぶのが難しそうですが、 CodeDeploy は EC2 で動かす色々なアプリケーションのデプロイに使えそうなので試して見るには良さそうに見えました。

CodeDeploy でのデプロイの流れ

  • CodeDeploy 設定

    デプロイ対象のアプリケーションとデプロイを行う EC2 インスタンスや AutoScaling グループを設定します。

  • デプロイデータのアップロード

    EC2 インスタンスにデプロイするソースやバイナリ、設定ファイルなどを zip にまとめて S3 にアップロードします。

  • 新しいリビジョンのアプリケーションをデプロイ

    アプリケーション、デプロイメントグループと S3 の URL を指定してデプロイします。 EC2 インスタンス上で動作している CodeDeploy エージェントがデプロイデータの配置や Hookスクリプトの実行を行います。

CodeDeploy を使うための準備

まずデプロイ対象の EC2 インスタンスには CodeDeploy エージェントをインストールして起動させておく必要があります。 CodeDeploy エージェントのインストールは起動設定のスクリプトで行ったり、AMI に含めたりするのだと思います。

それと EC2 インスタンスは S3 からデプロイデータを取得するので S3 にアクセスする権限が必要になります。 S3 への権限を含むインスタンスプロファイルを EC2 に設定しておきます。 S3 にはデプロイデータを置くバケットを作成しておきます。

Amazon Linux または RHEL の AWS CodeDeploy エージェントをインストールまたは再インストールします。 - AWS CodeDeploy

ステップ 4: Amazon EC2 インスタンス用の IAM インスタンスプロファイルを作成する - AWS CodeDeploy

CodeDeploy アプリケーション設定時に使うサービスロールも作成しておく必要があるようです。 これは CodeDeploy が EC2 インスタンスや AutoScaling グループを作成したり ELB を設定するために使われるようです。

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/getting-started-create-service-role.html

CodeDeploy エージェント

GitHub - aws/aws-codedeploy-agent: Host Agent for AWS CodeDeploy

CodeDeploy エージェントのソースは公開されているようです。Ruby で書かれているようです。

AppSpec と Hook スクリプト

AWS CodeDeploy のリビジョンにアプリケーション仕様ファイルを追加 - AWS CodeDeploy

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file-structure.html

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/tutorials-wordpress-configure-content.html

デプロイするデータには appspec.yml というアプリケーション仕様ファイルを含める必要があります。 このファイルではデータの配置先のディレクトリやパーミッション、Hook の設定を行います。

AppSpec の「hooks」セクション - AWS CodeDeploy

Hook スクリプトではアプリケーション起動時、停止時、インストール前、インストール後などの タイミングで実行されるスクリプトが設定できます。

ELB と連携したデプロイでは新しい AutoScaling グループへのトラフィックを許可する前、許可した後、 古い AutoScaling グループへのトラフィックをブロックする前、ブロックした後などの Hook もあります。

ELB と連携した Blue/Green デプロイ

CodeDeploy のデプロイ形式には インプレースデプロイと Blue/Green デプロイがあります。 インプレースデプロイはすでに稼働している EC2 インスタンスにデプロイするというやり方で、 Blue/Green デプロイはデプロイ対象の EC2 インスタンスや AutoScaling グループを新規に用意して 古いインスタンスは破棄するようなやり方のようです。

ELB (Elastic Load Balancer) との連携もできるようになっているようです。 これは最初からできたわけではなく後のリリースで追加されたもので、それまでは Hook スクリプトなどで対応していたのだと思います。

AWS CodeDeploy を Elastic Load Balancing に統合する - AWS CodeDeploy

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/applications-create-blue-green.html

あまり詳しくかかれてないので内部の挙動がよくわかりませんが、おそらく次のような流れになるのではないかと思います。

  1. AutoScaling グループのコピーを作成
  2. 新しい AutoScaling グループの EC2 インスタンスにデプロイを行う
  3. 新しい AutoScaling グループを ELB のターゲットグループにアタッチする (両方にトラフィックが流れる)
  4. 古い AutoScaling グループを ELB のターゲットグループから外して削除する

AWS Black Belt Online Seminar 2017 Deployment on AWS

最初に貼ったこのスライドに書かれていますが、ELB も新規で作成して route53 で切り替えを行うような方法もあるようです。

LB が2つある場合は?

前にブログに書きましたが LB を二つ置くような構成もあると思います。 しかし CodeDeploy は連携する ELB は一台しか設定できないようです。 この場合は Hook スクリプトで色々やることになるのかなと思います。

トラフィックが流れるようになった後 (AfterAllowTraffic) に、二つ目の ELB のターゲットグループに新しい AutoScaling グループを追加し、 トラフィックをブロックする前 (BeforeBlockTraffic) に古い AutoScaling グループを二つ目の ELB のターゲットグループから外すような感じ でできそうな気がしますが、 Hook スクリプトは EC2 インスタンスごとに呼び出されるのでこれではうまくいかないかもしれません。

https://github.com/aws-samples/aws-codedeploy-samples/tree/master/load-balancing/elb-v2

ここに参考になりそうなサンプルがありました。 このサンプルのようにターゲットグループへの追加は AutoScaling グループではなくインスタンスごとに行う方がいいかもしれません。

まとめ

CodeDeploy のチュートリアルをやってみてデプロイの方法を学びました。 デプロイ方法を決めるためにはシステム全体の構成、バージョン更新後の互換性、デプロイ失敗時の挙動など色々と考えることがたくさんあってなかなか難しそうですが、 ある程度自由に自動化されたデプロイができたほうが開発しやすいと思うので色々なデプロイ方法を身に付けたいです。