EC2をデプロイ先としたCI/CD 環境を構築する

概要

CodeCommitにファイルをコミットすると、CodePipelineが変更を検知し、自動でEC2にデプロイが実行されるCI/CD環境を構築する

実装方法

EC2の起動と設定

IAM Roleの作成

EC2用のRoleを作成し、S3FullAccessのpolicyを適用する

aws iam create-role \
  --role-name ci-cd-handson-role \
  --assume-role-policy-document file://policy_ec2.json

aws iam create-instance-profile \
  --instance-profile-name ci-cd-handson-role

aws iam add-role-to-instance-profile \
  --role-name ci-cd-handson-role \
  --instance-profile-name ci-cd-handson-role

aws iam attach-role-policy \
  --role-name ci-cd-handson-role \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

ファイル: policy_ec2.json

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

セキュリティーグループの作成

セキュリティーグループを作成し、80/TCPに対してのインバウンドアクセスを許可する

  • vpc-idにはEC2を起動するVPCのIDを指定
aws ec2 create-security-group \
  --description ci-cd-handson-sg \
  --group-name ci-cd-handson-sg \
  --vpc-id vpc-48e5b920 

aws ec2 authorize-security-group-ingress \
    --group-id sg-0e0c2b3de1f708991 \
    --protocol tcp \
    --port 80 \
    --cidr xxx.xxx.xxx.xxx/32

aws ec2 authorize-security-group-ingress \
    --group-id sg-0e0c2b3de1f708991 \
    --protocol tcp \
    --port 22 \
    --cidr 3.112.23.0/29

※ EC2 Instance Connectでアクセスする場合、SGでsshの解放が必要
3.112.23.0/29 はEC2 Instance Connectを使用する場合にアクセス元になるAWSのアドレス
AWS IP アドレスの範囲 - AWS 全般のリファレンス

EC2の起動

  • image-id: AmazonLinux2のAMIを指定
  • subnet-id: Publicセグメントのネットワークを指定
    ※ Privateなネットワークでも問題ないが、その場合、ブラウザでアクセスするのにELBも作成が必要
  • 検証なので、sshキーは指定しないでEC2 Instance Connectでブラウザ経由でアクセスする
    EC2 Instance Connect を使用して接続 - Amazon Elastic Compute Cloud
aws ec2 run-instances \
    --image-id ami-0ce107ae7af2e92b5 \
    --instance-type t2.micro \
    --subnet-id subnet-38e5b950 \
    --security-group-ids sg-0e0c2b3de1f708991 \
    --associate-public-ip-address \
    --iam-instance-profile Arn=arn:aws:iam::xxx:instance-profile/ci-cd-handson-role \
    --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=handson}]'

EC2への接続

AWSコンソールよりEC2を選択し、「接続」をクリック
EC2 Instance Connectのタブで「接続」をクリックすると、ブラウザ経由でインスタンスにsshができる

EC2の設定

yum updateとapacheのインストール

sudo yum update -y
sudo yum install httpd -y

sudo systemctl start httpd
sudo systemctl enable httpd

インスタンスのグローバルIPを確認し、ブラウザでアクセスできることを確認する

CodeDeployエージェントのインストール
Amazon Linux 用または RHEL 用の CodeDeploy エージェントをインストールする - AWS CodeDeploy

sudo yum install ruby -y
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 status codedeploy-agent

CodeBuildの設定

  • CodeBuildでは、ソースをコンパイルし、テストができるできるソフトウェアパッケーの作成を行う
  • CocdeBuildの設定はbuildspec.ymlに記載する

アーティファクト(成果物格納)用のS3バケットの作成

aws s3 mb s3://ci-cd-arti --region ap-northeast-1 

Buildプロジェクトの作成

以下の内容を設定し、「ビルドプロジェクトを作成する」をクリックする

プロジェクトの設定

プロジェクト名: ci-cd-handson

ソース

