EC2にCodeDeployを用いてデプロイ自動化

社内用に React + Nginx + Java(Quarkus) + MySQL を用いて簡単なWEBアプリケーションを作成しました。
ECS や S3 に配置して RDS や DynamoDB を用いてサーバレス化する手法もあったのですが、多くのお金がかかりそうだったので今回はEC2(t2.micro)を利用することにしました。
しばらくはこのままで行くのでデプロイする際に毎回手動でファイルコピーしてサービスの起動が手間なのでCodeDeployを用いて自動化してみました!

Reactプロジェクトの準備

Reactアプリは各自良い感じで作成してください。CodeDeployを実行させるために必要なファイル達を追加しましょう!

まずは appspec.yml。詳細は公式ドキュメントを参照してください。

version: 0.0
os: linux

files:
  - source: build/                    # 同期元
    destination: /usr/share/nginx/html # 同期先

permissions:
  - object: /usr/share/nginx/html
    owner: root
    group: root
    mode: 755
    type:
      - directory
  - object: /usr/share/nginx/html
    owner: root
    group: root
    mode: 644
    type:
      - file

hooks:
  ApplicationStop:
    - location: scripts/application_stop
      timeout: 300
      runas: root
  BeforeInstall:
    - location: scripts/before_install
      timeout: 300
      runas: root
  ApplicationStart:
    - location: scripts/application_start
      timeout: 300
      runas: root

大事なのでは files セクション。
CodeDeployでリビジョン、デプロイする成果物のzip(zip以外にもtarなどがあります)内のパスをします。

続いて hooks の location にかかれているファイル群

scripts/application_stop

#!/bin/bash

isExistApp=$(pgrep nginx)
if [[ -n $isExistApp ]]; then
    systemctl stop nginx
fi

script/before_install

#!/bin/bash

rm -fr /usr/share/nginx/html/*

script/application_start

#!/bin/bash

systemctl start nginx

hooks のライフサイクルについてクラメドさんのブログを参考にしてください。

さて、必要なファイルが整ったので、ビルドして成果物と上記で準備したファイル達をS3にアップロードしましょう。

yarn build
zip -r build.zip build appspec.yml scripts
aws s3 cp build.zip s3://ec2-code-deploy-test

EC2側の準備

IAMロールをEC2に付与

EC2 へ IAMロールを付与します。EC2のコンソールから実施します。

付与するIAMにはS3へのアクセスを許可するポリシーを設定してください

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:Get*",
        "s3:List*"
    ],
      "Resource": [
        "arn:aws:s3:::ec2-code-deploy-test/*"
      ]
    }
  ]
}

※ IAMロール作成直後にEC2に付与する際にエラーが出る場合があります。IAMロールを正しく認識できずにエラーになるそうです。しばらく時間が経てば設定可能になりますので、焦らずちょっと待ちましょう

EC2にタグ設定

CodeDeployでデプロイするインスタンスを識別するためにタグが用いられるので、デプロイ用のタグを任意に設定しましょう。

EC2にCodeDeploy Agentのインストール

CodeDeploy の Agent をインストールしないと実際のデプロイ作業が実施されません。

sudo yum install ruby 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

sudo systemctl enable codedeploy-agent
sudo systemctl status codedeploy-agent
● codedeploy-agent.service - AWS CodeDeploy Host Agent
   Loaded: loaded (/usr/lib/systemd/system/codedeploy-agent.service; enabled; vendor preset: disabled)
   Active: active (running) since 金 2021-06-04 14:12:59 UTC; 2min 4s ago
  Process: 2676 ExecStart=/bin/bash -a -c [ -f /etc/profile ] && source /etc/profile; /opt/codedeploy-agent/bin/codedeploy-agent start (code=exited, status=0/SUCCESS)
 Main PID: 2688 (ruby)
   CGroup: /system.slice/codedeploy-agent.service
           ├─2688 codedeploy-agent: master 2688
           └─2692 codedeploy-agent: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller of master 2688

 6月 04 14:12:59 ip-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal systemd[1]: Starting AWS CodeDeploy Host Agent...
 6月 04 14:12:59 ip-xxx-xxx-xxx-xxx.ap-northeast-1.compute.internal systemd[1]: Started AWS CodeDeploy Host Agent.

正しくIAMの設定などができていない場合
/var/log/aws/codedeploy-agent/ にあるログにエラーが表示されますのでIAMの権限を確認したのち、codedeploy-agent を再起動しましょう。

CodeDeployの準備

CodeDeployのコンソールに行き、アプリケーションの作成

続いてデプロイグループの作成

そしてデプロイの作成

追加のデプロイ動作で「コンテンツの上書き」にすれば before_install で実施しているファイルの削除は不要かと思います。今回のブログではデプロイ前に削除しています。

最後に

これでEC2に対してデプロイが完了です。
CodeDeployは追加の費用がないので、1度設定しておけば今後が楽ちんですね!

質問やうまく設定できない、動作しないなどがあれば質問箱からお待ちしております。