AWS CodeDeployを設定してみる EC2にデプロイ

## 概要

AWS CodeDeployを初めて触ったので体験記的に残しておく。
今回はGithubで管理されているlaravelのコード郡をEC2にデプロイする。WebサーバーはApacheを使っている。
当該のEC2は下記の方法（一部PHPのバージョンなどは異なる）で構築し、手動git pullでコードの取得しEC2のパブリックDNSでブラウザからwelcome画面が開くことを確認できている。

https://qiita.com/miriwo/items/b39d1ac6289c54cc2cfd

## 前提

先に下記の記事で構築したCodePiplineに、本記事で作成するCodeDeployを紐づけて動作確認を行っている。

https://qiita.com/miriwo/private/ea5b16655612002b8af0

またCode三兄弟と言われるAWSリソースのざっくりとした役割分担を下記に簡単にまとめた。

https://qiita.com/miriwo/items/c28204e3f53150dca2ce

## 基本的な設定項目

先に決定しておいたほうが良い内容を下記に記載しておく。

| 項目 | 制約や選択や内容 | 備考 |
| --- | --- | --- |
| アプリケーション名 | 100文字以下で日本語不可 | CodeDepoloyのアプリケーション名<br>アプリケーション名とはデプロイ動作をグルーピングする最も外側の概念 |
| コンピューティングプラットフォーム | 「EC2/オンプレミス」 or 「AWS Lambda」 or 「Amazon ECS」から選択 | デプロイ対象のリソースを選択 |
| デプロイグループ名 | 100文字以下で日本語不可 | デプロイアプリケーションに所属する具体的なデプロイ動作の設定の名前 |
| サービスロール名（CodeDeploy割当） | 64文字以下で日本語不可 `+=,.@-_`などの特殊文字使用可 |  |
| サービスロール説明（CodeDeploy割当） | 1000文字以下で日本語不可 `+=,.@-_`などの特殊文字使用可 |  |
| サービスロール名（EC2割当） | 64文字以下で日本語不可 `+=,.@-_`などの特殊文字使用可 | EC2にロール未設定の場合 |
| サービスロール説明（EC2割当） | 1000文字以下で日本語不可 `+=,.@-_`などの特殊文字使用可 | EC2にロール未設定の場合 |
| デプロイタイプ | 「インプレース」 or 「Blue/Green」| デプロイ方法の選択 |
| デプロイ設定 | 「CodeDeployDefault.OneAtATime」 or<br>「CodeDeployDefault.HalfAtATime」 or<br>「CodeDeployDefault.AllAtOnce」<br>もしくは自分で設定 | 「CodeDeployDefault.OneAtATime」→すべてのインスタンスを一括デプロイ<br>「CodeDeployDefault.HalfAtATime」→すべてのインスタンスを半分半分にデプロイ<br> 「CodeDeployDefault.AllAtOnce」→一つのインスタンスのみデプロイ |
| デプロイ先EC2のインスタンス名 |  | CodeDeployがデプロイする先のインスタンス指定で使用 |
| アクション名 | 100文字以下で日本語不可 | CodePiplineと紐付ける際のデプロイアクション名 |

## 流れ

1. デプロイグループに割り当てるサービスロールの作成
1. EC2に割り当てるサービスロールの作成
1. CodeDeployアプリケーションの作成
1. デプロイメントグループの作成
1. CodeDeployエージェントをEC2にインストール
1. AppSpecファイルの作成
1. CodePiplineとの紐づけ

## 詳細

1. デプロイグループに割り当てるサービスロールの作成
    1. IAMを開き、左サイドバーの「ロール」をクリックする。
    1. ロールを作成をクリックする。
    1. AWSのサービスを選択し、「サービスまたはユースケース」で「CodeDeploy」を選択する。
    1. 「ユースケース」で「CodeDeploy」を選択する。
    1. 追加ポリシーを確認して問題なければ「次へ」をクリックする。
1. EC2に割り当てるサービスロールの作成
    1. IAMを開き、左サイドバーの「ロール」をクリックする。
    1. ロールを作成をクリックする。
    1. AWSのサービスを選択し、「サービスまたはユースケース」で「EC2」を選択する。
    1. 「ユースケース」で「EC2」を選択する。
    1. 「許可を追加」にて`AWSCodeDeployRole`と`AmazonS3ReadOnlyAccess`を検索し、付与する。
    1. 追加ポリシーを確認して問題なければ「次へ」をクリックする。
    1. ロール名を`ec2-code-deploy`としてロールを作成する。
    1. EC2の画面に移動し、デプロイ先インスタンスの詳細ページを開く。
    1. 「アクション」をクリックし「セキュリティ」→「IAMロールを変更」をクリックする。

        ![インスタンスの詳細___EC2___ap-northeast-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/6709ed7f-3a37-b337-f386-e0759fb0bb17.png)

    1. 先に追加した`ec2-code-deploy`のロールを割り当ててIAMロールの更新を行う。
1. CodeDeployアプリケーションの作成
    1. CodeDeployのサイドバーで「アプリケーション」をクリックする。
    1. アプリケーションの作成をクリックする。
    1. 下記の情報を入力・選択する。
        1. アプリケーション名
        1. コンピューティングプラットフォーム
1. デプロイメントグループの作成
    1. サイドメニューで「デプロイ」の「アプリケーション」をクリックし、先に作成したCodeDeployのアプリケーション名をクリックする。
    1. 「デプロイグループの作成」をクリックする。
    1. 各種情報を入力し、保存する。