ソースプロバイダ: AWS CodeCommit
リポジトリ: ci-cd-handson
リファレンスタイプ: ブランチ
ブランチ: master

環境

オペレーティングシステム: AmazonLinux2
ランタイム: Starndard
イメージ: /aws/codebuild/amazonlinux2-x86_64-standard:3.0
イメージのバージョン: /aws/codebuild/amazonlinux2-x86_64-standard:3.0-20.09.04

アーティファクト

タイプ: Amazon S3
バケット名: ci-cd-arti

IAM Roleに権限を追加

Buildプロジェクト作成の際に作成されたRoleに、AWSCodeDeployDeployerAccceeの権限を追加する

aws iam attach-role-policy \
  --role-name codebuild-ci-cd-handson-service-role \
  --policy-arn arn:aws:iam::aws:policy/AWSCodeDeployDeployerAccess

buildspec.ymlの作成

↓を参考に作成する
CodeBuild のビルド仕様に関するリファレンス - AWS CodeBuild
CodeDeploy のリビジョンを Amazon S3 にプッシュする (EC2/オンプレミス デプロイのみ) - AWS CodeDeploy

ファイル: buildspec.yml
※ application-nameはCodeDeployでアプリケーションを作成した後に修正する

version: 0.2
phases:
  build:
    commands:
      - aws deploy push \
        --application-name xxx \
        --s3-location s3://ci-cd-arti/artifact.zip \
        --source .
artifacts:
  files:
    - '**/*'
  base-directory: src

ディレクトリ構成

ci-cd-handson
├── buildspec.yml
└── src
    ├── error.html
    └── index.html

CodeDeployの設定

  • CodeDeployでは、デプロイするリソースの単位であるアプリケーションを作成する
  • どのようにデプロイするかはappspec.ymlで定義する

CodeDeploy用のIAM作成

CodeDeploy用ののRoleを作成し、AWSCodeDeployRoleのpolicyを適用する

aws iam create-role \
  --role-name ci-cd-deploy-role \
  --assume-role-policy-document file://policy_deploy.json

aws iam attach-role-policy \
  --role-name ci-cd-deploy-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole

ファイル: policy_deploy.json

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

アプリケーションの作成

下記の項目を入力し、「アプリケーションの作成」をクリックする

アプリケーション名: ci-cd-handson-app
コンピューティングプラットフォーム: EC2/オンプレミス

buildspec.yml作成の際に保留にしていたapplication-nameを修正する
ファイル名: buildspec.yml

version: 0.2
phases:
  build:
    commands:
      - aws deploy push \
        --application-name ci-cd-handson-app \
        --s3-location s3://ci-cd-arti/artifact.zip \
        --source .
artifacts:
  files:
    - '**/*'
  base-directory: src

デプロイメントグループの作成

以下の内容を設定し、「デプロイグループの作成する」をクリックする

デプロイグループ名

デプロイグループ名の入力: ci-cd-handson-web

サービスロール

サービスロールの入力: arn:aws:iam::xxx:role/ci-cd-deploy-role

環境設定

Amazon EC2 インスタンス を選択
タググループ 1 キー: Name
タググループ 1 値: handson

AWS Systems Manager を使用したエージェント設定

CodeDeployエージェントは手動でインストールしたので、「なし」を選択

デプロイ設定

デプロイメント先のサーバが1台しかないので
CodeDeployDefault.AllAtOnce

Load balancer

ロードバランサーはないので
ロードバランシングを有効にする のチェックを外す

appspec.ymlの作成

CodeDeploy AppSpec File リファレンス - AWS CodeDeploy

ファイル: appspec.yml

version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html

ディレクトリ構成

ci-cd-handson
├── buildspec.yml
└── src
    ├── appspec.yml
    ├── error.html
    └── index.html

実際にデプロイする

CodeCommitにpush

buildspec.ymlやappspec.ymlをCodeCommitにpushする

