LoginSignup
0
0

AWS CodeBuildの様々な実行環境をTerraformで作成する

Last updated at Posted at 2024-06-23

はじめに

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.0aws/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]
    }
  }
}

コードスニペット

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の使い方の幅が拡がったのではないだろうか。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0