GitLab + CodePipeline + CodeDeploy で SpringBootApp を自動デプロイ
GitLab は CodePipeline のトリガーに指定することができないので S3 を噛ませて Codeシリーズを起動するサンプル。
- 修正内容を GitLab に push
- GitLab CI/CD で S3 にプロジェクトをアップロード
- CodePipeline で S3 のアップロードを検知
- CodeBuild で S3 にアーティファクトを保存
- CodeDeploy で EC2 インスタンスにデプロイ
の流れを試してみる。
手順
- SpringBoot のプロジェクトを作成
- IAMユーザとS3バケットの作成
- GitLab CI/CD の設定
- デプロイ用EC2インスタンスを作成/設定
- CodeBuild の設定
- CodeDeploy の設定
- CodePipeline の設定
SpringProject に加えて追加するファイルは以下のように配置にする。
.
├─ .gitlab-ci.yml
├─ buildspec.yml
├─ appspec.yml
└─ hooks
└─ restart.sh
各役割をまとめると・・・
ファイル名 | 役割 |
---|---|
.gitlab-ci.yml | GitLabのCI設定ファイル。今回はS3にアップロードする手順を記載する |
buildspec.yml | CodeBuildでSpringBootをビルドしてJarを生成する手順を記載する |
appspec.yml | CodeDeployで生成したJarをEC2に配置する手順を記載する |
restart.sh | CodeDeployでデプロイが完了した後にサービスの再起動などを行うスクリプト |
では早速始めよう。
SpringBoot のプロジェクトを作成
Spring Initializr でプロジェクトを作成する。
今回は以下の条件で作成してみた。
key | value |
---|---|
Project | Gradle Project |
Language | Java |
Spring Boot | 2.2.5 |
Project Metadata - Group | com.example |
Project Metadata - Artifact | cisample |
Options - Name | cisample |
Options - Description | cisample project for Spring Boot |
Options - Package name | com.example.cisample |
Options - Packaging | Jar |
Options - Java | 11 |
Dependencies | Spring Web |
設定が終わったら Generate で作成/DLして展開しておく。
簡単なテキストを表示するために CisampleApplication.java
を変更しておく。
package com.example.cisample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+@RestController
@SpringBootApplication
public class CisampleApplication {
public static void main(String[] args) {
SpringApplication.run(CisampleApplication.class, args);
}
+ @RequestMapping("/")
+ String home() {
+ return "Hello World ver 1.0";
+ }
}
展開できたらコンテナを起動して動作確認をする。
※ 面倒ならスキップしてもOK
# コンテナの起動/接続
docker run --rm -it -p 8080:8080 -v $(pwd):/app openjdk:11 bash
# jarのビルド
cd /app
./gradlew build
# jarの実行
java -jar ./build/libs/cisample-0.0.1-SNAPSHOT.jar --server.port=8080
ブラウザから http://localhost:8080
にアクセスして画面が表示されれば成功。
コンテナは停止してOK
次にS3バケットとIAMユーザを作成する。
S3バケットとIAMユーザの作成
S3にプロジェクトをzip形式で保存するためのS3バケットを作成する。S3はバージョニングを有効にしておくこと。
また、アップロード権限を持ったIAMユーザも作成する。
- AWSコンソールにログイン
- S3バケットの作成
- サービスから S3 を検索
- バケットを作成
- バケット名を入力 ex)
cisample-backet
- リージョンを入力 ex)
ap-northeast-1
- パブリックアクセスをすべてブロックをチェック
- バケット作成ボタンでバケットを作成
- 作成したバケットを選択
- プロパティタブ
- バージョニング
- バージョニングの有効化を選択
- 保存
- IAMユーザの作成
- サービスから IAM を検索
- 左メニューのユーザー
- ユーザーを追加ボタン
- ユーザー名を入力 ex)
cisample-user
- プログラムによるアクセスをチェック
- 次のステップ
- 既存のポリシーを直接アタッチ
-
AmazonS3FullAccess
を検索してチェック - 次のステップ
- タグは任意で設定して次のステップ
- ユーザーの作成ボタン
- アクセスキーIDとシークレットアクセスキーを控えておく
S3バケットとIAMユーザができた。
次に公開用のデプロイ先インスタンスを作成する。
デプロイ用EC2インスタンスを作成/設定
httpアクセスできるネットワークにインスタンスを作成してPublicIPを付与する。
jarが起動できればなんでもいいので、細かい手順はよしなに作成する。
デプロイ時に使うので条件として2つ
- デプロイグループの設定で使うのでタグを設定する ex) key:
DeployGroup
val:cisample
- ロールに
S3FullAccess
をつけておく ※必要に応じてアクセス制限をつけてね
作成したらsshで接続して設定する。
# CodeDeploy用エージェントをインストール & 起動
sudo -i
yum update -y && yum install -y ruby wget
wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
chmod +x ./install
./install auto
systemctl enable codedeploy-agent
systemctl start codedeploy-agent
# jar(配置予定地)を起動するサービスを作成して権限を付与しておく
mkdir /usr/local/app
cat <<EOS > /usr/local/app/start.sh
#!/bin/sh
java -jar /usr/local/app/cisample-0.0.1-SNAPSHOT.jar --server.port=80
EOS
chmod +x /usr/local/app/start.sh
cat <<EOS > /etc/systemd/system/cisample.service
[Unit]
Description = ci sample daemon
[Service]
ExecStart = /usr/local/app/start.sh
Restart = always
Type = simple
[Install]
WantedBy = multi-user.target
EOS
systemctl enable cisample
# 適当な場所に java をインストールする
cd /opt
wget https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_linux-x64_bin.tar.gz
tar -zxf openjdk-11.0.2_linux-x64_bin.tar.gz
ln -s /opt/jdk-11.0.2/bin/java /usr/bin/java
# インストールの確認
java -version
とりあえず一旦Javaが動けばOK
次にプロジェクトをアップロードする GitLab CI の設定を追加する。
GitLab CI/CD の設定
pushを検知したら AWS の S3 にプロジェクトの内容をアップロードする処理を追加する。
AWSCLIの認証情報はファイルに書いてしまうと悪い人に見つかってしまうので、GitLab側に変数として値を保持しておいて実行時に参照するように設定しておく。
- GitLabにログイン
- テスト用のリポジトリを作成
- さっきのプロジェクトをpushしておく
- プロジェクトのページに移動
- 左メニューの 設定 > CI/CD
- Variables メニューを展開
- 以下の値を設定して変数を保存する
type | key | val |
---|---|---|
Variable | aws_access_key_id | IAMユーザのアクセスキー |
Variable | aws_secret_access_key | IAMユーザのシークレットアクセスキー |
Variable | backet_name | 作成したバケット名 |
GitLab CIの設定ファイルを追記する。
image: "alpine:3"
stages:
- build
- push
build:
stage: build
script:
- apk --no-cache add zip
- zip -qr src.zip *
- zip -u src.zip .gitlab-ci.yml
artifacts:
paths:
- src.zip
deploy:
stage: push
script:
- AWS_CLI_VERSION="1.18.31"
- |-
apk --no-cache add \
python \
py-pip \
mailcap
- pip install --upgrade awscli==$AWS_CLI_VERSION python-magic
- mkdir ~/.aws
- |-
cat << EOS > ~/.aws/config
[default]
region = ap-northeast-1
output = json
EOS
- |-
cat << EOS > ~/.aws/credentials
[default]
aws_access_key_id = ${aws_access_key_id}
aws_secret_access_key = ${aws_secret_access_key}
EOS
- aws s3 cp ./src.zip s3://${backet_name}/src.zip
apline で awscli の2系がうまく動かなかったので1系で動かす。
バージョンはこちらで確認する。
独自のRunnerを使いたい場合は別途設定をすること。
作成したらGitLabにpushしてパイプラインを眺めましょう。
ステータス: 成功 が確認できたらS3に src.zip
があることを確認する。
続いてこの src.zip
をビルドするためにCodeBuildの設定に進もう。
CodeBuild の設定
ビルドするコンピューティングリソースなど、ビルドの設定を作成する。
- サービスから CodeBuild を検索
- ビルドプロジェクトを作成する
- プロジェクト名を入力 ex)
cisample-build
- 送信元をソースプロバイダを
Amazon S3
に設定 - バケット名を入力 ex)
cisample-backet
- S3 オブジェクトキーまたは S3 フォルダ を入力 ex)
src.zip
- 環境イメージにマネージド型イメージを選択
- OSに Amazon Linux 2 を選択
- ランタイムの Standard を選択
- イメージとバージョンは最新を選択
- 環境タイプは Linux を選択
- サービスロールは新しいサービスロールを選択
- ロール名を入力 ex)
CiSampleBuildRole
- ビルド仕様は buildspec ファイルを使用するを選択
- アーティファクトタイプは Amazon S3 を選択
- バケット名を入力 ex)
cisample-backet
- 名前を入力 ex)
artifact.zip
- アーティファクトのパッケージ化はZipを選択
- CloudWatch Logs をチェック
- ビルドプロジェクトを作成する
作成したロールに権限を追加する
- サービスから IAM を検索
- 左メニューのロールを選択
- 作成したロールを検索する ex)
CiSampleBuildRole
- ポリシーをアタッチします
-
AmazonS3FullAccess
をチェックしてポリシーのアタッチ
次にビルド内容の定義ファイルを作成する。
version: 0.2
phases:
build:
commands:
- echo start build at `date`
- ./gradlew build
artifacts:
type: zip
files:
- ./appspec.yml
- ./hooks/restart.sh
- ./build/libs/cisample-0.0.1-SNAPSHOT.jar
name: artifact
discard-paths: yes
appspec.yml
と hooks/restart.sh
は後ほど追加するので気にしない。
これでビルド設定ができた。
ビルドの開始でビルドを実行して、ステータス: 成功 なるまで待つ。
ビルドに成功したら S3に artifact.zip
があることを確認して、デプロイの設定にはいる。
CodeDeploy の設定
push されたプロジェクトをビルドするまでできたので、ビルド結果をデプロイする部分を作成する。
手順は4段階
- デプロイ用ロールを作成
- デプロイ用アプリケーションを作成
- デプロイ設定の作成
- デプロイ設定ファイルの追加
まずはデプロイ用ロールを作成する。
- サービスから IAM を詮索
- ロールを選択
- ロールの作成
- AWS サービス > CodeDeploy > CodeDeploy を選択して次のステップ
-
AWSCodeDeployRole
が表示されている状態で次のステップ - タグを任意で設定する
- ロール名を入力する ex)
CisampleDeployRole
- ロールの作成
次にデプロイ用アプリケーションを作成する。
- サービスから CodeDeploy を検索
- アプリケーションの作成
- アプリケーションの名前を入力 ex)
cisample-app
- コンピューティングプラットフォームを選択 ex)
EC2/オンプレミス
- アプリケーションの作成
続いてデプロイの設定を作成する。
- デプロイグループの作成
- デプロイグループの作成
- デプロイグループ名を入力 ex)
cisample-dg
- サービスロールのarnを入力 ex)
arn:aws:lam::xxxxxxxxxxxx:role/CisampleDeployRole
- デプロイタイプを選択 ex)
インプレース
- 環境設定は
Amazon EC2 インスタンス
を選択 - タグは key:
DeployGroup
val:cisample
を追加 - 一意に一致したインスタンス が 1 になっていることを確認する
- デプロイ設定は
CodeDeployDefault.AllAtOnce
を選択 - ロードバランシングを有効にする のチェックを外す
- デプロイグループの作成
- デプロイの作成
- デプロイの作成
- デプロイグループを入力 ex)
cisample-dg
- リビジョンタイプは
Amazon S3
を選択 - リビジョンの場所を入力 ex)
s3://cisample-backet/artifact.zip
- リビジョンファイルの種類は
.zip
を選択 - デプロイの作成
このままでは設定ファイルがなくてデプロイが失敗してしまうので、設定ファイルを追加する。
version: 0.0
os: linux
files:
- source: /
destination: /usr/local/app
hooks:
AfterInstall:
- location: restart.sh
timeout: 180
新jarのデプロイ後に再起動するスクリプトも追加しておく
#!/bin/sh
sudo systemctl restart cisample
これでデプロイが通ってEC2インスタンスにビルド結果の artifact.zip
の内容が展開される。
サービスも起動しているはずなのでブラウザからEC2インスタンスにアクセスして Hello World ver 1.0
が表示されることを確認する。
最後に S3の更新を検知して CodeBuild と CodeDeploy を起動するための CodePipelineを作成する。
CodePipeline の設定
- サービスから CodePipeline を検索
- パイプラインを作成する
- パイプライン名を入力 ex)
cisample-pipeline
- 新しいサービスロールを選択
- ロール名を入力 ex)
CiSamplePipelineRole
- 高度な設定を展開する
- アーティファクトストアは カスタムロケーション を選択
- S3バケット名を入力 ex)
cisample-backet
- 次に
- ソースプロバイダーに
Amazon S3
を選択 - バケット名を入力 ex)
cisample-backet
- S3 オブジェクトキーを入力 ex)
src.zip
- 検出オプションを変更する は
Amazon CloudWatch Events
を選択 - 次に
- プロバイダーを構築するは
AWS CodeBuild
を選択 - リージョンを選択 ex)
アジアパシフィック(東京)
- プロジェクト名を入力 ex)
cisample-build
- 環境変数は今回は未設定で次に
- デプロイプロバイダーは
AWS CodeDeploy
を選択 - リージョンを選択 ex)
アジアパシフィック(東京)
- アプリケーション名を入力 ex)
cisample-app
- デプロイグループを入力 ex)
cisample-dg
- 次に
- パイプラインを作成する
これでS3の変更を検知して一連の流れが通るはず。
Pipelineが成功したらインスタンスにアクセスして
Hello World ver 1.0
が出ることを確認する。
できた!!
おわりに
今回の手順で以下のリソースができているはず。
- S3バケット
- IAMユーザ
- IAM Role
- IAM ポリシー
- EC2 Instance
- CodeBuild
- CodeDeploy
- CodePipeline
不要な場合は削除しちゃいましょ。
画像がないのでそのうちCLI操作のコマンドでも確認してみましょうかね。