CI/CDツールはAWSのCodePipelineを軽く使った事があるので、一応備忘録として書いておく。
(jenkisは使った事がないが、別途見ておきたい)
CodePipeline
基本的には
- コード管理であるgit (CodeCommitやGitHub)
- ビルド、テストを行う(CodeBuildもしくはJenkis。ECRにPushする)
- デプロイはCodeDeployでECSでリリースなど
のセットをpipelineで作成する。
起動トリガーはgitへのPushやS3へのファイルアップロード等が選択可能
途中で停止させて、ボタンを押さないと進まないようにすることも可能
設定方法
terraformで作成する場合を想定する。Formationでも大差はない、はず?
少し前のバージョンで書いたコードなので今のterraformで使う場合は修正が必要か。
まずはaws_codebuild_projectでビルドプロジェクトを作成する。
var.やlocal.は変数設定している箇所。
ECRやCodeCommitのリポジトリは既に存在しているという前提。
(大量に作るのでない限り、リポジトリはわざわざIaCで管理する必要なさそうな気がする)
AWS公式も参照
resource "aws_codebuild_project" "codebuild_project" {
name = local.CodeBuildName
service_role = "arn:aws:iam::${local.account}:role/CodeBuildServiceRole"
artifacts {
type = "NO_ARTIFACTS"
}
# ビルド環境の設定
environment {
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/standard:2.0"
type = "LINUX_CONTAINER"
image_pull_credentials_type = "CODEBUILD"
# ここで設定した値をbuildspeck.ymlで使える
environment_variable {
name = "AWS_DEFAULT_REGION"
value = "ap-northeast-1"
}
environment_variable {
name = "AWS_ACCOUNT_ID"
value = local.account
}
# ECRは事前に作成
environment_variable {
name = "ECR_REPOSITORY_NAME"
value = local.ECRName
}
environment_variable {
name = "SYSTEM_ID"
value = var.SystemID
}
environment_variable {
name = "CONTAINER_NAME"
value = local.ContainerName
}
privileged_mode = "true"
}
# クラウドウォッチにログ出力する場合
logs_config {
cloudwatch_logs {
group_name = local.CloudWatchLogName
status = "ENABLED"
stream_name = var.SystemID
}
}
// gitHubの場合は別途参照
source {
type = "CODECOMMIT"
location = "https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/${var.GitReposName}"
}
}
ビルドするマシンは公式から選択
イメージも公式を見ると良い。
ここを見るとaws/codebuild/standard:2.0は時代遅れっぽい。
CodeCommitをソースにしているが、GitHubの場合はパラメータストアにトークン保存した上で以下のようにする。
CodeCommitも悪くはないのだが、本番とテストでアカウントが分かる事を考えるとgitHubが使えるならそちらで良い気はする。
(専用線経由でアクセスできるからCodeCommitを使いたい、というような要望はあるかもしれないけど)
source {
type = "GITHUB"
location = var.github_repository_location
git_clone_depth = 1
report_build_status = true # 結果をリポジトリに通知する場合はtrueを指定
}
そして、このビルド設定をCodePipelineに適用する。
resource "aws_codepipeline" "codepipeline" {
name = local.CodePipelineName
# ロールは事前に作成されているとする
role_arn = "arn:aws:iam::${local.account}:role/CodePipelineServiceRole"
# S3の名前は自分の所有しているものにする
artifact_store {
location = "s3_codepipeline"
type = "S3"
}
# Source,Build,Deployの順番で実行されるので、設定していく。
stage {
name = "Source"
action {
name = "Source"
category = "Source"
owner = "AWS"
provider = "CodeCommit"
version = "1"
output_artifacts = ["source_output"]
configuration = {
RepositoryName = var.GitReposName
BranchName = "master"
PollForSourceChanges = "false" # CloudWatchで検出するのでfalseにする
}
}
}
stage {
name = "Build"
action {
name = "Build"
category = "Build"
owner = "AWS"
provider = "CodeBuild"
input_artifacts = ["source_output"]
output_artifacts = ["build_output"]
version = "1"
configuration = {
ProjectName = local.CodeBuildName
}
}
}
# ECSにデプロイ
stage {
name = "Deploy"
action {
name = "Deploy"
category = "Deploy"
owner = "AWS"
provider = "ECS"
input_artifacts = ["build_output"]
version = "1"
configuration = {
ClusterName = local.ECSClusterName
ServiceName = local.ECSServiceName
FileName = "imagedefinitions.json"
}
}
}
}
ソースコードの検知はCloudWatchを使う
resource "aws_cloudwatch_event_rule" "event_rule" {
name = local.CloudWatchEventName
description = "Amazon CloudWatch Events rule to automatically start your pipeline when a change occurs in the AWSCodeCommit."
event_pattern = <<-JSON
{
"source": [
"aws.codecommit"
],
"detail-type": [
"CodeCommit Repository State Change"
],
"resources": [
"arn:aws:codecommit:ap-northeast-1:${var.git_account}:${var.GitReposName}"
],
"detail": {
"event": [
"referenceCreated",
"referenceUpdated"
],
"referenceType": [
"branch"
],
"referenceName": [
"master"
]
}
}
JSON
depends_on = ["aws_codepipeline.codepipeline"]
}
resource "aws_cloudwatch_event_target" "event_target" {
rule = aws_cloudwatch_event_rule.event_rule.name
target_id = aws_cloudwatch_event_rule.event_rule.name
arn = aws_codepipeline.codepipeline.arn
role_arn = "arn:aws:iam::${local.account}:role/StartPipelineExecutionRole"
}
これでgit上のファイルが変わった場合に動くように出来る。
特定のファイルが変わった場合のみビルド場合は.shでコントロールするといった方法があった。
機能追加されてフィルタをかけられるようになっている、というような情報は知らない。
S3へのファイルをアップロードをトリガーとする場合は以下のようにソースを設定する。
こちらはkeyでファイル名を指定できるので、例えばxyz.warがアップロードされるとpipelineが走る、というように出来る。
resource "aws_cloudwatch_event_rule" "event_rule" {
name = local.CloudWatchEventName
description = "Amazon CloudWatch Events rule to automatically start your pipeline when a change occurs in the AWSCodeCommit."
event_pattern = <<-JSON
{
"source": [ "aws.s3" ],
"detail-type": [ "AWS API Call via CloudTrail" ],
"detail": {
"eventSource": [ "s3.amazonaws.com" ],
"eventName": [ "PutObject", "CompleteMultipartUpload", "CopyObject" ],
"requestParameters": {
"bucketName": [ "s3-codepipeline" ],
"key": [ "${local.CodePipelineName}/${var.warfile}" ]
}
}
}
JSON
depends_on = ["aws_codepipeline.codepipeline"]
}
これらのAWS上の設定をした上で、実際にビルドするには設定ファイルbuildspec.ymlがgit上に必要となる。
version: 0.2
env:
# Dockerhubへのアクセストークンをパラメーターストアから読み込んでおく
parameter-store:
DOCKER_USER: docker-hub-user
DOCKER_TOKEN: docker-hub-token
phases:
# 自動テストを行う場合はinstallセクションのcommandsでテストツールインストール
install:
runtime-versions:
docker: 18
# ログイン等、ビルド前の準備
# AWS_ACCOUNT_ID等はterraform側で設定した値
pre_build:
commands:
- echo Logging in to Amazon ECR ...
- $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
- REPOSITORY_URI=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPOSITORY_NAME
- IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- echo $DOCKER_TOKEN | docker login -u $DOCKER_USER --password-stdin
build:
# ここではS3から.warをコピーしてdockerImageを作成する想定
commands:
- aws s3 cp s3://s3-codepipeline/$PIPELINE_NAME/$SYSTEM_WAR ./$SYSTEM_WAR
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t $REPOSITORY_URI:latest .
- echo docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
post_build:
# イメージをECRにプッシュする
commands:
- echo Build completed on `date`
- echo Pushing the Docker image...
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
- printf '[{"name":"%s","imageUri":"%s"}]' $CONTAINER_NAME $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$ECR_REPOSITORY_NAME:$IMAGE_TAG > imagedefinitions.json
artifacts:
files: imagedefinitions.json
これでビルドが動くがDockerイメージを作成しているので、Dockerfileが必要なので
例えばtomcat9+jdk8のイメージにwarファイルを追加するようなものを用意して配置しておく。
#
# VERSION 0.0.1
#
FROM tomcat:9.0.41-jdk8-corretto
LABEL maintainer="test@test.com"
ARG MEM_MX="2048m"
ARG MEM_MS="64m"
ARG APP_WARFILE="./xyz.war"
RUN echo $CATALINA_HOME
RUN echo $CATALINA_HOME/webapps/
ADD ./app/conf/server.xml $CATALINA_HOME/conf/server.xml
ENV CATALINA_OPTS "-server -Xmx$MEM_MX -Xms$MEM_MS
# check Web application
ADD $APP_WARFILE $CATALINA_HOME/webapps
WORKDIR $CATALINA_HOME/bin
これで一連の動きは出来る。
テストレポート等を作る場合はこことか公式を参考に。
buildでテストを実行するコマンドを書いた上でreportsセクションを追加してやればよい。
途中で承認処理を付ける場合
公式
おわり