【AWS】git pushでEC2にも自動デプロイ(CodeDeploy / CodePipeline)

この記事では、

・ローカルのソースコードを更新してコミット
　　　↓
・Githubにプッシュ
　　　↓
・EC2上のソースコードも自動更新

する設定法を備忘録としてまとめておきます。
ローカル環境を更新して、さらにそこから手動でEC2にデプロイするのが面倒だったので
自動デプロイ化を取り入れてみたのですが、だいぶ作業が効率化されて楽になってように感じます。

#今回利用するAWSリソースについて

自動デプロイを実現するために、今回は以下のAWSリソースを利用します。

①VPC（パブリックサブネット）/InternetGateway
②IAM
③EC2
④CodeDeploy
⑤CodePipeline

※別途Githubアカウントも必要になります

#設定の手順について

###①IAMロールの作成

###②EC2を作成し、CodeDeployエージェントをインストール

###③ローカル環境とGithub上での設定

###④CodeDeployの設定

###⑤CodePipelineの設定

<br>

#①IAMロールの作成

EC2用に、
以下の２種類のポリシーがアタッチされたIAMロールを作成します。

①AmazonS3FullAccess　(CodePipelineの仕様で、S3にアクセスする必要があるため）
②AWSCodeDeployRole　 （CodeDeployと連携するため）


IAMロール作成画面にて、
以下のように選択して次に進みます。

| 項目 | 選択する値 |
|:-:|:-:|
|  信頼されたエンティティの種類を選択 | AWS サービス  |
|  ユースケースの選択 | EC2  |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/b8e0b00e-f1c2-788a-566d-e24bbb5549da.png)


次に、「awscodedeployrole」で検索して、ヒットした
AWSCodeDeployRole　のポリシーを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/b78551f0-8989-3c77-6527-f4d2b1ea0aac.png)


続けて「AmazonS3FullAccess」で検索して、
AmazonS3FullAccess　のポリシーを選択して次に進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/e1d993a9-81b8-6b2b-a0f5-d6b1011b863f.png)


次に、タグの選択画面に進みますが、こちらはつけてもつけなくてもOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/09975d2e-93fa-4dff-c68f-21e6c43009fa.png)


ロール名／ロールの説明は任意のものでOKです。
(今回はどちらも「CodeDeployRole」としました）
そして「ロールの作成」をクリックすると、ロールが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/d711ac86-b44e-28d1-0a09-25079ba2f0fd.png)

最後に、作成されたIAMロールを少し編集します。
今作成したロールの概要ページに移動して、**信頼関係**のタブをクリックし、
青色の**信頼関係の編集**ボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/0222ba9d-17d3-9f04-cf01-49b93cbf0a0f.png)

するとポリシードキュメントの編集画面が開くので、これを編集していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/2c17d6be-83fb-e1e2-9103-86372931d9df.png)

`"Service": "ec2.amazonaws.com"`

この部分に、`"codedeploy.amazonaws.com"`を追加して、以下のように編集します。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "codedeploy.amazonaws.com",
          "ec2.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

**信頼ポリシーの更新**ボタンをクリックすると、これでIAMロールの設定は完了です。




#②EC2を作成し、CodeDeployエージェントをインストール

自動デプロイ用のEC2の作成していきます。
EC2のマネジメントコンソールに移動して、「インスタンスの作成」をクリックします。
##ステップ１：AMIの選択
今回は、無料枠対象の**Amazon Linux 2 AMI (HVM), SSD Volume Type**を選択していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/6e96a0df-4514-cdc9-7fb9-b17ff344565c.png)


##ステップ２：インスタンスタイプの選択
こちらも自由ですが、今回は無料枠のt2.microを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/9d27a53b-826c-687f-6865-86bb74d44794.png)


##ステップ３：インスタンスの詳細の設定

以下のように項目を選択して、それ以外はデフォルトでOKです。

| 項目 | 選択する値 |
|:-:|:-:|
|  ネットワーク | InternetGatewayがアタッチされたVPCを選択  |
|  サブネット |  インターネットからアクセスできるパブリックサブネットを選択 |
|  自動割り当てパブリック IP | 有効 |
|  IAMロール | 先ほど作成したロールを選択 |

例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/37286990-86c3-8116-432f-2111be421b67.png)

また、この設定ページの一番下「高度な詳細」という項目内に、**ユーザーデータ**を入力する箇所があるので、
以下のコードを入力します。

