2025/2/26に、Self-hostedなGitLabに関して、そのCI/CDを実行するGitLab RunnerをCodeBuildで動かせるようになったという発表がありました (2024/9/17に発表された[AWS CodeBuild がマネージド GitLab ランナーのサポート開始:title:bookmark]はあくまでSaaSのGitLabに対してのものでした)。
企業でGitLabを使っている場合、情報資産管理の関係でSelf-hostedなGitLabを使い情報資産を封じ込める構成をとっていることが多いと思います。このSelf-hostedなGitLabにおいても、CodeBuild-hosted GitLab Runnerを使えるようになる。これが意味するところは、Self-hostedなGitLabにおいても、CI/CDが大規模スケールするということです。たくさんのCIジョブが詰まっている諸君、良かったな!
Terraformで構築する
それでは、このCodeBuild-hosted RunnerをTerraformで構築してみましょう。 僕の環境は以下です。
$ terraform version Terraform v1.10.3 on linux_arm64 + provider registry.terraform.io/hashicorp/aws v5.94.1
環境前提
GitLab Self-Managedのバージョンは17.10。VPC内のprivate subnet上のEC2サーバ(Amazon Linux2)上にインストールし、インターネットからはALB経由でアクセスできるようにしています。アクセス用のFQDNは仮にgitlab.example.comとしましょう。
モジュール
まずは全体から。CodeBuild用のモジュールのmain.tfは次のようになりました。
resource "aws_codeconnections_host" "gitlab" { name = "GitLab" provider_endpoint = "https://gitlab.example.com" provider_type = "GitLabSelfManaged" # interface VPC Endpoint経由でアクセスできるようにする vpc_configuration { # ここは、GitLabがインストールされているVPCのID等を指定 # これらの設定をもとに、CodeConnections が接続に利用するENIが作成される vpc_id = var.vpc_id security_group_ids = var.security_group_ids subnet_ids = var.subnet_ids } } resource "aws_codeconnections_connection" "gitlab_connection" { name = var.connection_name host_arn = aws_codeconnections_host.gitlab.arn } resource "aws_codebuild_project" "gitlab_runner" { name = "gitlab-runner" description = "GitLab Runner for GitLab" service_role = aws_iam_role.codebuild.arn build_timeout = "60" # minutes badge_enabled = false project_visibility = "PRIVATE" environment { # see: https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-compute-types.html#environment.types compute_type = "BUILD_GENERAL1_SMALL" # 4 GiB、2 vCPU # see: https://docs.aws.amazon.com/codebuild/latest/userguide/ec2-compute-images.html image = "aws/codebuild/standard:5.0" # Amazon Linux 2023 type = "LINUX_CONTAINER" } logs_config { cloudwatch_logs { status = "ENABLED" group_name = aws_cloudwatch_log_group.codebuild.name } } source { auth { type = "CODECONNECTIONS" resource = aws_codeconnections_connection.gitlab_connection.arn } type = "GITLAB_SELF_MANAGED" buildspec = var.build_spec_content git_clone_depth = 1 location = var.gitlab_repository_url report_build_status = true # GitLabだとサポートされていないので無視される build_status_config { context = "CodeBuild / gitlab-runner" } } artifacts { type = "NO_ARTIFACTS" } cache { type = "LOCAL" modes = [ "LOCAL_CUSTOM_CACHE", "LOCAL_DOCKER_LAYER_CACHE" ] } } resource "aws_codebuild_webhook" "gitlab_runner" { project_name = aws_codebuild_project.gitlab_runner.name build_type = "BUILD" filter_group { filter { pattern = "WORKFLOW_JOB_QUEUED" type = "EVENT" } } } resource "aws_cloudwatch_log_group" "codebuild" { name = "/aws/codebuild/gitlab_runner" retention_in_days = 30 tags = { Name = "GitLab Runner" } } data "aws_iam_policy_document" "codebuild_assume_role" { statement { effect = "Allow" principals { type = "Service" identifiers = ["codebuild.amazonaws.com"] } actions = ["sts:AssumeRole"] } } resource "aws_iam_role" "codebuild" { name = "codebuild-github-runner-role" assume_role_policy = data.aws_iam_policy_document.codebuild_assume_role.json } data "aws_iam_policy_document" "codebuild_policy" { statement { effect = "Allow" actions = [ "ec2:Describe*", "s3:GetObject", "s3:PutObject", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ] resources = ["*"] } statement { sid = "UseConnection" effect = "Allow" actions = [ "codestar-connections:UseConnection", "codeconnections:GetConnectionToken", "codeconnections:GetConnection", ] resources = ["*"] } } resource "aws_iam_role_policy" "codebuild" { name = "codebuild-github-runner-policy" role = aws_iam_role.codebuild.id policy = data.aws_iam_policy_document.codebuild_policy.json }
色々とゴチャゴチャしていますが、重要なのは多くないです。
- GitLab Self-ManagedとAWS CodeBuildを接続するための接続ホスト(
aws_codeconnections_host)を定義 - その接続ホストを使って、GitLab Self-Managedのリポジトリにアクセスするための接続(
aws_codeconnections_connection)を定義 - その接続を利用して認証することを前提に、GitLab Self-ManagedのリポジトリをソースにするCodeBuildプロジェクト(
aws_codebuild_project)を定義
これでとりあえず概形は完成ですが、実はこの状態ではTerraformの実行が失敗します。
原因は、まだ「接続」(CodeConnections)ができただけで、未認証(Pending)の状態であるからです。実際、CodeConnections(接続)のマネジメントコンソール上では「保留中」となっています。
これにより、aws_codebuild_webhookの生成が失敗し、Terraformの実行も失敗します。

CodeConnectionsの「保留中」の状態を解消するためには、当該コンソールから、apiスコープを持つGitLabのPAT(Personal Access Token)を使って認証する必要があります。
A Set up host_name page displays. In Provide personal access token, provide your GitLab PAT with the following scoped-down permission only:
api. Connections for GitLab self-managed

この認証を完了させてから再度Terraformを実行すると、すべてのリソースの作成が成功します。
GitLab CI/CDの実行
CodeBuild側の設定が完了したので、次はGitLab側の設定です。
設定といってもgitlab-ci.ymlを作成するだけなのですが、CodeBuild特有の癖があり、GitLab CI/CDとCodeBuildを関連づけるのは各ジョブのtagsです。
hello-world-job: stage: test script: - echo "Hello World!" - echo "今日は $(date '+%Y年%m月%d日') です" tags: - codebuild-<project-name>-$CI_PROJECT_ID-$CI_PIPELINE_IID-$CI_JOB_NAME
上の指定では、<project-name>というCodeBuildプロジェクトとGitLab CI/CDジョブを紐づけています。これにより、GitLabから作成したwebhook経由でCodeBuildの対象プロジェクトにジョブが投げられ、CodeBuild上で当該ジョブが実行されます。
他にもtagsで、利用するDockerイメージ等も指定ができます。その辺りの仕様はLabel overrides supported with the CodeBuild-hosted GitLab runnerに記載があります。
tags: - codebuild-myProject-$CI_PROJECT_ID-$CI_PIPELINE_IID-$CI_JOB_NAME - image:arm-3.0 - instance-size:small - fleet:myFleet - buildspec-override:true
実行結果
GitLab CI/CDジョブの実行結果は、GitLabのWeb UIから確認できます。

一方で、パイプラインの結果が見えません。なぜなんだ。これは仕様なのか判断がついていない。
