AWS CodeDeployでAuto Scaling Lifecycleを手軽に利用する #cmdevio

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

ども、大瀧です。
先日CM re:Growth Developers.IO Meetup 11 Tokyoで担当した同タイトルのセッションで紹介した内容を、サンプルコードと手順としてまとめてみました。セッションのスライドはエントリー末尾をご覧ください。

AWSの新デプロイツールCodeDeployは、アプリケーションをEC2インスタンス上に効率的にデプロイするサービスです。CodeDeployでは、デプロイ対象のEC2インスタンスを以下2つの方法で指定します。

  • 特定のタグが設定されているインスタンス単位
  • Auto Scaling配下のインスタンスであれば、Auto Scalingグループ単位

Auto Scalingの場合はDeploymentを手動で実行するほかに、Auto Scalingが新規インスタンスを自動起動する際にDeploymentを自動実行するようになっています。実は、この自動実行はAuto ScalingのLifecycle Hookという機能と連携するようになっており、ちょっと敷居の高いLifecycle Hookを手軽に活用する一例として見ることもできます。今回は、Deploymentの自動実行とLifecycle Hookの様子をご紹介してみます。

検証環境

  • EC2インスタンス : Amazon Linux 2014.09 HVM
  • リージョン : Oregon(us-west-2)

1. IAMロールの作成

CodeDeployではIAMロールを前提とした設計になっていて、以下2つのIAMロールを準備しておく必要があります。

  1. CodeDeployサービスのロール
  2. EC2インスタンスのロール

CodeDeployサービスのロールは、サービス許可設定のTrust Relationshipの部分が複雑なので、インスタンスのロールとセットでCloudFormationで作成するテンプレートを用意しました。手動で作成する場合は、こちらのブログエントリーを参考にしてください。

CloudFormationスタックを作成

CloudFormationスタックの作成画面が表示されたら、ウィザードを進めていきます。オレゴンリージョン(us-west-2)が指定されますが、バージニアリージョン(us-east-1)で試したい場合は画面右上のリージョン一覧から切り替えてください。

codedeploy-cw11

[Next]を2回クリックして進め、[Capabilities]の「I acknowledge that this template might cause AWS CloudFormation to create IAM resources.」のチェックをオンにし、[Create]で作成がスタートします。

codedeploy-cw12

スタックの[Status]列が「CREATE_COMPLETE」になったら完了です。[Output]タブを確認します。

codedeploy-cw13

CodeDeployTrustRoleARNがCodeDeployサービスのロールのARN(このあとCodeDeployの設定で必要)、InstanceProfileがインスタンスに紐付けるロールです。

2. Auto Scalingの構成

デプロイ対象とするAuto Scalingの設定を行います。新規Launch Configurationで以下2点を設定し作成します。

  • IAM Role : 手順1で作成したInstanceProfileを選択
  • User Data : CodeDeployエージェントをインストールする以下をコピペ(バージニアリージョンの場合はaws s3 cpコマンドの引数を適宜調整してください)
#!/bin/bash
yum -y update
yum install -y aws-cli
cd /home/ec2-user
aws s3 cp s3://aws-codedeploy-us-west-2/latest/install . --region us-west-2
chmod +x ./install
./install auto

sds-as11

他の項目は任意の設定で構いません。Auto Scaling Groupも任意の設定で作成します。今回はひとまず「Keep this group at its initial size」(Scaling Policyなし)を選択し、インスタンス1台で構成しました。作成したら、[Scaling History]タブと[Instances]タブを確認しておきましょう。この後、CodeDeployの構成時に再度確認することがあります。

sds-as12

sds-as13

3. CodeDeployの構成

つづいて、CodeDeployを設定していきます。Management ConsoleのCodeDeploy管理画面から[Get Started Now]ボタンをクリックしウィザードを表示、[Custom Deployment]を選択、[Skip Walkthrough]ボタンをクリックします。

sds-as14

[Create Application]画面では、Application名、Deployment Group名を適当に入力します。

sds-as15

[Add Amazon EC2 Instances]では、「Search by Auto Scaling Group Names」をクリックしAuto Scaling Group名を入力するテキストボックスを表示、手順2で作成したAuto Scaling Group名を選択します。

sds-as16

sds-as17

[Deployment Configuration]は任意の設定、[Service Role]は、手順1で作成したCodeDeployTrustARNを選択し、[Create Application]ボタンをクリックしApplicationを作成します。

sds-as18

4. Revisionのアップロード

AWSが提供するサンプルのRevisionをベースにします。