```
#!/bin/bash
# CodeDeployAgentのインストール
yum install -y ruby
cd /home/ec2-user
curl -O https://aws-codedeploy-ap-northeast-1.s3.amazonaws.com/latest/install
chmod +x ./install
./install auto

====
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/a5940d75-b375-3bc2-4bdd-fa75810a13c0.png)



このユーザーデータとは、EC2が新規作成されて起動した時に自動で実行されるスクリプトです。(コマンドの集まり）
これにより、EC2にCodeDeployエージェントがインストールされます。


なお、CodeDeployエージェントのインストールコマンドについて、こちらは東京リージョンで
利用する場合限定になります。
CodeDeployエージェントのダウンロードリンクはリージョンによって異なるため、
もし違うリージョンで利用したい場合は、AWSの公式ドキュメントを参考にして、コマンド内の
ダウンロードリンクを適切なものに設定します。
https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/codedeploy-user.pdf#codedeploy-agent-operations-install

(427p辺り)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/fc16cbcc-3710-c875-ee8a-fe81fe0475af.png)




```
# CodeDeployAgentのインストール
yum install -y ruby
cd /home/ec2-user
                 #  ↓ この部分に、リージョン毎のバケットネームをいれる
curl -O https://<< bucket-name >>.s3.amazonaws.com/latest/install
chmod +x ./install
./install auto
```

ユーザーデータの入力が終わったら、「次のステップ：ストレージの追加」をクリックして進みます。

##ステップ 4: ストレージの追加

こちらはデフォルトのままで、次に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/56ca6d5c-2c38-46fa-0965-dd1f2b632832.png)

##ステップ 5: タグの追加

タグは以下のように追加します。
Nameの他にもう一組、CodeDeploy用のキーと値を設定しておくことで、
そのタグを持つ複数のインスタンスに一斉に自動デプロイすることが可能になります。

| キー | 値 |
|:-:|:-:|
| Name  | 任意の値(インスタンス名)  |
| 任意のキー<br>(自動デプロイ先の識別用)  | 任意の値<br>(自動デプロイ先の識別用)  |

例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/c55c5f62-a824-550a-9db3-410f0893c00e.png)


##ステップ 6: セキュリティグループの設定

セキュリティグループは、インスタンスにHTTPアクセスできる(ポート80)ものが既にあればそれを設定し、
もしなければ新しいセキュリティグループを以下のような設定で作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/abcbd918-350d-1fab-640b-2148af8bdc57.png)

##ステップ 7: インスタンス作成

最後に、キーペアを設定してインスタンスを作成します。
これで、EC2の設定と作成は完了です。

なお、CodeDeployエージェントがちゃんとインストールできているかは、EC2インスタンスに
ログインした後、以下のコマンドを打つことで確認することができます。

```
sudo yum info codedeploy-agent
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/73cfaa10-3174-993f-a7ed-469a4a5d57c9.png)

#③ローカル環境とGithub上での設定

###appspec.ymlの作成

CodeDeployでの自動デプロイをする際には、デプロイ元のソースのルートに、
appspec.ymlという設定ファイルを作成する必要があります。
なお、この設定ファイルはAWS公式サンプルスクリプトとして公開されているので、こちらのリンクからダウンロードすることができます。
https://github.com/aws-samples/aws-codedeploy-samples/tree/master/applications/SampleApp_Linux

また、上記のリポジトリにはappspec.ymlの他にも、**script**というディレクトリがありますが、こちらも一緒にダウンロードします。
このディレクトリの中には、Apacheの起動に関するスクリプトファイルが３つ格納されています。
scriptディレクトリも、asspec.ymlと一緒にソースのルートに配置しておきます。

ダウンロードしたappspec.ymlの中身を見てみると、以下のようになっています。

```
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

```

各項目の詳細については割愛しますが、主に重要なのは以下の項目です。

| 項目 | 説明 |
|:-:|:-:|
|os|デプロイ先のEC2インスタンスのOS|
| files: source  | デプロイ元のソースのパス<br>→全ファイル指定の場合は、「/」と記入<br>(同期元)  |
| files: destination  | ソースをEC2のどこにデプロイするか、パスを設定(同期先)  |

上記の設定では、**files: source**の項目に注目すると、これは
ローカルのソースのルートにある**index.html**という名前のファイルが更新されたら、EC2上の
**/www/html**配下のindex.htmlが更新されますよという内容になります。
もし、ローカルのindex.html以外のファイル全部を同期させたい場合は、以下のように「/」のみを指定します。

```
files:
  - source: /
```

###Githubへプッシュ

appspec.ymlとscriptディレクトリが用意できたら、コミットして同期させたいソースと一緒に
Githubのリモートリポジトリにプッシュします。
これで、ローカル環境とGithub上の設定は完了です。

#④CodeDeployの設定

次に、CodeDeployのマネジメントコンソールに移動し、「アプリケーションの作成」をクリックします。

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


| 項目 | 設定値 |
|:-:|:-:|
|  アプリケーション名 |  任意の名前を設定 |
|  コンピューティングプラットフォーム |  EC2/オンプレミス |


例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/1048fe70-b917-e668-210f-b58132cb41f0.png)


##デプロイグループの作成

今回は以下の表のように設定し、それ以外はデフォルトでOKです。

