AWS CodeDeployの導入 & AWS CodePipeLineでgit pushの度にEC2に自動デプロイ & 結果をSlackに通知

#AWS CodeDeployの導入

##2つのIAMロールの作成
###CodeDeployのIAMロール作成
1. マネジメントコンソールからIdentity and Access Managementを選択
2. 詳細の項目からロールを選択して、新しいロールを作成を選択

手順 1: ロール名の設定
	ロール名: myCodeDeploy
手順 2: ロールタイプの選択
	Amazon EC2を選択
手順 3: 信頼性の確立
	飛ばされる
手順 4: ポリシーのアタッチ
	AWSCodeDeployRoleを選択
手順 5: 確認
	内容を確認してロールの作成を選択


※次に、重要な作業で、Identity and Access Managementの詳細項目中のロールから先ほど作成したmyCodeDeployを選択して、信頼関係タブ中の信頼関係の編集を選択する

現れた信頼関係のポリシードキュメント中のStatementのPrincipal中のServiceを"ec2.amazonaws.com"から"codedeploy.us-west-2.amazonaws.com"に変更する。変更したjsonは以下のようになる。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "codedeploy.us-west-2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```
編集したら、信頼ポリシーの更新を選択する。

###EC2のIAMロール作成
CodeDeployのIAMロールの作成と同様に以下のものを作成する。

ロール名: myEC2CodeDeploy
ロールタイプ: EC2
ポリシーアタッチ: AmazonS3ReadOnlyAccess

ここでは信頼関係の設定は特には必要ない。

##EC2インスタンスの作成
マネジメントコンソールからEC2を選択し、トップ画面のインスタンスの作成項目中からインスタンスの作成を選択する

以下のように入力する。


1.AMI の選択
クイックスタート: Amazon Linux AMI 2016.03.3 (HVM), SSD Volume Type - ami-7172b611 を選択
2.インスタンスタイプの選択
	t2.micro
3.インスタンスの設定
	ここで重要なのが、IAMロールとして先ほど作成したmyEC2CodeDeployを選択する
4.ストレージの追加
	デフォルト設定のまま
5.インスタンスのタグ付け
	Name : MyCodeDeploy
6.セキュリティグループの設定
新しいセキュリティグループを作成するを選択し、
セキュリティグループ: myCodeDeploySGとし、
	SSH : 任意の場所
	HTTP : 任意の場所
を設定する
7.確認
	設定内容を確認し、インスタンスの作成を行う。

##EC2の設定

```bash
$ ssh -i ~/.ssh/id_rsa_aws_test ec2-user@<EC2インスタンスに割り振られたパブリックIPアドレス>
```

```bash
$ sudo yum -y update
$ sudo yum install -y aws-cli
$ pwd
/home/ec2-user
$ aws configure
$ aws s3 cp s3://aws-codedeploy-us-east-1/latest/install . --region us-west-2
$ chmod +x ./install
$ sudo ./install auto
$ sudo service codedeploy-agent status
```


#CodeDeployの設定
##デプロイに必要なファイルの準備
###appspec.ymlの作成
appspec.ymlというdeploy時の挙動について定義するファイルを作成する。appspec.ymlには以下の内容がある。

```
os
files
permissions
hooks
```
また、
hooksには、以下のようなライフサイクルがあり、その都度の挙動を定義できる。

```
(Start)
↓
ApplicationStop
↓
DownloadBundle
↓
BeforeInstall
↓
Install	
↓
AfterInstall
↓
ApplicationStart
↓
ValidateService
↓
(End)
```

詳細はドキュメントを参照
http://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/app-spec-ref-structure.html

例えば、以下のように作成する

```appspec.yml
version: 0.0
os: linux
files:
    - source: /
      destination: /var/www/html
permissions:
    - object: /var/www/html
      pattern: "**"
      owner: apache
      group: apache
      mode: 755
      type:
        - file
hooks:
    BeforeInstall:
     - location: scripts/initialize.sh
       runas: root
```

その他、以下のようなファイルを作成する。

```initialize.sh
#!/bin/bash
yum -y install httpd
service httpd start
```

```index.html
<html>
	<body>Hello, world!</body>
</html>
```

ファイル構成としては以下の通りとなる。

```
scripts/initialize.sh
index.html
appspec.yml
```

上記をGitHubのレポジトリにアップしておく。
S3にアップロードしてやることもできる。

重要なのは、リビジョンのトップにappspec.ymlを置くことである。

マネジメントコンソールからCodeDeployを選択する

##アプリケーションの設定
CodeDeployトップの画面から、新しいアプリケーションの作成を選択する

アプリケーション名: myCodeDeploy
デプロイグループ名: myCodeDeploy

