Edited at

GitHubへのpush時にCodeDeployを使ってEC2にアプリケーションをデプロイする

More than 3 years have passed since last update.

EC2へのアプリケーションのデプロイを考えた時に色んな候補があるかと思います。以下にまとまっていました。

AWSでデプロイとスケーリングを自動化する方法まとめ

最初、OpsWorksを検討したのですが、オートスケーリングに対応していないという点でボツとなりました。。。また、Jenkinsなどを使えば可能だと思いますが、その場合にはJenkinsをSPOFにならないように気をつけたり、AWSと連携するためにごにょごにょするのが面倒かなと思いました。

で、まだtokyoリージョンにはきていませんが、CodeDeployはオートスケーリングが対応しており、どうだろうということで色々試してみたたのでメモ。

今回の例ではGitHubへのpush時にCodeDeployを利用してEC2にWordPressのデプロイを行ってみました。


CodeDeployとは


  • アプリケーションのデプロイを行うためのサービス。デプロイするプログラミング言語などに制限はない

  • アプリケーションにデプロイに特化した機能なので環境構築などに使うべきではない(やろうと思えばできるけどやらない方が良いと思う)環境構築もしたい場合、ElasticBeanstalkやOpsWorksを考えたほうが良い


  • appspec.ymlというファイルにデプロイ時の詳細を記述。デプロイ時の独自のライフサイクルタイミングで任意のシェルスクリプトを実行できる

  • 特定のタグが付与されたEC2群もしくはオートスケーリングに紐づくEC2群にデプロイ可能

  • 特定のリビジョンに戻ることが可能

  • 現在はGitHubとS3と連携が可能(なぜCodeCommitがない??)

  • 実行するためにはCodeDeployAgentを対象EC2(にインストールする必要がある

  • 対象OSはAmazon Linux、Red Hat Enterprise Linux、Ubuntu Server、Microsoft Windows Server

  • CodeDeployエンドポイントと接続する必要があるため、プライベートサブネットの場合などにはNATが必要


前提


  • AWS CLIインストール済み

  • GitHubのアカウント取得済み

  • 2015/7/20現在CodeDeployはtokyoリージョンはないのでus-east1で確認


参考


CodeDeployが使うRoleの作成

Create a Service Role for AWS CodeDeploy

CodeDeploy自体が利用するRoleの設定を行います。

まず、以下のファイルを作成します。


CodeDeployDemo-Trust.json

{

"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"codedeploy.us-east-1.amazonaws.com",
"codedeploy.us-west-2.amazonaws.com",
"codedeploy.eu-west-1.amazonaws.com",
"codedeploy.ap-southeast-2.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}

作成後、以下のコマンドを実行し、CodeDeployDemoというCodeDeploy用のロールを作成します。

$aws iam create-role --role-name CodeDeployDemo --assume-role-policy-document file://CodeDeployDemo-Trust.json

上記コマンド実行後、

"Arn": "arn:aws:iam::hogefuga:role/CodeDeployDemo"

というような形でこのロールのArnが表示されるのでメモしておきます。

また、以下のコマンドを実行し、先ほどのロールがCodeDeployで利用できるように設定します。

$aws iam attach-role-policy --role-name CodeDeployDemo --policy-arn arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole


RDSの作成

WordPressで利用するMySQLをRDSで作成します。

リージョンはus-east1で作成してください。また、次に作成するEC2からの3306ポートで接続できるようなSecurityGroupの設定をしてください。

作成時に設定したユーザー名、パスワード及び作成後のRDSの接続エンドポイントはメモしておいてください。


EC2の起動

Step 1: Launch an Amazon Linux or Red Hat Enterprise Linux Amazon EC2 Instance


  • OSはAmazonLinux

  • Auto-assign PublicIPを有効にする

  • SecurityGroupのInboundでSSHとHTTPを0.0.0.0/0で許可し、Outboundは制限しない

  • S3のread権限があるIAMロールを付与すること(CodeDeployAgentのインストールのため)

  • NameタグではCodeDeployDemoと設定すること

  • UserDataに以下の設定を行う。なお、CodeDeployAgent取得先バケット名はregionによって変わるので注意。また、SQL実行の箇所はユーザー名はroot、パスワードはpassword、RDSのエンドポイントはcodedeploy.cukvcqdui8ox.us-east-1.rds.amazonaws.com という場合の設定となるので適宜変更してください。

#!/bin/bash

# install CodeDeploy agent
yum -y update
yum install -y ruby
yum install -y aws-cli
cd /home/ec2-user
aws s3 cp s3://aws-codedeploy-us-east-1/latest/install . --region us-east-1
chmod +x ./install
./install auto

# install httpd
yum install -y httpd
chkconfig httpd on
service httpd start

# install application dependencies
yum install php php-mysql php-gd php-mbstring -y
yum install mysql -y

#exec sql
mysql -u root -ppassword -h codedeploy.cukvcqdui8ox.us-east-1.rds.amazonaws.com <<EOF
CREATE USER'wordpress-user'@'%' IDENTIFIED BY 'wordpress';
CREATE DATABASE \`wordpress\`;
GRANT ALL PRIVILEGES ON \`wordpress\`.*TO"wordpress-user"@"%";
FLUSH PRIVILEGES;
EOF

起動し、StatsuCheckがrunningになったら、ssh接続し、agentがインストールされているか確認します。

$sudo service codedeploy-agent status

The AWS CodeDeploy agent is running as PID 6975

必要に応じてvar/log/cloud-init-output.logでのログ確認やその他ミドルウェアの設定も確認してください。


GitHubにCodeDeploy用のWordPressをpushする

Step 2: Configure your Source Content to Deploy to the Amazon Linux or Red Hat Enterprise Linux Amazon EC2 Instance

以下より、ローカルPCで実施します。

WordPressのソースコードをgit cloneしてきます。

$mkdir -p /tmp/WordPress

$git clone https://github.com/WordPress/WordPress.git /tmp/WordPress

スクリプト配置用のフォルダ作成。

$mkdir -p /tmp/WordPress/scripts

httpdを止めるためのスクリプトを作ります。


/tmp/WordPress/scripts/stop_server.sh

#!/bin/bash

isExistApp=`pgrep httpd`
if [[ -n \$isExistApp ]]; then
service httpd stop
fi

httpdを開始するスクリプトも作ります。


/tmp/WordPress/scripts/start_server.sh

#!/bin/bash

service httpd start

パーミッションを変更するスクリプトを作成します。


/tmp/WordPress/scripts/change_permissions.sh

#!/bin/bash

chown -R apache:apache /var/www/html/WordPress
chmod -R 744 /var/www/html/WordPress

作成したスクリプト群の権限を変更します。

$chmod +x /tmp/WordPress/scripts/*

次にどこにソースコードを配置するのか、またどのライフサイクルタイミングで何をするのかをappsec.ymlに記述します。


/tmp/WordPress/appspec.yml

version: 0.0

os: linux
files:
- source: /
destination: /var/www/html/WordPress
hooks:
AfterInstall:
- location: scripts/change_permissions.sh
timeout: 300
runas: root
ApplicationStart:
- location: scripts/start_server.sh
timeout: 300
runas: root
ApplicationStop:
- location: scripts/stop_server.sh
timeout: 300
runas: root

appsec.ymlの詳細は以下を参照のこと。

AWS CodeDeploy AppSpec File Reference

次にGithubでリポジトリを作成します。

今回の例ではブラウザから事前に toshihirock/CodeDeployWordPressというリポジトリを作成しました。

リポジトリ作成後、GitHubにコードをpushします。

$cd /tmp/WordPress

$git add .
$git commit -m "add codedeploy scripts"
$git remote rm origin
$git remote add origin https://github.com/toshihirock/CodeDeployWordPress.git


CodeDeployの設定

まずCodeDeployでアプリケーションの作成を行います。以下のコマンドで WordPress_App というアプリケーションを作成します。

$aws deploy create-application --application-name WordPress_App --region us-east-1

次にデプロイメントグループを作成します。本設定ではどのEC2にデプロイするかを設定します。下記例ではEC2のタグでKey=Name、Value=CodeDeployDemoというEC2群にデプロイすることを示す WordPress_DepGroup というデプロイ面とグループを作成しました。

$aws deploy create-deployment-group \

--region us-east-1 \
--application-name WordPress_App \
--deployment-group-name WordPress_DepGroup \
--deployment-config-name CodeDeployDefault.OneAtATime \
--ec2-tag-filters Key=Name,Value=CodeDeployDemo,Type=KEY_AND_VALUE \
--service-role-arn arn:aws:iam::hogefuga:role/CodeDeployDemo

最後にソースコードをデプロイします。--github-locationオプションは適宜自分のリポジトリ名、対象コミットIDに変更してください。

$aws deploy create-deployment \

--region us-east-1 \
--application-name WordPress_App \
--deployment-config-name CodeDeployDefault.OneAtATime \
--deployment-group-name WordPress_DepGroup \
--github-location commitId=74e74ad4e0f80fb91a6034f3be58fce5b45d4a2c,repository=toshihirock/CodeDeployWordPress

デプロイが成功すればデプロイ対象のEC2のPublicIPアドレスを利用して以下のようなURLでアクセスが可能だと思います。

http://ec2-52-2-237-19.compute-1.amazonaws.com/WordPress/


GitHubとの連携を行う

Automatically Deploy from GitHub Using AWS CodeDeploy

まず、IAMでGitHubというユーザーを作成します。なお、ユーザー作成の際に表示されるAccess Key IDとSecret Access keyをメモしておいてください。

また、以下のポリシーを上記ユーザーにCustomPolicyとしてアタッチします。PolicyNameはCodeDeploy-Accessとしました。なお、123ACCOUNTIDという部分は自分のAWSアカウントIDに変更してください。


  • IAM->Users->GitHub->InlinePolicies->click here

  • Custom Policy

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "codedeploy:GetDeploymentConfig",
"Resource": "arn:aws:codedeploy:us-east-1:123ACCOUNTID:deploymentconfig:*"
},
{
"Effect": "Allow",
"Action": "codedeploy:RegisterApplicationRevision",
"Resource": "arn:aws:codedeploy:us-east-1:123ACCOUNTID:application:WordPress_App"
},
{
"Effect": "Allow",
"Action": "codedeploy:GetApplicationRevision",
"Resource": "arn:aws:codedeploy:us-east-1:123ACCOUNTID:application:WordPress_App"
},
{
"Effect": "Allow",
"Action": "codedeploy:CreateDeployment",
"Resource": "arn:aws:codedeploy:us-east-1:123ACCOUNTID:deploymentgroup:WordPress_App/WordPress_DepGroup"
}
]
}

次にGitHub側の設定をします。AWS CodeDeploy用のサービスを追加します。


  • GitHubのページでリポジトリを選択(私の場合、toshihirock/CodeDeployWordPress)

  • Settings

  • Webhooks and Services

  • Add Services->AWS CodeDeploy

以下のように項目を追加します。

次にGitHubのアクセストークンを取得します。

Personal access tokensを表示し、Generate a personal access token を選択し、以下のように設定します。

設定後、トークン情報が表示されるのでメモしておいてください。

先ほどCodeDeployのサービスを設定したページへ再度遷移し、GitHub Auto-Deploymentを追加します。


  • GitHubのページでリポジトリを選択(私の場合、toshihirock/CodeDeployWordPress)

  • Settings

  • Webhooks and Services

  • Add Services->GitHub Auto-Deployment

作成後、以下のように2つのサービスが設定された形となっているかと思います。

準備ができたので試しにWordPressリポジトリにからコミットをしてみます。

$cd /tmp/WordPress

$git commit --allow-empty -m "test CodeDeploy"
$git push origin master
$git log -1
commit b74c07c54a747fd9a44be09031bcd272ae749bed

上記実施後、CodeDeployの画面を確認すると先ほどのコミットIDのリビジョンのソースコードがデプロイされたのが分かります。


最後に

今回CodeDeployを試してみましたが、GitHubへのHook時にデプロイできるのは非常に便利に感じました。そしてCodeDeploy自体の管理をしなくて良いというのは非常に楽ですね。

はやくCodeCommitとの連携ができて、VPCエンドポイントにCodeDeployとCodeCommitが出来てプライベートサブネットからも利用できるようになるととても嬉しいです。