| 項目 | 設定値 |
|:-:|:-:|
| デプロイグループ名  | 任意の名前  |
| サービスロール  | 手順①で作成したIAMロールを選択<br>（入力欄のテキストボックスをクリックすると、候補一覧が表示されます。）  |
| デプロイタイプ  |  インプレース |
| 環境設定  |**Amazon EC2 インスタンス**にチェックをいれる  |
|キー/値|手順②のステップ５でEC2に追加した、<br>CodeDeploy用のキー/値を入力|
| Load balancer  | チェックを外す<br>(今回はELBを使用しないため)  |

例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/3dc27150-cf61-9f08-dc24-fa54058d3cf8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/54673c4b-56e5-6d09-a7dd-87c93b820f88.png)

最後に画面右下の**デプロイメントグループの作成**ボタンを押して次に進みます。


##デプロイの作成

デプロイメントグループが作成できたら、次は**デプロイの作成**ボタンをクリックして設定画面に移り、以下のように設定していきます。

| 項目 | 設定値 |
|:-:|:-:|
|  デプロイグループ |  先ほど作成したデプロイグループを選択 |
| リビジョンタイプ | **アプリケーションは GitHub に格納されています** を選択 |
|  GitHub トークン名 | Githubアカウント名を入力  |
|  リポジトリ名 | Githubのリポジトリ名を入力<br>→ **アカウント名/リポジトリ名** の形式  |
|  コミットID | 最新のコミットIDを入力（ハッシュ値）  |

Githubgとの連携も完了したら、画面下の**デプロイの作成**をクリックします。
するとデプロイの作成が開始され、やや時間がかかります。ここでエラーが発生せずに無事に「成功」と出れば無事にデプロイ完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/64719628-d107-f14b-0522-7e4e48923ba2.png)

EC2インスタンスのIPアドレスを、ブラウザのアドレスバーに入れてエンターキーを押すと、ソースコードの中身が表示されます。
（デプロイ元のソースのルートにindex.htmlという名前のファイルがある場合）

ここで、ローカルのソースに変更を加えてコミットし、Githubへプッシュしてみます。
そしてCodeDeployのマネジメントコンソールから**コードのデプロイ**ボタンを押すとデプロイ作成画面に移り、
**コミットID**の入力欄に最新のコミットIDを入れて**デプロイの作成**を実行すると、Githubにプッシュした内容がEC2上にも反映されて、同期します。
Githubにプッシュする度にコミットIDを書き換えてデプロイの作成を行うのは面倒なので、プッシュと同時に自動デプロイされるように、最後にCodePipelineの設定をします。

#⑤CodePipelineの設定

CodeDeployのマネジメントコンソールの左側に、**パイプライン**という項目があるのでこちらをクリックするとCodePipelineのマネジメントコンソールに移動します。
そうしたら**パイプラインを作成する**ボタンをクリックして設定画面に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/95d8e047-59eb-fe20-681b-a9e2aabe6374.png)

設定画面では、以下のように設定します。

| 項目| 設定値 |
|:-:|:-:|
|  パイプライン名 | 任意の名前  |
|  サービスロール | 新しいサービスロール  |
| ロール名  | ロールが自動入力されるので、そのままでOK  |

例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/119df0dd-8bf3-ed2a-0f8f-f13d3f640390.png)

ソースプロバイダーはGitHubを選択**「GitHubに接続する」**をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/d5c8b9c7-82a4-51eb-039d-6d68cb7d544f.png)


リポジトリとブランチの入力欄が表示されるのでそれぞれを入力して次に進みます。


| 項目 | 設定値 |
|:-:|:-:|
|  リポジトリ | CodeDeployで設定したリポジトリ<br>  |
| ブランチ  | master  |

今回は、ビルドステージの追加をスキップします。
※もしソースにJavaやC#等、コンパイルの必要な言語を使用している場合はビルドの設定が必要になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/898b359c-ff7a-09bb-60ad-9b67d7a2c101.png)

次に、デプロイステージの追加画面では、以下のように設定して次に進みます。

| 項目 | 設定値 |
|:-:|:-:|
| デプロイプロバイダー  | AWS CodeDeploy  |
|  リージョン |  利用するリージョンを選択 |
| アプリケーション名  | CodeDeployで作成したアプリケーションを選択  |
| デプロイグループ  | CodeDeployで作成したデプロイグループを選択  |

例）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/12f9443b-87b2-aa15-5c8d-70c95f204846.png)

確認画面で内容の確認が終わったら、**パイプラインの作成**を実行します。
そうすると以下のような画面が表示され、無事に成功したら、これで全ての設定は終了です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/dfc7c544-11de-adc3-a895-199e1c3dfc8f.png)

ここまできたら、もうローカルのソースを更新してGitHubにプッシュするだけで、自動でEC2にも更新が反映されるようになります。