1. CodeDeployエージェントをEC2にインストール
    1. EC2インスタンスにssh接続する。
    1. 下記を実行してCodeDeployエージェントをEC2にインストールする。（東京リージョンの場合）

        ```shell
        sudo yum update
        sudo yum install ruby
        sudo yum install wget
        cd /home/ec2-user
        wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
        chmod +x ./install
        sudo ./install auto
        ```

    1. 下記を実行してインストールできて動作しているか確認する。

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

    1. 下記のようにでたらインストール完了となる。

        ```
        The AWS CodeDeploy agent is running as PID
        ```

    1. CodeDeployエージェントインストール後にEC2などのIAMいじった場合下記コマンドを実行してCodeDeployエージェントの再起動を都度実施する必要がある。

        ```
        sudo service codedeploy-agent restart
        ```
         
1. AppSpecファイルの作成
    1. 実際にデプロイするときの動作を示すファイルを作成・記載していく。（Githubのリポジトリルートのappspec.ymlを特に設定せずともCodeDeployは勝手に見に行く。）
    1. appspec.ymlについては[こちら](https://qiita.com/miriwo/private/19b4dfacf31ed0508dde)でちょっとだけ詳しく記載している。
    1. Githudで管理されているルートディレクトリに下記のファイルとディレクトリを追加する。
        - `appspec.yml`
        - `scripts/`
    1. 更に上記で追加した`scripts/`ディレクトリに下記のスクリプトファイルを追加する。
        - `scripts/application_stop.sh`
        - `scripts/before_install.sh`
        - `scripts/after_install.sh`
        - `scripts/application_start.sh`
        - `scripts/validate_service.sh`
    1. それぞれ下記のように記載する。
        - `appspec.yml`

            ```appspec.yml
            version: 0.0
            os: linux
            files:
              - source: ./
                destination: /var/www/html/test
            file_exists_behavior: OVERWRITE
            hooks:
              ApplicationStop:
                - location: scripts/application_stop.sh
                  timeout: 60
                  runas: root
              BeforeInstall:
                - location: scripts/before_install.sh
                  timeout: 60
                  runas: root
              AfterInstall:
                - location: scripts/after_install.sh
                  timeout: 60
                  runas: root
              ApplicationStart:
                - location: scripts/application_start.sh
                  timeout: 60
                  runas: root
              ValidateService:
                - location: scripts/validate_service.sh
                  timeout: 60
                  runas: root
            ```

        - `scripts/application_stop.sh`

            ```scripts/application_stop.sh
            #!/bin/bash
            
            # Apacheサーバーの停止コマンド
            sudo systemctl stop httpd
            ```

        - `scripts/before_install.sh`

            ```scripts/before_install.sh
            #!/bin/bash
            
            # 既存のキャッシュや一時ファイルのクリーンアップ
            rm -rf /var/www/html/test/bootstrap/cache/*.php
            
            # 設定ファイルのバックアップ
            cp /var/www/html/test/.env /var/www/html/test/.env.backup
            ```

        - `scripts/after_install.sh`

            ```scripts/after_install.sh
            #!/bin/bash
            
            # Laravelアプリケーションのディレクトリに移動
            cd /var/www/html/test
            
            # Composerを使用して依存関係をインストール
            composer install --no-interaction --prefer-dist --optimize-autoloader
            
            # マイグレーション
            php artisan migrate --force
            
            # キャッシュのクリア
            php artisan cache:clear
            ```

        - `scripts/application_start.sh`

            ```scripts/application_start.sh
            #!/bin/bash
            
            # Apacheサーバーの起動
            sudo systemctl start httpd
            ```

        - `scripts/validate_service.sh`

            ```scripts/validate_service.sh
            #!/bin/bash
            
            # ヘルスチェック系の処理
            ```

1. CodePiplineとの紐づけ
    1. [こちら](https://qiita.com/miriwo/private/ea5b16655612002b8af0)の記事で作成したCodePiplineの詳細ページを開く。
    1. 「編集する」をクリックする。
    1. 「編集する: Deploy」の「ステージを編集する」をクリックする。
    1. すでに設定されているS3のデプロイシーケンスを削除する。
    1. 「+アクションの追加」をクリックし、任意のアクション名を入力し、「アクションプロバイダー」のプルダウンで「AWS CodeDeploy」を選択する。
    1. 入力項目が増えるはずなのでそれぞれ入力・選択する。
        1. 「リージョン」 → アジアパシフィック（東京）
        1. 「入力アーティファクト」 → SourceArtifact
        1. 「アプリケーション名」 → 今回追加したCodeDeployのアプリケーション名
        1. 「デプロイグループ」 → 今回追加したデプロイグループ
    1. それぞれ入力できたら「完了」を押下して登録する。
1. 動作確認
    1. CodePiplineで監視しているリモートリポジトリに紐づくローカルリポジトリにて下記を実行し、空コミットの作成とpushを行う。（筆者の場合masterブランチが監視対象）

        ```
        git commit -m '空コミット' --allow-empty
        git push origin master
        ```

    1. CodePiplineが起動し、CodeDeployが無事に正常完了するかを監視する。
    1. エラー終了する場合、下記の方法でログを確認する事ができる。

☆リンク☆


## 参考文献

https://carametal.hatenablog.com/entry/2020/12/05/114515#EC2%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%AE%E8%B5%B7%E5%8B%95

https://nihemak.hatenablog.com/entry/2018/12/04/001852

https://qiita.com/imunew/items/687221e02d977564d610

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/codedeploy-agent-operations-install.html

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/codedeploy-agent-operations-install-linux.html

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/troubleshooting-deployments.html

https://open-groove.net/ci-cd/codedeploy-file_exists_behavior/

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file.html

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/tutorials-github.html