前回のデプロイ記事 で初回のデプロイは完了しました。しかし、プロダクトの改善速度を上げるためには継続的に開発し、デプロイできる環境が必要です。

ということで、今回は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 rsa

GitHubにSecrets情報を登録する

Github Actionsが動くサーバからAWS CLIとSSH接続ができる必要があります。そのために必要な環境変数をRepository secretsに登録します。

GitHubリポジトリ → Setting → Actions secrets and variablesに移動して登録します。

登録する変数は6つです。

名前
EC2_USER_NAMEEC2のユーザー情報
EC2_HOST_NAMEEC2のホスト情報
EC2_SECURITY_GROUP_IDEC2のセキュリティグループID
GIT_PRIVATE_KEYEC2でkeygenしたgithub用の秘密鍵
AWS_ACCESS_KEYAWS CLIのアクセスキー
AWS_SECRET_ACCESS_KEYAWS 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はこれ以外にもいろいろなツールがあります。今回はシンプルという方針で考えたアーキテクチャでした。