AWS CodeDeployでEC2にBlue/Greenデプロイする

## 概要
[AWS CodeDeploy](https://aws.amazon.com/jp/codedeploy/)を使ってEC2にBlue/Greenデプロイをする。

## 流れ
![auto_deploy_small.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/153b1210-3835-e363-f427-4125e558c529.png)



## デプロイ対象のEC2インスタンスを作成
### IAMロールを設定する
`AmazonS3ReadOnlyAccess`をアタッチしたIAMロールを指定する。

### アプリケーションが動作する環境を作成
アプリケーションが動作する環境を作成する。

### AWS CodeDeploy エージェントをインストール
東京リージョンの場合は下記手順でインストールする。

```
$ sudo yum update
$ sudo yum install ruby
$ sudo yum install aws-cli
$ cd /home/ec2-user
$ aws s3 cp s3://aws-codedeploy-ap-northeast-1/latest/install . --region ap-northeast-1
$ chmod +x ./install
$ sudo ./install auto
```
下記のコマンドで導入が確認できればOK

```
sudo service codedeploy-agent status
```


## デプロイ対象のEC2インスタンスで利用するAMIイメージを作成する
EC2インスタンスの起動イメージであるAMIイメージを作成する。
作成したインスタンスを元にAMIイメージを作成する。

## ロードバランサーの作成
マネジメントコンソール → EC2 → ロードバランサー より作成を行う。

![ALB_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/20647f84-b991-7d2c-8f42-94640b1513ff.png)

## AutoScalingGroupの作成 
マネジメントコンソール → EC2 → Auto Scaling グループ より作成を行う。

**新しい起動設定を作成する**を選択する。


- AMIの選択
**マイAMI**から先程作成したAMIイメージを選択する。
![AutoScall_3_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/b21cee22-df4a-9c63-91c8-92e63d5bd79f.png)


- インスタンスタイプの選択
インスタンスタイプを選択する
- 詳細設定
起動設定の名前を入力。
IAMロールは`AmazonS3ReadOnlyAccess`をアタッチしたIAMロールを指定する。
![AutoScall_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/fc2040ad-3222-f738-26f9-69898d701108.png)


この後の手順は省略する。セキュリティグループの設定を忘れずに行う。
ここまででAutoScalingGroupで利用する起動設定が作成完了。

- AutoScalingGroup本体の作成
起動設定は先程作成した起動設定を選択する。
グループ名を入力し、VPCとサブネットの選択を行う。
(少なくとも2つ以上のAZになるように設定しておくことを推奨する。)

この後の手順は省略する。

## builderサーバの準備
`AmazonS3FullAccess`と`AWSCodeDeployDeployerAccess`をアタッチしたIAMロールを指定する。

## デプロイ用ソースコードを格納するS3バケットを作成
非公開のS3バケットを作成する。

## デプロイ対象のアプリケーション設定
`appspec.yml`をデプロイ対象アプリケーションのプロジェクトルートに設置する。
アプリケーション再起動やミドルウェアの再起動等設定が可能。

appspec.yml(サンプル)

```
version: 0.0
os: linux
files:
  - source: /
    destination: /home/ec2-user/my-app
permissions:
  - object: /
    owner: ec2-user
    group: ec2-user
    mode: 777
    pattern: "**"
hooks:
  AfterInstall:
    - location: run.sh
      timeout: 1000
      runas: root
 
```

run.sh

```
#!/bin/bash

mkdir -p /var/my-app/bin

chmod +x my-app
cp -f /home/ec2-user/my-app/my-app /var/my-app/bin/my-app
ln -f -s /var/my-app/bin/my-app /etc/init.d/my-app
service my-app start

```

`appspec.yml`は[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file.html)をよく見ておく事をオススメする。


## デプロイ設定の作成
`AWSCodeDeployRole`をアタッチしたIAMロールを作成しておく。

### アプリケーションの作成
アプリケーション名を入力。
コンピューティングプラットフォームは「EC2/オンプレミス」を選択。
![code_deploy_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/d17fa82a-b506-0dde-e20a-5015dd9bbb4a.png)


### デプロイグループの作成
- デプロイグループ名  
  任意の名前を入力  
- サービスロール  
CodeDeployのフルアクセス権限をアタッチしたIAMロールを指定
![code_deploy_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/29bab92c-867a-aa38-cade-d9f9a28d05d3.png)

- デプロイタイプ  
「Blue/Green」を選択
![code_deploy_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/b3dafa67-dfcc-c075-fb92-797ae8fabb6a.png)

- 環境設定  
「Amazon EC2 Auto Scaling グループの自動コピー」を選択し、作成したAmazon EC2 Auto Scaling グループを選択する。
![code_deploy_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/164ac77f-79c2-7cd0-965a-5dfee6c41fbd.png)


- デプロイ設定
デプロイ成功後インスタンス削除するか選択し、待機時間を指定。
デプロイ設定を選択。
![code_deploy_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/f44b1057-11f4-d05e-a512-e55c6235bf90.png)


| デプロイ設定                    | 条件内容                                |
|:------------------------------|:---------------------------------------|
| CodeDeployDefault.AllAtOnce   | 一回で全部のインスタンスにデプロイしようとする |
| CodeDeployDefault.HarfAtATime | 半分ずつデプロイする                      |
| CodeDeployDefault.OneAtATime  | 1つずつデプロイする                       |

- ロードバランサー  
作成したロードバランサーを選択。

![code_deploy_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/6823d47a-fd05-cff4-3b55-f6307dfc7bb2.png)

- 詳細  
必要に応じて設定する。

### デプロイの作成
- デプロイグループ  
先程作成したデプロイグループを選択。
- リビジョンタイプ  
Amazon S3を選択。
- リビジョンの場所
アップロード済みのソースコードの場所を選択。
作成したAmazon S3 バケット名が`deploy-test-bucket`、ソースコードのファイル名が`my-app`の場合以下のようになる。  
`s3://deploy-test-bucket/my-app.zip`
![code_deploy_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241942/3caff895-7f20-2152-e3a5-a7899762e2d2.png)


## builderサーバでの実行設定
builderサーバから以下のようなスクリプトを実行することでS3バケットにソースコードをアップロードしデプロイ要求を出すことができる。

```
BUILD_DIR=.
REGION=ap-northeast-1
APP_NAME=my-app
DEPLOYMENT_GROUP=deploy-test-group
DEPLOYMENT_CONFIG=CodeDeployDefault.AllAtOnce
S3_BUCKET=deploy-test-bucket
S3_KEY=${APP_NAME}.zip

aws deploy push \
    --region ${REGION} \
    --application-name ${APP_NAME} \
    --s3-location s3://${S3_BUCKET}/${S3_KEY} \
    --source ${BUILD_DIR}

ETAG=`aws deploy list-application-revisions --region ${REGION} \
    --application-name ${APP_NAME} --s-3-bucket ${S3_BUCKET} --s-3-key-prefix ${S3_KEY} \
    --sort-by registerTime --sort-order descending \
    --query 'revisions[0].s3Location.eTag' --output text`

aws deploy create-deployment --region ${REGION} --application-name ${APP_NAME} \
    --s3-location bucket=${S3_BUCKET},key=${S3_KEY},bundleType=zip,eTag=${ETAG} \
    --deployment-group-name ${DEPLOYMENT_GROUP} --deployment-config-name ${DEPLOYMENT_CONFIG}

```

---

[BlueOseanでGitHubとJenkinsの連携](https://qiita.com/yuuulf/items/cee10af0412c12bd9a28)