インスタンスの追加で
キー: Name
値: MyCodeDeploy


サービスロール
	サービスロールARN: arn:aws:iam::~:role/myCodeDeploy

アプリケーションの作成を選択する

##新しいデプロイの作成
CodeDeployトップから先ほど作成したmyCodeDeployにチェックを入れて、アクションから新しいリビジョンのデプロイを選択して、以下のように入力する

アプリケーション: myCodeDeploy
デプロイグループ: myCodeDeploy
リビジョンタイプ: アプリケーションは GitHub に格納されています

GitHubに接続を選択する。すると現れる項目について以下のように入力する

リポジトリ名: ＜GitHub登録ユーザー名＞/＜レポジトリ名＞
コミットID: ＜コミットID＞
デプロイ設定: CodeDeployDefault.oneAtTime

を入力して、今すぐデプロイを選択する

しばらくすると、作成したデプロイのステータスが成功となる。

ブラウザから```http://<EC2インスタンスに割り振られたパブリックIPアドレス>```へアクセスすると、作成したindex.htmlの内容が表示される。




#git pushでEC2に自動デプロイ
ここではAWS CodePipelineを使う方法とGitHubのWebhooks機能を使う方法の2つを紹介する。いずれかの方法で行うと良い。
なお、AWS CodePipelineを使った場合は簡単に設定でき、また、GitHubに限らずS3からソースをデプロイしたり、ビルドにJenkinsやSolano CIを選択したり、Deploymentを行う手段として、CodeDeployやAWS Elastic Beanstalkなどを用いることができる。

##(その1) AWS CodePipelineを使う方法
###Step 1: Name
Pipeline name: CodePipelineTest

###Step 2: Source
Source provider: GitHub
Repository: ＜GitHubユーザー名＞/＜レポジトリ名＞
Branch: master

###Step 3: Build
Build provider: No Build

###Step 4: Beta
Deployment provider: AWS CodeDeploy
Application name: myCodeDeployForCodePipeline
Deployment group: myCodeDeployForCodePipeline

###Step 5: Service Role
Role nameはCreate Roleを選択して遷移した先のページで以下のように入力して許可を選択する。

IAMロール: 新しいIAMロールの作成
ロール名: AWSCodePipelineService

###Step 6: Review
内容を確認したら、Create pipelineを選択

以上で、EC2に自動でデプロイが始まり、以降GitHubにpushする度に自動でデプロイされるようになる。


##(その2) GitHubのWebhooks機能を使う方法
GitHubのServiceにAWS CodeDeployとGitHub Auto-Deploymentの2つを追加する必要がある。
###AWS CodeDeployをServiceに登録
GitHubのデプロイするレポジトリ内のページからSettingsタブを選択し、Webhooks & servicesを選択。
Servicesの項目から、Add serviceを押してAWS CodeDeployを選択する。そして、以下ののように入力する。

Application name: myCodeDeploy
Deployment group: myCodeDeploy
Aws access key: ＜IAMユーザーで発行されたcredetialsのアクセスキー＞
Aws region: ＜CodeDeployを実行する地域 ex. us-west-2＞
GitHub api url: 空欄
Aws secret access key: ＜IAMユーザーで発行されたcredetialsのアクセスシークレット＞
GitHub token: 空欄


###GitHub Auto-DeploymentをServiceに登録
最初にGitHubからデプロイするためのトークンを発行する。
1.GitHubの画面右上の自分のアイコンを押すと出て来るメニューからSettingsを選択
2.Personal settingsからPersonal access tokensを選択する。
3.Generate new tokenを押す
4.出て来る画面で、Token descriptionは自分で他のトークンと識別ができるように適当に記述しておく。加えて、repo_deploymentを最低限チェックを入れた上でGenerate tokenを押すと、トークンが発行されるので、表示されたトークンをメモしておく。

次に、GitHubのデプロイするレポジトリ内のページからSettingsタブを選択し、Webhooks & servicesを選択
Servicesの項目から、Add serviceを押してGitHub Auto-Deploymentを選択する。そして、以下ののように入力する。

GitHub token: <先ほど発行したトークン>
Environment: myCodeDeploy
Deploy on status: 未チェック
GitHub api url: 空欄
Active: チェック


以上で、git pushでGitHubに変更を送るとEC2のサーバーに自動で反映されるようになる。

#デプロイ結果をSlackに通知
##SNSトピックの作成
1.マネジメントコンソールからSNSを選択する。
2.SNS dashboardからCommon actions中のCreate topicを選択する。
3.出てきたポップアップで以下のように入力する
Topic name: deploy_status
Display name: deploystat 

入力したらCreate topicを選択する。

