CI/CD実装編

概要編の続きになります

実装の方法をまとめてみました。試しに作ってみたい方などの参考になれば幸いです。

前提

CodePipeLine,CodeDeploy,CodeBuildを使って、EC2インスタンスにデプロイしてみます。

今回はRailsアプリを準備して行いました。使用したいアプリケーションに合わせて設定してみてください。

手順

以下の手順に沿って作っていきます

  • EC2の準備
  • CodeDeployAgentをインスタンスにインストール
  • githubリポジトリの準備
  • appspec.yml・buildspec.ymlなどの準備
  • IAM Roleの作成
  • CodeDeployの作成
  • CodeBuildの作成
  • CodePipelineの作成
  • 実行

EC2の準備

大体は下記を参照に作成しました。

構成例5) Nginx + Puma + Railsを使用しています。

https://qiita.com/rubytomato@github/items/44eb173c0111283a418c

また上記の作り方をした後にインスタンスにタグを設定する必要があります。

これはCodeDeployで設定する必要されたタググループのkeyとvalueが一致するインスタンスのデプロイを行われるためです。

なので、CodeDeployで設定するタグと一緒に設定してください。
今回はkey,value共にdeploygroupと設定しました。

CodeDeployAgentをインスタンスにインストール

公式のユーザガイドに沿ってCodeDeployagentをEC2にインストールします。

CodeDeployのデプロイはagentが実行してくれます。

appspec.ymlに設定などを書くことができ、
compileやwebサーバーの再起動など実行内容はbashファイルで書くことができます。(この後にサンプルを用意してあります。)

また、ユーザーの指定なども可能です。

githubリポジトリの準備

railsアプリを準備し、リポジトリにアップします。
今回は簡単なものにしたかったので、以下のようなものにしました。

  • rails newコマンドで作成
  • topページにHello,Worldと表示される
  • Hello,Worldの文字を変える。(CodeBuildでasset precompileをしたかったので無理やりCSSを入れました。)

IAM Roleの作成

CodeDeployで使用する、IAMRoleを作成します。

ロールの作成を選択肢、「信頼されたエンティティの種類を選択」からユースケースの選択で「CodeDeploy」を選択します。

ロール名を記入し、ロールを作成します。

CodeDeployの作成

次にCodeDeployのアプリケーションとグループを作成します。

グループ作成時に注意してほしい点は

  • ロールは先程作ったIAMを指定する
  • タグはEC2インスタンス作成時に使用したタグを設定する。(key,value共に、”deploygroup”で設定)
インスタンスで設定したタグ

仮に2台目のインスタンスを立ち上げたときにこのタグ設定がされているインスタンスはすべてDeploy対象となるので気をつける必要があります。

appspec.ymlの準備

appspec.ymlはCodeDeployの実行時に、やってほしいことを指定するファイルです。

配置場所はソースディレクトリのルートです。
ここに置いておくことでCodeDeployAgentが自動的に読み込んでくれます。

appspec.ymlの説明の前におおまかなCodeDeployの流れを説明します。
基本的に、今回は画像の左側の流れでデプロイがなされます。

ライフサイクルフック(公式から引用)

黒い部分はDeploy側で行うイベントで強制的になされます。
DwonloadBundleではインスタンス内のCodeDeployAgentがソースコードが配置されているところから、コードをダウンロードします。
このときのダウンロードしたものは、CodeDeployAgent管理下のディレクトリに保存されます。

InstallではDwonloadBundleでダウンロードした内容を指定した場所へコピーします。
この指定はappspec.ymlで行えます。

ライフサイクルイベントについてより詳細は公式ユーザーガイドを参照ください

その上で今回使用するappspec.ymlを見てみます。

appspec.yml

version: 0.0
os: linux
files:
  - source: /
    destination: /home/ec2-user/codepipeline-test
    runas: ec2-user
permissions:
  - object: /
    pattern: "**"
    owner: ec2-user
    group: ec2-user
hooks:
  ApplicationStart:
    - location: scripts/ApplicationStart.bash
      runas: ec2-user


filesで、今回配置するソースコードの場所を指定しています。ここに記述することでinstall時に配置場所のカレントディレクトリが決まります。

permissionsでは、配置するファイルとその権限を指定できます。
公式ユーザーガイドにも出てきますが、特定のファイルごとにpermissionを決めることができます。
配置場所はfilesで指定した場所をカレントとして認識されます。

