G-gen の武井です。 当記事では GitHub Actions の Self-hosted runners (セルフホストランナー) を使って Google Cloud (旧称 GCP) 環境に Terraform を実行する方法を紹介します。

はじめに
GitHub Actions の概要や実行方法については以下の記事で解説しています。
一読いただくと後述の理解が深まりますで是非ご参照ください。
実行環境について
概要
GitHub Actions では、ワークフローの実行環境を ランナー と呼びます。
ランナーの種類
ランナーは以下の2種類から選択可能です。
# | 種類 | 特徴 |
---|---|---|
1 | GitHub-hosted runners | GitHub 側で用意される実行環境。ユーザーによる管理は不要だが条件次第で課金が発生 |
2 | Self-hosted runners | ユーザーが用意する実行環境。管理は必要だが利用料金は不要で HW/SW 構成も自由 |
ランナーの特徴
各ランナーの特徴について整理します。
項目 | GitHub-hosted | Self-hosted |
---|---|---|
管理 | GitHub が管理 | ユーザーが管理 |
構成自由度 | 小さい (契約プランに依存) | 大きい |
料金 | パブリックリポジトリ:無料 プライベートリポジトリ:従量課金型 (無料枠あり) |
無料 |
管理
前者の場合、ランナーの管理は GitHub 側で行われますが、後者の場合はユーザー側に責任が生じるため管理に伴う工数やコストが発生します。
参考:GitHub ホステッド ランナーの概要
参考:セルフホステッド ランナーの概要
構成自由度
前者の場合、ハードウェアやソフトウェア仕様の選択は契約プランに依存しますが、後者の場合はありません。ジョブの規模などに応じて柔軟な調整が可能です。
料金
前者の場合、パブリックリポジトリにおけるランナーの利用は無料ですが、プライベートリポジトリにおけるランナーの利用については契約プランに応じた無料の使用時間 (分) とストレージ (サイズ) が各アカウントに付与されます。無料枠を超過した場合に使用時間による従量課金が発生します。
ランナーの使用時間は毎月リセットされますが、ストレージはリセットされません。契約プランごとの無料枠や費用計算、その他詳細は以下をご確認ください。
参考:GitHub Actions の課金について
参考:GitHub 料金計算ツール
その他
上記の他にも両者の仕様上の違いがありますので詳細は以下をご確認ください。
参考:セルフホスト ランナーと GitHub ホステッド ランナーの違い
セルフホストランナーを使った Terraform の実行方法
では実際にセルフホストランナーを使用して Google Cloud 環境に Terraform を実行する方法をご紹介していきます。
セルフホストランナー用 VM マシンの準備
以下は Terraform から VM マシン (OS : Debian11
) と関連リソースをデプロイする場合のソースです。ご利用される場合、リソース名や変数をご自身の環境に合わせて置き換えてください。
# vpc resource "google_compute_network" "runner_vpc" { project = var.terraform_project_id name = "runner-vpc" auto_create_subnetworks = false mtu = 1460 } # subnet resource "google_compute_subnetwork" "runner_subnet" { name = "runner-subnet" ip_cidr_range = "192.168.10.0/24" region = "asia-northeast1" network = google_compute_network.runner_vpc.id project = var.terraform_project_id private_ip_google_access = true log_config { aggregation_interval = "INTERVAL_5_MIN" flow_sampling = 0.5 metadata = "EXCLUDE_ALL_METADATA" } } # firewall resource "google_compute_firewall" "allow_ssh { name = "allow-ssh" network = google_compute_network.runner_vpc.name project = var.terraform_project_id priority = "100" direction = "INGRESS" description = "Cloud IAP の SSH 通信を許可" allow { protocol = "tcp" ports = ["22"] } log_config { metadata = "EXCLUDE_ALL_METADATA" } source_ranges = ["35.235.240.0/20"] } # compute engine resource "google_compute_instance" "runner" { name = "runner-01" machine_type = "e2-micro" zone = "asia-northeast1-b" project = var.terraform_project_id boot_disk { initialize_params { image = "debian-cloud/debian-11" size = "10" type = "pd-balanced" labels = { instance = "runner-01" } } } network_interface { subnetwork = google_compute_subnetwork.runner_subnet.name subnetwork_project = var.terraform_project_id network_ip = "192.168.10.11" access_config {} } service_account { email = "${TERRAFORM_SERVICE_ACCOUNT}" // サービスアカウント scopes = ["cloud-platform"] } }
参考:
セルフホストランナー用 VM マシンのセットアップ
設定用コマンドの取得
以下の手順でコマンドを取得します。
GitHub リポジトリ
にログインSettings > Actions > Runners
の順に画面を遷移[New self-hosted runner]
をクリック[Runner image]
をLinux
、[Architecture]
をx64
に選択、表示されるコマンドを取得

設定用コマンドの実行
一般ユーザで実行する場合
先程取得した設定用コマンドを VM マシンにログインして OS 上で実行します。
config.sh
の実行コマンドで以下のエラーが表示された場合、エラーメッセージ内の依存関係解消用のコマンド (sudo ./bin/installdependencies.sh
) を実行した後にリトライしてください。
$ ./config.sh --url https://github.com/{OWNER_NAME}/{REPOSITORY_NAME} --token {VALUE} Libicu's dependencies is missing for Dotnet Core 6.0 Execute sudo ./bin/installdependencies.sh to install any missing Dotnet Core 6.0 dependencies.
セルフホストランナーが GitHub に紐付きプロセスが正常に起動すると Connected to GitHub
と表示されます。

また、GitHub の画面には登録されたセルフホストランナーのマシン名が表示されます。

root で実行する場合
root にスイッチ (sudo su -
) した後に先程取得した設定コマンドを実行しても config.sh
の実行コマンドがエラーとなります。
以下のように変数 (RUNNER_ALLOW_RUNASROOT
) を設定しつつコマンドを実行します。その際、依存関係を示すエラーが表示された場合は前述と同じように対応します。
# RUNNER_ALLOW_RUNASROOT="1" ./config.sh --url https://github.com/{OWNER_NAME}/{REPOSITORY_NAME} --token {VALUE}
変数を設定する理由としては、config.sh
を実行したユーザの UID が "0" (root の UID は "0") の場合はプログラムが終了する作りになっているためです。
#!/bin/bash user_id=`id -u` # we want to snapshot the environment of the config user if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then echo "Must not run with sudo" exit 1 fi
プロセスの自動起動設定
取得したコマンドではセルフホストランナーのプロセスを ./run.sh
コマンドで手動起動する前提になっています。
プロセスを自動起動させたい場合は以下のリンク先に記載の設定を実行してください。
参考:セルフホストランナーアプリケーションをサービスとして設定する
定義ファイルの作成
セルフホストランナーを使用する場合、15行目に記載のある通りジョブ定義の中で runs-on: self-hosted
と指定するだけです。
name: terraform # main ブランチへの Pull request と Merge on: pull_request: branches: - main push: branches: - main # ジョブ (Self-hosted runners で実行) jobs: terraform-workflow: runs-on: self-hosted permissions: id-token: write contents: read pull-requests: write # main.tf のあるディレクトリを指定 strategy: matrix: tf_working_dir: - ./env/yutakei steps: - uses: actions/checkout@v3 name: Checkout id: checkout # https://github.com/marketplace/actions/setup-tfcmt - uses: shmokmt/actions-setup-tfcmt@v2 name: Setup tfcmt # https://github.com/marketplace/actions/setup-github-comment - uses: shmokmt/actions-setup-github-comment@v2 name: Setup github-comment # https://github.com/actions/setup-node # https://github.com/hashicorp/setup-terraform/issues/84 - uses: actions/setup-node@v3 with: node-version: '16' - uses: hashicorp/setup-terraform@v2 name: Setup terraform - name: Terraform fmt id: fmt run: | cd ${{ matrix.tf_working_dir }} terraform fmt -recursive continue-on-error: true - name: Terraform Init id: init run: | cd ${{ matrix.tf_working_dir }} terraform init -upgrade - name: Terraform Validate id: validate run: | cd ${{ matrix.tf_working_dir }} terraform validate # main ブランチへの pull request した際のみ terraform plan を実行 - name: Terraform Plan id: plan if: github.event_name == 'pull_request' run: | cd ${{ matrix.tf_working_dir }} export GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} tfcmt -var target:${{ matrix.tf_working_dir }} plan -- terraform plan --parallelism=50 github-comment hide -condition 'Comment.Body contains "No changes."' continue-on-error: true # terraform status で失敗した際に workflow を停止 - name: Terraform Plan Status id: status if: steps.plan.outcome == 'failure' run: exit 1 # main ブランチへの push した際のみ terraform apply を実行 - name: Terraform Apply id: apply if: github.ref == 'refs/heads/main' && github.event_name == 'push' run: | cd ${{ matrix.tf_working_dir }} export GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} tfcmt -var target:${{ matrix.tf_working_dir }} apply -- terraform apply -auto-approve -input=false --parallelism=50
ワークフローの実行
定義ファイルに記載のトリガー条件を満たすとセルフホストランナーによってワークフローが実行されます。
- 所定のブランチに Pull request を実行すると
tarraform plan
が実行 - 所定のブランチに Merge を実行すると
tarraform apply
が実行


武井 祐介 (記事一覧)
2022年4月入社 / クラウドソリューション部 / 技術2課所属
趣味はゴルフにロードバイク。IaC や CI/CD 周りのサービスやプロダクトが興味分野です。
Google Cloud 認定全冠達成!(2023年6月)