0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform で始めるセルフホステッドランナー:terraform-aws-github-runner での構築手順

Posted at

はじめに

GitHub actions にはセルフホステッドランナー(Self-Hosted Runner)と呼ばれる機能があります。

通常 GitHub actions のワークフローは GitHub 側が用意してくれたホストで実行されます。
一方セルフホステッドランナー(Self-Hosted Runner)は、GitHub Actions のワークフローをユーザーが用意したホストにできます。

セルフホステッドランナーを使うことにより、ユーザーが実行ホストを詳細にカスタマイズできたり、ワークフロー実行時にかかるランニングコストを抑えることができます。

調べてみると、この環境を Terraform で構築できるモジュールが見つかったので、実際に使ってみました。
構築中いくつかつまりポイントなどがあったので、それらも含めて紹介していきます。

terraform-aws-github-runner とは

Terraform で GitHub actions の実行環境を手軽に構築することができるモジュールです。

もともとは PHILIPS 社(シェーバーや車のライトで有名なメーカー)が開発・管理されていました。

こちらのリポジトリは 2025 年 1 月 16 日にアーカイブされており、現在は上記のリポジトリに移ったみたいです。

アーキテクチャ

こちらは公式のアーキテクチャ図です。

詳しいアーキテクチャが気になったので、少し調べてみました。

terraform-aws-self-hosted-runner.drawio (1).png

  • GitHub actions のワークフロー開始をトリガーとして webhook を実行
  • AWS はそのリクエストを受取、Spot Instance の作成
  • 作成された Spot Instance は GitHub Actions にセルフホステッドランナーとして登録
  • GitHub actions はセルフホステッドランナーが登録されたことを検知し、ワークフローを実行

アーキテクチャもわかったので、実際にこれを使って構築してみます。

構築手順

以下の流れで構築をしていきます。

  • GitHub App を作成
  • Terraform で AWS 環境を構築
  • GitHub App に AWS のエンドポイントを登録
  • 必要なリポジトリへインストール

GitHub App の作成

ここでは大きく2つ作成します。

  • GitHub App の作成
  • 秘密鍵の作成

GitHub App の作成

https://github.com/settings/apps/new から作成できます。

各設定値は以下の通りです。

  • GitHub App name:任意の名前
  • Homepage URL:https://github-aws-runners.github.io/terraform-aws-github-runner/getting-started/#setup-guide(必須なので書いていますが、おそらくなんでも大丈夫)
  • Webhook:Active のチェックを外す(あとで有効化するので一旦外しておきます)
  • Permissions(すべて Repository permissions)
    • Actions:Read-only
    • Administration:Read and write(個人のリポジトリの場合)
    • Checks:Read-only
    • Metadata:Read-only

上記の設定が終わったら「Create GitHub App」を選択します。

「App ID」は Terraform で使うので控えておきましょう。

image.png

秘密鍵の作成

「Private keys」で秘密鍵を発行します。

ボタンは App の General カテゴリにあります。

image (1).png

Terraform で AWS 環境を構築

ディレクトリ構成は以下の通りです。

.
├── lambdas-download
│   ├── runner-binaries-syncer.zip
│   ├── runners.zip
│   └── webhook.zip
├── main.tf
└── 秘密鍵.pem

lambdas-download の下の zip ファイルは公式 Releases からダウンロードします。

秘密鍵.pem はさきほど GitHub App で作成した秘密鍵を配置する。

main.tf
locals {
  key_base64 = base64encode(file("./秘密鍵.pem"))
}

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.27"
    }
    random = {
      source  = "hashicorp/random"
      version = "~> 3.0"
    }
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }

  required_version = ">= 1.3.0"
}
provider "aws" {
  region = "ap-northeast-1"
}

resource "random_id" "random" {
  byte_length = 20
}

# Create a VPC
resource "aws_vpc" "test" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true
  tags = {
    Name = "test-vpc"
  }
}

# Create an Internet Gateway
resource "aws_internet_gateway" "test_igw" {
  vpc_id = aws_vpc.test.id
  tags = {
    Name = "test-igw"
  }
}

# Create a Public Route Table
resource "aws_route_table" "test_public_rt" {
  vpc_id = aws_vpc.test.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.test_igw.id
  }
  tags = {
    Name = "test-public-rt"
  }
}

# Associate Public Route Table with Subnet 1
resource "aws_route_table_association" "test_subnet_1_association" {
  subnet_id      = aws_subnet.test_subnet_1.id
  route_table_id = aws_route_table.test_public_rt.id
}

# Associate Public Route Table with Subnet 2
resource "aws_route_table_association" "test_subnet_2_association" {
  subnet_id      = aws_subnet.test_subnet_2.id
  route_table_id = aws_route_table.test_public_rt.id
}

# Create Subnet 1
resource "aws_subnet" "test_subnet_1" {
  vpc_id                  = aws_vpc.test.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "ap-northeast-1a"
  map_public_ip_on_launch = true
  tags = {
    Name = "test-subnet-1"
  }
}

# Create Subnet 2
resource "aws_subnet" "test_subnet_2" {
  vpc_id                  = aws_vpc.test.id
  cidr_block              = "10.0.2.0/24"
  availability_zone       = "ap-northeast-1c"
  map_public_ip_on_launch = true
  tags = {
    Name = "test-subnet-2"
  }
}

module "github-runner" {
  source  = "github-aws-runners/github-runner/aws"
  version = "~> 6.0.0"

  aws_region = "ap-northeast-1"
  vpc_id     = aws_vpc.test.id
  subnet_ids = [aws_subnet.test_subnet_1.id, aws_subnet.test_subnet_2.id]

  prefix = "gh-ci"

  github_app = {
    key_base64     = local.key_base64
    id             = "{さきほど取得したAppを入れる}"
    webhook_secret = "webhook_secret"
  }

  webhook_lambda_zip                = "lambdas-download/webhook.zip"
  runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip"
  runners_lambda_zip                = "lambdas-download/runners.zip"
  enable_organization_runners       = false
}

output "runners" {
  value = {
    lambda_syncer_name = module.github-runner.binaries_syncer.lambda.function_name
  }
}

output "webhook_endpoint" {
  value = module.github-runner.webhook.endpoint
}

output "webhook_endpoint" {
  value = module.github-runner.webhook.endpoint
}

output "webhook_secret" {
  value     = random_id.random.hex
}

AWS へのデプロイ権限があるターミナルでデプロイします。

terraform init
terraform plan
terraform apply

デプロイが完了すると、webhook_url と webhook_secret がコンソールに出力されるので控えておきます。

Apply complete! Resources: 101 added, 0 changed, 0 destroyed.

Outputs:

runners = {
  "lambda_syncer_name" = "gh-ci-syncer"
}
webhook_endpoint = "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/webhook"
webhook_secret = xxxxxxxx

GitHub App に AWS のエンドポイントを登録

やることは2つです。

  • Webhook URL の登録
  • Event の設定

Webhook URL の登録

GitHub App の General で Webhook URL を以下のように設定します。

  • Active:チェック
  • Webhook URL:先ほど Terraform で発行した内容
  • WebhookSecret:先ほど Terraform で発行した内容

「Save Changes」をクリックする。

Advanced で ping が通ったログを確認できればOKです。

image (2).png

Event の設定

ping が通ると Permissioin & events に Subscribe to events が追加されるので以下の項目にチェックを入れて保存します。

  • Workflow job

※公式ドキュメントだと「Workflow job か Check run のどちらか片方」と書いてあったが、自分の場合 Workflow job でないと動きませんでした。

必要なリポジトリへインストール

Install App で自分のアカウントを選択します。

Only select repositories でセルフホステッドランナーを使いたいリポジトリを選択します。

image (3).png

選択後、Install をクリックします。

ここまでで構築は完了です。

動かしてみる

最初はランナーが登録されていない状態です。

image (4).png

以下のワークフローを実行してみます。

name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

  workflow_dispatch:

jobs:
  build:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v3

      - name: Run a one-line script
        run: echo Hello, world!

実行してしばらくすると、セルフホステッドランナーが追加されています。

image (5).png

ワークフローが動いていることも確認できました。

image (6).png

まとめ

今回は GitHub Actions のセルフホステッドランナーを terraform-aws-github-runner モジュールを使って AWS 上に構築する方法を解説しました。
実際に構築完了後、ワークフローを実行することで、自動的に AWS 上に Spot Instance が作成され、GitHub Actions のセルフホステッドランナーとして登録・動作することを確認しました。
セルフホステッドランナーを使うことで、実行環境を詳細にカスタマイズできるだけでなく、ランニングコストの削減も可能になります。
また、ワークフロー実行時だけインスタンスが立ち上がるため、コスト効率の良い CI/CD 環境を実現できます。
みなさんもぜひ terraform-aws-github-runner を使ってみてください。

参考

0
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?