Top View


Author Choi Jiho

TerraformでAWS CodePipeline(ECR pushで発火) + CodeBuildを作る

2021/12/10

TerraformでAWS CodePipeline(ECR pushで発火) + CodeBuildを作る

AWS CodePipeline記事を探してみるとGithub pushで発火はいろいろありますが、ECR pushで発火はあまりありませんでした。ですから書いて見ました。

結論

  • CodePipelineのCodeBuildのbuildspec.ymlをS3を置く場合は versioningenabled することが必須です
  • ECRで変更を検知してCodePipelineに知らせるCloudWatchイベントルールが必須 を認識することが大事
    • AWSコンソール上でポチポチでECRをsourceにするCodePipelineを作ると 自動 で作られてしまって認識が難しかった
    • 参考資料です
... 
コンソールを使用してパイプラインを作成または編集すると、CodePipeline は、リポジトリで変更が生じた場合にパイプラインを開始する CloudWatch イベントルールを作成します。
...

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/action-reference-ECR.html から
  • docker imageをbuildするところのCPUアーキテクチャーが問題になりますから、注意が必要です
    • MAC(M1)でdocker imageをbuildしてECRにpushしたら、AWS上でdocker imageが使われる時エラーになる可能性があります
    • buildしたところのCPUアーキテクチャーと使われるところのCPUアーキテクチャーが違うと動けません
    • 筆者はWindowsユーザーです

構成

ディレクトリ紹介

  • Terraformスクリプトがいる ./terraform
  • CodeBuildで必要なファイルを集めた ./codebuild

ファイル紹介

GitHubに全体コード公開してます。
https://github.com/fusic/tb_pipeline_source_ecr

./terraform/provider.tf

Terraformのproviderのまとめです。

./terraform/variables.tf

Terraformで全体的に使いたい変数を定義しました。

./terraform/main.tf

./modules で定義されたAWSリソースたちを束ねるところです。

./terraform/modules/cw_events/main.tf

  • ECRにpushしたらCodePipelineに知らせるCloudWatchイベントルールです。
    • この設定がないとECRにpushしてもCodePipelineで何も起こりません。

./terraform/modules/cd_pipeline/main.tf

  • Source で名付けた stageaction にCodePipelineを発火するECRのリポジトリ名とタグ名を設定しました。
  • Source で名付けた stageaction にCodeBuildのbuildspec.ymlがあるS3を設定しました。CodeBuildのbuildspec.yml担当S3がCodePipelineで管理されるようにしてますが、CodePipelineから外してCodeBuild単独でbuildspec.yml担当S3を参照する形にしても問題ないと思います。
resource "aws_codepipeline" "main" {
  name     = var.app_name
  role_arn = var.iam_role_codepipeline_arn

  artifact_store {
    type     = "S3"
    location = var.s3_pipeline_artifact_id
  }

  stage {
    name = "Source"
    action {
      name             = "Source"
      category         = "Source"
      owner            = "AWS"
      provider         = "ECR"
      version          = "1"
      run_order        = 1
      output_artifacts = ["ecr_source"]

      configuration = {
        RepositoryName = var.ecr_web_name
        ImageTag       = var.app_env # stgとかprdとか
      }
    }

    # https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-S3.html
    action {
      category         = "Source"
      configuration    = {
        "PollForSourceChanges" = "false"
        "S3Bucket"             = var.buildspec_bucket_name
        "S3ObjectKey"          = "build.zip"
      }
      name             = "s3_source"
      output_artifacts = ["s3_source"]
      owner            = "AWS"
      provider         = "S3"
      run_order        = 1
      version          = "1"
    }
  }

  stage {
    name = "Build"
    action {
      name             = "Build"
      category         = "Build"
      owner            = "AWS"
      provider         = "CodeBuild"
      version          = "1"
      run_order        = 2
      input_artifacts  = ["s3_source"]
      configuration    = {
        ProjectName = var.app_name
      }
    }
  }
}

./terraform/modules/cdb/main.tf

./terraform/modules/cw_events/event_pattern.tpl

CodePipelineにECRがpushされたことを知らせることが大事です。 検知したいdocker imageのtagを指定できます。

{
  "source": [
    "aws.ecr"
  ],
  "detail": {
    "action-type": [
      "PUSH"
    ],
    "image-tag": [
      "prd"
    ],
    "repository-name": [
      "${repository_name}"
    ],
    "result": [
      "SUCCESS"
    ]
  },
  "detail-type": [
    "ECR Image Action"
  ]
}

./terraform/modules/cw_logs/main.tf

CodeBuildで使うログです。ないとAWSコンソール上でもCodeBuildのログが見れません。作ることをお勧めします。

./terraform/modules/ecr/main.tf

docker imageをpushするECRを作ります。

./terraform/modules/iam 配下

もろもろ必要なIAM RoleやIAM Policyを作ります。

./terraform/modules/s3/main.tf

CodePipelineのCodeBuildのbuildspec.ymlをS3を置く場合は versioningenabled することが必須です。

...
resource "aws_s3_bucket" "codebuild_buildspec" {
  bucket        = "${var.app_name}-codebuild-buildspec"
  acl           = "private"
  force_destroy = true

  # codepipelineの正確な参照のために必要
  versioning {
    enabled = true
  }
}

./codebuild/buildspec.yml

./codebuild/update_codebuild_files.sh

buildspec.ymlをzipにしてS3にアップロードするコマンドのまとめです。

./deploy_by_pushing_docker.sh

ECRにログインする、docker imageをbuildする、ECRにpushするコマンドのまとめです。 実行前に設定する変数がありますが、下の exportでshellで使う環境変数を設定する で説明します。

#!/bin/bash

ECR_REPO=$AWS_SP_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com

# ECRログイン
aws ecr get-login-password \
  --region ap-northeast-1 \
  --profile $AWS_SP_PROFILE_NAME \
| docker login \
  --username AWS \
  --password-stdin $ECR_REPO

#### ruby(web) docker image
WEB_CONTAINER_NAME=src-ecr
ECR_WEB_URI=$ECR_REPO/$AWS_SP_APP_NAME:$AWS_SP_APP_ENV

docker build -t $ECR_WEB_URI . -f ./docker/production/Dockerfile
docker push $ECR_WEB_URI

実行手順

aws profile設定します

profile名は src-ecr-prd にしてください。terraformで参照してます。
AWS Access Key IDAWS Secret Access Key は保有しているものを入力してください。

aws configure --profile src-ecr-prd
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: ap-northeast-1
Default output format [None]:

terraformを実行

APP_ROOT/terraform
terraform init
terraform apply

exportでshellで使う環境変数を設定する

AWSコンソール上でアカウントIDを確認してから下の AWS_SP_ACCOUNT_ID に設定してください。

export AWS_SP_PROFILE_NAME=src-ecr-prd
export AWS_SP_ACCOUNT_ID=xxxxx
export AWS_SP_APP_NAME=src-ecr-prd
export AWS_SP_APP_ENV=prd

Codebuild用buildspecとCodedeploy用ファイルをzipでアップロード

cd APP_ROOT/codebuild
sh update_codebuild_files.sh

ECRへdocker imageたちをbuildしてpushする

cd APP_ROOT
sh deploy_by_pushing_docker.sh
Choi Jiho

Choi Jiho

Company : Fusic CO., LTD Program Language : PHP, Go, Ruby