hooksはさきほどのライフサイクルフックの画像で黒くないところ(DownloadBundle、Install)以外の箇所でbashファイルを実行できます。
ファイルの場所も指定できるので、locationで指定してください。
(./scripts/ApplicationStart.bashに配置してます)

  • ApplicationStop
  • BeforeInstall
  • AfterInstall
  • ApplicationStart
  • ValidateService

今回はApplicationStartでbashを実行します。

ApplicationStart.bash

#!/bin/bash -e
source ~/.bash_profile

cd /home/ec2-user/codepipeline-test

bundle install


appspec.ymlの書き方の詳細は、公式ユーザーガイドを参照ください。
またライフサイクルイベントは今説明したことが基礎にはなりつつ、ロードバランサーが入ったり、デプロイ先がEC2以外だったりすると若干異なるのでそういった場合は公式ユーザーガイドをご参照ください。

CodePipelineの作成

CodeDeployの設定をしていきます。

今回はソースをGithubで使用するので、ソースプロバイダーをgithubにして、認証を済ませます。(画像は認証済みですが「接続」ボタンがあります。)

そのあと、該当のリポジトリを指定し、ブランチをmasterに指定します。こうすることでmasterにマージされる度に、CodePipelineが起動するようになります。

次に、ビルドステージを選択します。

今回はCodeBuildを選択します。
そうすると下記のような画面になるので、「プロジェクトを作成する」をクリックし、作成画面に入ります。

CodeBuildの作成

ビルドの設定をします。
今回はRails6系を使う予定だったので画像の環境で設定しました。

使用するイメージによって、対応しているruntimeが異なるのでこちらをご参考ください

また、buildを通すために環境変数にRAILS_MASTER_KEYを設定する必要があります。ローカルで起動してからconfig/master.key の中身をコピーして,環境変数に設定してください。
詳細

※画像では設定忘れています。「環境」の一番下の追加設定で設定できます。

buildspec.ymlの準備

CodeBuildに必要なbuildspec.ymlを準備します。
配置場所はソースディレクトリのルートです。
buildspec.ymlでは以下を指定できます。

  • 実行環境の設定
  • ビルドコマンド
  • ビルド結果の保存ファイル

今回は下記のファイルを準備しました。
buildspec.yml

version: 0.2

phases:
  install:
    runtime-versions:
      ruby: 2.6
      nodejs: 10
  pre_build:
    commands:
      - rbenv install 2.6.3 && rbenv global 2.6.3
      - bundle install
      - bundle exec rake webpacker:yarn_install
  build:
    commands:
      - echo Build Start
      - bundle exec rake assets:precompile RAILS_ENV=production
artifacts:
  files:
    - ./**/*

phaseではruntimeの指定や実行するコマンドを指定できます。

artifactsでは保存するファイルの指定を行う事ができます。

buildspec.ymlを見ていくと
rbenvでrubyのマイナーバージョンのインストール、webpackerのインストールで環境を整えています

bundle install
bundle exec rake webpacker:yarn_install

環境を整え終えたら、assets:precompileでCSSとJSのファイルを1つのファイルとしてまとめます。
最後にbuildを終えたら、CodeBuildがビルド内容をS3に保存してくれます。
今回はCodePipeLineを使用しているのでCodePipeLine管理のS3直下に保存されています。
これらはCodePipeLineを作成した際に自動的に作成されます。(下記はCodePipeLine実行後の画像になります)

※CodeBuildを単体で使う場合は別のS3バケットに保存されます。詳細は公式ユーザーガイドをご参考ください

CodePipelineの続き(デプロイステージ)を設定

ビルドを設定したら、最後にデプロイステージを設定します。

先程作成したCodeDeployのアプリケーションとグループを指定します。

いざ、デプロイ

上記で設定が終わると、デプロイが走ります。

成功すると下記のような画面になります。

これでCodePipeline完成です。masterにマージされる度にCodePipelineが走るはずです。

CodeDeployのエラーログの場所

上記のように設定されていればうまくいくはずですが、もしハマってしまった場合は下記を確認してみてください

# CodeDeployAgentのログ
/var/log/aws/codedeploy-agent/codedeploy-agent.log

# Application.bashなどのbashの実行ログ
/opt/codedeploy-agent/deployment-root/{デプロイグループID}/d-{デプロイID}/logs

最後に

いかがでしたでしょうか?
デプロイの工数がまるっと減り、リリースへのストレスも軽減されます。
ぜひ、試してみてください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA