BitBucketPipelines で image の push を行っていましたが、cpu がマルチプラットフォームに対応しておらず、x86_64 のみしか対応していないため、イメージの push を CodeBuild で行うことにしました。 arm64 で ECS タスクを実行するとコストが 20%落ち、使い方によってはパフォーマンスが向上するらしい。
コストが 20%ぐらい落ちた。パフォーマンスはまだサービスインしてないため分からない
data "aws_region" "this" {}
resource "aws_codebuild_project" "ecr" {
badge_enabled = false
build_timeout = 20 // 20分
concurrent_build_limit = 1 // 並列実行数
encryption_key = "arn:aws:kms:${data.aws_region.this.name}:${data.aws_caller_identity.self.account_id}:alias/aws/s3"
name = "ecr-build-${terraform.workspace}"
project_visibility = "PRIVATE"
queued_timeout = 480
service_role = aws_iam_role.codebuild_role.arn
tags = {
Environment = "${terraform.workspace}"
Name = "ecr-build-${terraform.workspace}"
}
environment {
compute_type = "BUILD_GENERAL1_SMALL" // 1vCPU, 3.75GB
image = "aws/codebuild/amazonlinux2-aarch64-standard:3.0"
type = "ARM_CONTAINER"
image_pull_credentials_type = "CODEBUILD"
privileged_mode = true // dockerコマンドを叩く場合は必須
}
artifacts {
type = "NO_ARTIFACTS"
}
source {
location = "bucketname/buildspec/"
buildspec = "codebuild/${terraform.workspace}/buildspec.yml"
report_build_status = false
type = "S3"
}
}
#------------------------------------------------------------#
# code build role
#------------------------------------------------------------#
data "aws_iam_policy_document" "codebuild_role" {
statement {
sid = "1"
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = [
"codebuild.amazonaws.com"
]
}
}
}
resource "aws_iam_role" "codebuild_role" {
name = "codebuild-ecr-build-${terraform.workspace}"
assume_role_policy = data.aws_iam_policy_document.codebuild_role.json
}
#------------------------------------------------------------#
# code build atached policy s3 access
#------------------------------------------------------------#
resource "aws_iam_policy" "codebuild_s3_access_policy" {
name = "codebuild-s3-access-policy-${terraform.workspace}"
description = "codebuild_s3_access_policy"
policy = <<EOT
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::bucketname/buildspec/",
"arn:aws:s3:::bucketname/buildspec/*"
]
},
{
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::bucketname"
],
"Action": [
"s3:ListBucket",
"s3:GetBucketAcl",
"s3:GetBucketLocation"
]
}
]
}
EOT
}
resource "aws_iam_role_policy_attachment" "codebuild_s3_access_policy" {
role = aws_iam_role.codebuild_role.name
policy_arn = aws_iam_policy.codebuild_s3_access_policy.arn
}
#------------------------------------------------------------#
# code build atached ecr push policy
#------------------------------------------------------------#
resource "aws_iam_policy" "codebuild_ecr_push_policy" {
name = "codebuild-ecr-push-policy-${terraform.workspace}"
description = "codebuild_ecr_push_policy"
policy = <<EOT
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ecr",
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:CompleteLayerUpload",
"ecr:GetAuthorizationToken",
"ecr:InitiateLayerUpload",
"ecr:PutImage",
"ecr:UploadLayerPart"
],
"Resource": "*"
}
]
}
EOT
}
resource "aws_iam_role_policy_attachment" "codebuild_ecr_push_policy" {
role = aws_iam_role.codebuild_role.name
policy_arn = aws_iam_policy.codebuild_ecr_push_policy.arn
}
#!/bin/bash
env=$1
# codebuildの実行結果を取得する
build_output=$(aws codebuild start-build --project-name nnslink-ecr-build-${env})
build_id=$(echo "$build_output" | jq -r '.build.id')
count=0
while : ; do
# codebuildの状態を取得する
build_status=$(aws codebuild batch-get-builds --ids $build_id --query 'builds[0].[buildStatus]' --output text)
if [ "$build_status" = "SUCCEEDED" ]; then
echo "done!"
break
elif [ "$build_status" = "FAILED" ]; then
exit 1
fi
# 10分以上かかったら失敗扱いで終了
count=$((count+1))
if [ $count -gt 20 ]; then
echo "[timeout] check aws codebuild console for more detail."
exit 1
fi
echo "prosessing..."
sleep 30
done
exit 0
definitions:
steps:
- step: &ECR-push
name: ECR push
image: atlassian/pipelines-awscli:latest
trigger: manual
oidc: true
script:
- export AWS_WEB_IDENTITY_TOKEN_FILE=$(pwd)/web-identity-token
- echo $BITBUCKET_STEP_OIDC_TOKEN > $(pwd)/web-identity-token
- aws s3 sync ${BITBUCKET_CLONE_DIR}/image/ s3://bucketname/buildspec/ --delete
- /bin/bash ./scripts/codebuild.sh ${ENV}
pipelines:
custom:
image-update:
- step:
<<: *ECR-push
deployment: Staging
- step:
<<: *ECR-push
deployment: Production