##CodeDeployにトリガーの設定
CodeDeployの画面から先ほど作成したmyCodeDeployを選択し、Actionから編集を押す。

先ほど未設定にしておいたトリガーの項目からトリガーの作成を選択し、以下のように入力する

トリガー名: deploy-status-trigger
イベント: Deployment Status(all)
Amazon SNS トピック: <先ほどSNSで作成したトピック>


myCodeDeploy のデプロイ設定が変更されましたの項目にチェックを入れ、保存して今すぐデプロイを押し、現れたポップアップから今すぐデプロイを選択する

#デプロイ結果をSlackに通知
##SNSの通知設定
マネジメントコンソールからSNSを選択
SNS dashboardの項目からTopicsを選択
Create new topicを選択して以下のように項目を入力する

Topic name: Deploy_information
Display name: Deployer

入力したらCreate topicを選択する

##CodeDeployの設定
1.予め対象となるEC2のインスタンスにタグ名を選択しておく。
例)EC2のページで対象となるインスタンスを選択して、タグ項目中に以下のようなタグを追加する
Name: MyCodeDeploy

2.マネジメントコンソールからIdentity and Access Managementを選択して、ロールから新しいロールの作成を選択する。

手順 1: ロール名の設定
ロール名: myLambdaExecuteRole

手順 2: ロールタイプの選択
AWS Lambdaを選択

手順 3: 信頼性の確立
Pass

手順 4: ポリシーのアタッチ
AWSLambdaExecuteを選択

手順 5: 確認
内容を確認してロールの作成を選択



3.マネジメントコンソールからCodeDeployを選択
4.新しいアプリケーションの作成を選択して、以下の内容を入力する

###新しいアプリケーションの作成

```
アプリケーション名: CodeDeployApp
デプロイグループ名: CodeDeployGroup
```

###インスタンスの追加

```
Name: MyCodeDeploy
```
ここは予めEC2に割り当てておいたタグ名とする


###デプロイ設定

```
CodeDeployDefault.OneAtTime
```


###トリガー
トリガーの作成を選択して、現れたポップアップに以下の内容を入力する

トリガー名: CodeDeploy
イベント: Deployment Status(All)

###Amazon SNS トピック: Deploy_information

以上のように項目を入力したら、トリガーの作成を選択

サービスロール

```
サービスロールARN: arn:aws:iam::~:role/myLambdaExecuteRole
```

デプロイグループの作成を選択する



##Lambdaの作成
予めローカルでLambdaにアップロードするファイルを作成しておく.
事前準備として、Slack APIを使用するための登録をしておく

###Slack APIの登録
1.https://api.slack.com/custom-integrations のURLにブラウザから飛ぶ

2.Set up an incoming webhookを選択

3.右上のセレクトボックスから対象のチームを選択
4.Post to Channelでチャンネルを選択
ここでは自分宛にするので、```Privately to @hoge (you)```を選択

5.Add Incoming Webhooks integrationを選択

6.遷移した先のページに表示されるWebhook URLをメモしておく。


###Lambdaファイルの作成
ローカルで以下のような作業を行う

```bash
$ mkdir deployInform
$ cd deployInform
$ pip install requests -t .
$ vim lambda_function.py
```

lambda_function.pyの内容は以下のURLの内容のものを参考にさせて頂きました。channelは先ほどの個人宛の場合は@hogeのように指定する。
http://ceblog.mediba.jp/post/141460887747/aws-codedeployのデプロイ結果をslackに流す


```bash
$ zip -r deploy.zip -t *
```

###コンソールからLambdaの操作
マネジメントコンソールからLambdaを選択
Create a Lambda funtionを選択

###Select blueprint
sns-message-pythonを選択

###Configure triggers
SNS topic: Deploy_information
Enable triggerのチェックを入れる


###Configure function
Name: myDeploymentLambda


Lambda function code
Code entry type: Upload a .ZIP file
Function package: 作成したzipをアップロードする

Lambda function handler and role
Handler: lambda_function.lambda_handler(<ファイル名>/<関数名>)
Role: Choose a existing role
Existing role: myLambdaExecuteRole

残りの項目はEC2の属するVPCがデフォルトの物であればデフォルトで良い。

Review
内容を確認したらCreate functionを選択

以上でソースコードをgit pushする度にEC2インスタンスにデプロイされて、その結果がSlackに通知されるようになる。


#参考
https://www.youtube.com/watch?v=qZa5JXmsWZs
https://github.com/andrewpuch/code_deploy_example
http://qiita.com/yukofeb/items/e077fc8755416c904032
http://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/how-to-create-service-role.html
http://qiita.com/toshihirock/items/4ab08afcab2a0e7628a8