$ tree SampleApp_Linux/
SampleApp_Linux/
├── LICENSE.txt
├── appspec.yml
├── index.html
└── scripts
    ├── install_dependencies
    ├── start_server
    └── stop_server

1 directory, 6 files
$

Auto Scaling Lifecycle Hookの様子を確認しやすいように、BeforeInstallフックのスクリプトにsleepコマンドの実行を追加しました。

version: 0.0
os: linux
files:
  - source: /index.html
    destination: /var/www/html/
hooks:
  BeforeInstall:
    - location: scripts/install_dependencies
      timeout: 300
      runas: root
    - location: scripts/start_server
      timeout: 300
      runas: root
  ApplicationStop:
    - location: scripts/stop_server
      timeout: 300
      runas: root
#!/bin/bash
sleep 60
service httpd start

あとは、Revisionを配置するためのS3バケットを作成しておきます。CodeDeployエージェントからはIAMロールの権限でアクセスするため、S3バケットの設定を変更する必要は特にありません。では、aws deploy pushコマンドでRevisionをS3にアップロードします。

$ deploy push \
> --application-name DemoApplication \
> --ignore-hidden-files \
> --description "add sleep 60" \
> --s3-location s3://takipone-codedeploy-us-west-2/SampleApp_Linux.zip \
> --source .
To deploy with this revision, run:
aws deploy create-deployment --application-name DemoApplication --s3-location bucket=takipone-codedeploy-us-west-2,key=SampleApp_Linux.zip,bundleType=zip,eTag="9d02d9a789605889d562179d0ecc1b61" --deployment-group-name <deployment-group-name> --deployment-config-name <deployment-config-name> --description <description>
$

アップロードできました。

5. 初回デプロイの実行

Deploymentの自動実行のためには、最低1回手動でDeploymentを実行しておく必要があります。今回は、手順2でAuto Scalingのインスタンス1台が起動しているので、これに対してDeploymentを手動で実行してみます。CodeDeployの画面に戻りRevisionsにアップロードしたRevisionが表示されていることを確認、画面左側のDeployment Groupの詳細を開いて[Deploy New Revision]ボタンをクリックします。

sds-as19

[Create New Deployment]画面では、[Revision Location]から先ほどアップロードしたRevisionを選択します。

sds-as20

[Deployment Description]には任意のコメントを入力し、[Deploy Now]をクリックしてデプロイを実行します。

sds-as21

[Deployments]画面に切り替わり、Deploymentの進捗が表示されます。しばらく待つと[Status]が「Succeeded」になり、デプロイが成功したことを確認します。

sds-as22

6. Deployment自動実行の確認

それでは、Auto Scalingのインスタンス数を増やし、インスタンス起動時にDeploymentが自動実行される様子を確認してみます。Auto Scaling Groupの設定画面から[Edit]ボタンをクリックし、[Desired]と[Max]を2以上に増やし、[Save]をクリックします。

sds-as23

[Scaling History]タブに切り替え、少し待つとインスタンスが起動します。CodeDeployはAuto Scaling LifecycleのPending Stateにフックを登録し、Deploymentを実行します。下図のUser Actionが今回のCodeDeployにあたります。

pendingaction

少し待つとインスタンスが起動し、[Status]が「Waiting for Launch Lifecycle Action」になりCodeDeployのDeployment実行を待っていることがわかります(上図のPending:Wait)。

sds-as24

CodeDeployの画面を見ると、Deploymentが起動インスタンスごとに自動で作成、実行されることがわかります。

sds-as25

Deploymentが完了したらCodeDeployからAuto Scalingにフック処理の完了(上図のPending:Proceed)が通知され、[Status]の表示が「Successful」に変わります。

Auto Scaling GroupにELBを登録している場合はこの完了を待ってインスタンスがELBに登録されるため、Deploymentが終わっていないインスタンスにトラフィックが転送されるのを防げるわけですね。賢い賢い。

留意事項

検証して気になった点をいくつか挙げます。

  • "最近の"Revisionをデプロイするために最低1回、先にデプロイを実⾏しなければならない。そのため今後サポートされるであろうCloudFormationとの相性が良くなさそうな印象
  • Terminating Stateには未対応
  • 複数Applicationの場合、パッと見た限りでは実行順を制御できなさそう

まとめ

CodeDeployとAuto Scalingの組み合わせでLifecycle Hookを利用した、自動デプロイの様子をご紹介しました。CodeDeployは機能は地味ですが、細かいところでAWSと密に連携する良くできたデプロイツールだと思います。ともかく、早く東京に来てくれることを祈るのみですね!

発表のスライド