はじめに
2024年3月に、AWS CodeBuildの実行環境としてAWS Lambdaが使用できるようになった。
CodeBuildが実行されるコンテナのベースイメージとしてカスタムイメージは以前から使えたが、上記アップデートによりEC2 or Lambdaと、マネージドイメージ or カスタムイメージといった組み合わせが定義できるようになっている。
それぞれ用途に応じて何を選択するかを決めれば良いが、種類が増えてきているので、今回、上記の2×2通りの組み合わせのコードスニペットを用意しておく。
本記事の前提知識としては以下の通り。
- AWS CodeBuildの基本的な概念
- TerraformにおけるAWS CodeBuildの基本的な使い方
せっかく4種類のコードスニペットを書くのだから、起動時間の比較をしてみようと思ったが、今回利用したaws/codebuild/amazonlinux2-x86_64-standard:5.0
やaws/codebuild/amazonlinux-x86_64-lambda-standard:go1.21
のイメージでは、起動時間に有意な差はあまり出なかった。
事前準備
今回、以下のようにカスタムイメージ作成用のECRを作っておこう。
resource "aws_ecr_repository" "example" {
name = local.ecr_repository_name
}
なお、都度IAM側にカスタムイメージをPullするための設定を入れるのが面倒な場合は、ECRのリソースポリシーに以下を設定しておくと楽になる。これはCodeBuildのサービスロール側で設定してもOKなので、お好みで。conditionは忘れず設定しておこう。
resource "aws_ecr_repository_policy" "example" {
repository = aws_ecr_repository.example.name
policy = data.aws_iam_policy_document.example.json
}
data "aws_iam_policy_document" "example" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = [
"codebuild.amazonaws.com",
]
}
actions = [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
]
condition {
test = "StringEquals"
variable = "aws:SourceAccount"
values = [data.aws_caller_identity.current.account_id]
}
}
}
コンピューティングタイプとCodeBuild実行イメージ
この後のコードスニペットで利用するコンピューティングタイプとCodeBuild実行イメージは、以下のページを参照する。
- コンピューティングタイプ
- CodeBuild実行イメージ
コードスニペット
EC2 / マネージドイメージ
オーソドックスな組み合わせだと言えるだろう。
今回、AWS CodePipelineからAmazon S3経由でインプットアーティファクトをもらう前提としているため、以下のような書き方になっている。
resource "aws_codebuild_project" "ec2_managedimage" {
name = local.codebuild_project_name_ec2_managedimage
service_role = aws_iam_role.codebuild_ec2_managedimage.arn
source {
type = "CODEPIPELINE"
buildspec = "buildspec.yml"
}
artifacts {
type = "CODEPIPELINE"
}
environment {
type = "LINUX_CONTAINER"
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/amazonlinux2-x86_64-standard:5.0"
privileged_mode = "true"
}
logs_config {
cloudwatch_logs {
group_name = aws_cloudwatch_log_group.codebuild.name
}
}
cache {
type = "LOCAL"
modes = [
"LOCAL_CUSTOM_CACHE",
]
}
}
なお、上記の要件を満たすIAMポリシーは以下のようになる。
アーティファクトのAmazon S3からのソース情報取得と、Amazon CloudWatch Logsへの出力をするための記述なので、CodeCommitを使用する場合はAmazon S3のステートメントに代わりにCodeCommitに合わせたポリシーを設定しておこう。
resource "aws_iam_role_policy" "codebuild_ec2_managedimage" {
role = aws_iam_role.codebuild_ec2_managedimage.id
policy = data.aws_iam_policy_document.codebuild_custom_ec2_managedimage.json
}
data "aws_iam_policy_document" "codebuild_custom_ec2_managedimage" {
statement {
effect = "Allow"
actions = [
"logs:CreateLogStream",
"logs:PutLogEvents",
]
resources = [
"${aws_cloudwatch_log_group.codebuild.arn}:*",
]
}
statement {
effect = "Allow"
actions = [
"s3:GetObject",
]
resources = [
"${aws_s3_bucket.example.arn}/*",
]
}
}
EC2 / カスタムイメージ
カスタムイメージを使用する場合は、予めAmazon ECRにカスタムイメージを入れておいたら、あとはimage
をAmazon ECRのURIの形式に変更すれば良い。
resource "aws_codebuild_project" "ec2_customimage" {
// (中略)
environment {
type = "LINUX_CONTAINER"
compute_type = "BUILD_GENERAL1_SMALL"
- image = "aws/codebuild/amazonlinux2-x86_64-standard:5.0"
+ image = "${aws_ecr_repository.example.repository_url}:latest"
privileged_mode = "true"
}
// (中略)
}
なお、IAMは以下の内容を追記する。Amazon ECRのリソースポリシーで設定してある場合は、ecr:GetAuthorizationToken
のステートメントだけ追加すれば良い。
data "aws_iam_policy_document" "codebuild_custom_ec2_customimage" {
// (中略)
+ statement {
+ effect = "Allow"
+
+ actions = [
+ "ecr:GetAuthorizationToken",
+ ]
+
+ resources = [
+ "*",
+ ]
+ }
+ statement {
+ effect = "Allow"
+
+ actions = [
+ "ecr:GetDownloadUrlForLayer",
+ "ecr:BatchGetImage",
+ "ecr:BatchCheckLayerAvailability",
+ ]
+
+ resources = [
+ aws_ecr_repository.example.arn,
+ ]
+ }
// (中略)
}
ECRへのリソースベースのポリシー設定方法は、AWS CodeBuildユーザーガイドの以下の項目が詳しいので、興味がある方は参照していただきたい。
Lambda / マネージドイメージ
Lambdaのマネージドイメージは、EC2のマネージドイメージと以下の差分がある。
Lambdaの実行環境ではキャッシュがサポートされないので注意が必要だ。
また、privileged_mode
が、Lambdaのコンピューティング環境ではDocker in Dockerのようなことができないらしく、privileged_mode
を設定しようとしたらエラーになった。
resource "aws_codebuild_project" "lambda_managedimage" {
// (中略)
environment {
- type = "LINUX_CONTAINER"
+ type = "LINUX_LAMBDA_CONTAINER"
- compute_type = "BUILD_GENERAL1_SMALL"
+ compute_type = "BUILD_LAMBDA_4GB"
image = "aws/codebuild/amazonlinux-x86_64-lambda-standard:go1.21"
- privileged_mode = "true"
+ privileged_mode = "false"
}
// (中略)
- cache {
- type = "LOCAL"
- modes = [
- "LOCAL_CUSTOM_CACHE",
- ]
- }
}
なお、IAMについてはEC2のマネージドイメージとの差分は無い。
Lambda / カスタムイメージ
Lambdaのカスタムイメージは、Lambdaのマネージドイメージをベースに以下の変更を行う。
image_pull_credentials_typeについては、デフォルトのCODEBUILD
が設定不可能であるため、SERVICE_ROLE
に変更する。
resource "aws_codebuild_project" "lambda_customimage" {
// (中略)
environment {
type = "LINUX_LAMBDA_CONTAINER"
compute_type = "BUILD_LAMBDA_4GB"
- image = "aws/codebuild/amazonlinux-x86_64-lambda-standard:go1.21"
+ image = "${aws_ecr_repository.example.repository_url}:latest"
privileged_mode = "false"
+ image_pull_credentials_type = "SERVICE_ROLE"
}
// (中略)
}
IAMについては、EC2のカスタムイメージと同じで良い。
これで、CodeBuildの使い方の幅が拡がったのではないだろうか。