git add .
git commit -m "fix"
git push origin master

ビルド

  • CodeBuildのビルドプロジェクトの画面に行き、プロジェクト(ci-cd-handson)を選択し、「ビルド開始」をクリックする
  • ビルドの設定が麺が表示されるので、設定は変更せずに「ビルドの開始」をクリックする
  • 「テールログ」で処理が終わるのをログで確認する

アーティファクト用のS3バケットをみるとリソースが格納されている

aws s3 ls s3://ci-cd-arti/

デプロイ

  • CodeDeployのアプリケーションの画面に行き、アプリケーション(ci-cd-handson-app)を選択し、「アプリケーション」のデプロイをクリックする

Create deployment

デプロイ設定

下記の項目を入力し、「デプロイの作成」をクリックする

デプロイグループ: ci-cd-handson-web
リビジョンの場所: ビルドのログ等で確認し、デプロイするリソースを指定する

デプロイのステータスが「成功」になるまで待つ


EC2のグローバルIPにアクセスし、コンテンツが更新されていることを確認する

curl 52.198.167.58
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
            <title>index.html</title>
    </head>
    <body>
        ci-cd-handson index.html<br>
        managed by codecommit<br>
        build by codebuild<br>
        deploy by codedeploy
    </body>
</html>

CodePipelineの設定

CodeCommit、CodeBuild、CodeDeployの処理をCodePipelineでまとめる

パイプラインの作成

パイプラインの設定を選択する

下記の項目を入力し、「次に」をクリックする

  • パイプライン名: ci-cd-handson-ec2
  • ロール名 (自動入力) : AWSCodePipelineServiceRole-ap-northeast-1-ci-cd-handson-ec2

ソースステージを追加する

下記の項目を入力し、「次に」をクリックする

  • ソースプロバイダー: AWS CodeCommit
  • リポジトリ名: ci-cd-handson
  • ブランチ名: master

ビルドステージを追加する

下記の項目を入力し、「次に」をクリックする

  • プロバイダーを構築する: AWS CodeBuild
  • プロジェクト名: ci-cd-handson

デプロイステージを追加する

下記の項目を入力し、「次に」をクリックする
デプロイプロバイダー: AWS CodeDeploy
アプリケーション名: ci-cd-handson-app
デプロイグループ: ci-cd-handson-web

レビュー

これまで設定してきた内容が表示されるので、内容を確認し、「パイプラインを作成する」をクリックする

しばらくすると、パイプラインが作成される

この時点は、コンテンツを変更していないので、前回と同じコンテンが取得される

curl 52.198.167.58
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
            <title>index.html</title>
    </head>
    <body>
        ci-cd-handson index.html<br>
        managed by codecommit<br>
        build by codebuild<br>
        deploy by codedeploy
    </body>
</html>
CodePipelineの動作確認

CodeCommitに変更したコンテンツをPushするとで、自動でコンテンがデプロイされることを確認する

コンテンツを修正し、CodeCommitにPushする
index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
            <title>index.html</title>
    </head>
    <body>
        ci-cd-handson index.html<br>
        managed by codecommit<br>
        build by codebuild<br>
        deploy by codedeploy<br>
        automate by codepipeline
    </body>
</html>
`
```sh
git add 
git commit -m &quot;fix&quot;
git push origin master

CodeCommitにコンテンツがPushされたことを、CodePipelineが検知し、Pilelineが処理が開始される

パイプラインが全て完了した後にコンテンツを確認すると、修正したコンテンツが取得できる

curl 52.198.167.58
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
            <title>index.html</title>
    </head>
    <body>
        ci-cd-handson index.html<br>
        managed by codecommit<br>
        build by codebuild<br>
        deploy by codedeploy<br>
        automate by codepipeline
    </body>
</html>

これで、一通りの処理の自動化が完了!!

参考

EC2 Instance Connect のセットアップ - Amazon Elastic Compute Cloud

コメント