前回のデプロイ記事 で初回のデプロイは完了しました。しかし、プロダクトの改善速度を上げるためには継続的に開発し、デプロイできる環境が必要です。
ということで、今回はCI/CD環境を構築していきたいと思います。
今回の目的
今回の目的は手軽に開発し、手軽にデプロイできるCI/CD環境を作るということです。また業務を想定して、複数人で実行可能な環境とします。
しかしながら、高機能で複雑な仕組みは使いません。今回はスモールスタートでシンプルな構成でいきます。
仕組みをどうするか
目的と現状の環境から下記のような仕組みとしていきます。
- 開発はローカルPCで行い、ソースコード管理にはGithubを使う
 - エディタはVisual Studio Code
 - mainブランチにマージしたらGithub Actions を使ってEC2にデプロイする仕組みとする
 - Github Actionsの処理は最低限とする
 

Github Actionsの裏側ではサーバが動いています。このサーバからEC2に接続するのですが、このとき毎回グローバルIPアドレスが違います。よって、Github Actionsが動くたびにEC2のセキュリティグループでSSHを許可するルールを追加し、デプロイが終わった後に作成したルールを削除する処理を入れています。
導入手順
事前に必要なもの
- EC2にgitコマンドをインストール
 - ソースコードはGithubで管理している
 
IAM作成
Github Actionsが動くサーバからセキュリティグループを変更するためのユーザと権限を作成します。
まずIAMポリシーを作成します。権限はデプロイ先であるEC2のセキュリティグループを変更できる権限を付与します。[account-id] と [security-group-id] は環境に合わせて変更してください。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:RevokeSecurityGroupIngress",
                "ec2:AuthorizeSecurityGroupEgress",
                "ec2:AuthorizeSecurityGroupIngress",
                "ec2:CreateTags",
                "ec2:RevokeSecurityGroupEgress"
            ],
            "Resource": "arn:aws:ec2:ap-northeast-1:[account-id]:security-group/[security-group-id]"
        }
    ]
}IAMユーザを新規で作成し、さきほど作成したポリシーを割り当てます。
EC2でSSH鍵を作成する
Github Actionsが動くサーバからEC2にSSH接続するための鍵を作成します。
$ ssh-keygen -t rsaGitHubにSecrets情報を登録する
Github Actionsが動くサーバからAWS CLIとSSH接続ができる必要があります。そのために必要な環境変数をRepository secretsに登録します。
GitHubリポジトリ → Setting → Actions secrets and variablesに移動して登録します。
登録する変数は6つです。
| 名前 | 値 | 
|---|---|
| EC2_USER_NAME | EC2のユーザー情報 | 
| EC2_HOST_NAME | EC2のホスト情報 | 
| EC2_SECURITY_GROUP_ID | EC2のセキュリティグループID | 
| GIT_PRIVATE_KEY | EC2でkeygenしたgithub用の秘密鍵 | 
| AWS_ACCESS_KEY | AWS CLIのアクセスキー | 
| AWS_SECRET_ACCESS_KEY | AWS CLIのシークレットアクセスキー | 
設定画面

この変数の登録を行うことでGitHub Actionsのyamlファイルから変数として参照することが可能になります。
Github Actionsの設定
Githubリポジトリ → Actionsからyamlファイルを作成します。ファイル名は好きなものをつけてください。
テストのため、あえてトリガー設定は手動実行にしています。
name: EC2 deploy
on:
  workflow_dispatch:
jobs:
 build:
   runs-on: ubuntu-latest
   steps:
     # IP取得ライブラリをインストール
     - name: Public IP Install
       id: ip
       uses: haythem/public-ip@v1.2
     # BranchをCheckout
     - name: Checkout
       uses: actions/checkout@v2
     # AWS CLIをインストールする
     - name: AWS CLI install
       run: |
         curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
         unzip awscliv2.zip
         sudo ./aws/install --update
         aws --version
     # AWS CLIに認証情報を設定をする
     - name: AWS set Credentials
       uses: aws-actions/configure-aws-credentials@v1
       with:
         aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
         aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
         aws-region: ap-northeast-1
     # デプロイする
     - name: Deploy
       run: |
         # EC2のセキュリティグループにSSH許可ルールを追加する
         aws ec2 authorize-security-group-ingress --group-id ${{ secrets.EC2_SECURITY_GROUP_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
         # SSH接続して、git pullする
         echo "${{ secrets.GIT_PRIVATE_KEY }}" > private_key
         chmod 600 private_key
         ssh -o StrictHostKeyChecking=no ${{ secrets.EC2_USER_NAME }}@${{ secrets.EC2_HOST_NAME }} -i private_key "cd /home/ubuntu/blog.12sec.work/ && git fetch --prune && git checkout main && git pull origin main"
         # EC2のセキュリティグループからSSH許可ルールを削除する
         aws ec2 revoke-security-group-ingress --group-id ${{ secrets.EC2_SECURITY_GROUP_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32テスト
Github リポジトリのActionsからジョブを実行してみます。
最終的に全部のプロセスがPassすればOKです。

最終的なトリガー変更
テスト実行して問題なければトリガーを変更します。
変更箇所は on: となっている箇所です。トリガーの種類は公式ドキュメントに記載されています。
on:
  workflow_dispatch:まとめ
シンプルなCI/CD環境ができました。あとはガシガシ開発して、プロダクト改善するのみです。
CI/CDはこれ以外にもいろいろなツールがあります。今回はシンプルという方針で考えたアーキテクチャでした。