スケーラブルなSelf-hosted Runnerを立ち上げるために"terraform-aws-github-runner"を使ってみた

こんばんは、サーバサイドエンジニアの黒岩(@kro96_xr)です。
今回は先週の記事で触れられていたterraform-aws-github-runnerの環境構築を行ったときの作業内容を書いていきたいと思います。

先週の記事はこちら
synamon.hatenablog.com

構成図

先週の記事にもありましたがインフラ構成図は以下のようになっています。(引用元リンク)

処理フローを文章化すると以下のようになるでしょうか。

  • Github Appsでリポジトリに対するイベント発生を検知
  • Webhookが発火し、"Webhook" Lambdaが実行され、メッセージをSQSにキューイング
  • "Scale Up" Lambdaがメッセージを受け取り、スポットインスタンスを生成
  • インスタンス起動時にuser_dataスクリプトでエージェント等をインストール ⇒ ランナーとして登録
  • 処理の実行
  • "Scale Down" Lambdaが定期的にインスタンスをチェックし、不要となったインスタンスとランナーを削除

上記の通り、環境構築を行うためにはAWS側の設定Github側の設定が必要となります。
前者の設定はTerraformから実行できますが、後者の設定は手動で行う必要があります。

基本的にはREADMEを読めばわかるかと思いますが、設定方法を見ていきましょう。

STEP1: GithubAppの作成

まず、GithubAppを作成していきます。
名前等は自由に決め、Webhookのチェックボックスをこの時点では外しておきます

パーミッションはActions、Checks、MetadataをRead-onlyにします。
また、ランナーをリポジトリレベルで使用するため、AdministrationをRead & writeとします。

組織レベルで使用する場合はOrganization permissionsのSelf-hosted runnersをRead & writeとするそうです。
こちらは今回は試していないので画像等は割愛します。

アプリを保存するとAppIDとClientIDが発行されるので保存しておきます。

作成されたAppの秘密鍵を生成し、保存しておきます。

STEP2: Terraformの設定

続いてTerraformの設定になります。

まず、Lambdaのスクリプトをダウンロードします。
Github上のリリースページからダウンロード可能ですので最新版を落としておきます。
これらのファイルのパスをmain.tf内で指定するので控えておいてください。

次に、main.tfを書いていきます。
READMEにサンプルがありますが、今回はランナーとしてWindowsを使用するために修正を行っています。
先に全体を載せておきます。なお、VPCの作成は事前に行っている想定です。

# ランダムIDの生成
resource "random_id" "random" {
  byte_length = 20
}

module "github-runner" {
  source  = "philips-labs/github-runner/aws"
  version = "v0.36.0"

  # 事前に作成したVPCを指定
  aws_region = "ap-northeast-1"
  vpc_id     = <VPC ID>
  subnet_ids = [<サブネットID>]

  # 環境名(プレフィックス)
  environment = <任意の文字列>

  # GithubAppの設定
  github_app = {
    key_base64     =    <秘密鍵をBase64エンコードした文字列>
    id                     =    <GithubApp ID>
    webhook_secret =    random_id.random.hex
  }

  # 先にダウンロードしておいたLambdaのパスを指定
  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
  
  # OS指定
  runner_os = "windows"

  # ランナーのラベル指定
  runner_extra_labels = "default,example"

  # Runnerの立ち上げ待ち時間
  runner_boot_time_in_minutes = 20

  # webhookの実行を遅延させる(秒)
  delay_webhook_event = 5

  # スケールダウンチェックの頻度をcronで設定
  scale_down_schedule_expression = "cron(0 * * * ? *)"
}

ポイントはGithubApp作成時に生成した情報をセットすることです。

  # GithubAppの設定
  github_app = {
    key_base64     =    <秘密鍵をBase64エンコードした文字列>
    id                     =    <GithubApp ID>
    webhook_secret =    random_id.random.hex
  }

もちろんtfvarsで渡しても大丈夫です。というかtfvarsに書いてgitignoreした方がセキュリティ上いいと思います。

key_base64は秘密鍵をさらにBase64エンコードした文字列となりますので気を付けてください。
下記のissueを見るまで私は見落としていました…
PEM routines:get_name:no start line · Issue #40 · philips-labs/terraform-aws-github-runner · GitHub

書けたらterraform init, terraform plan, terraform applyを実行します。

$ terraform init
$ terraform plan
$ terraform apply

その他追加の設定

基本的な設定は上記で大丈夫だと思いますが、GithubにInputパラメータがありますので用途に合わせて調整してみてください。
弊社では下記のような設定を追加しています。

  • ラベル設定の変更

複数のUnityバージョンに対応できるようにラベルを変更しています。

  # ラベル設定
  runner_extra_labels = "<Unityバージョン>"
  runner_enable_workflow_job_labels_check = true
  • AMIの設定

カスタムAMIを使用しているためその設定を追加しています。

  # ami
  ami_filter = {
    name = [<自作したAMI名>]
  }
  ami_owners = ["<AMIを所有するアカウント名>"]
  • EBSの設定

カスタムAMIがストレージをだいぶ食っていたのでサイズをあげました。

  # EBSのサイズ(GB)
  volume_size = <EBSサイズ>

STEP3: Webhookの設定

Webhookの情報をGithubAppに設定していきます。
下記を実行するとWebhook URLとWebhook Secretが取得できるので控えておきます。

$ terraform output -raw webhook_secret

GithubAppの設定画面に戻り、Webhookを有効化してそれぞれの値を設定していきます。

次にWebhookを発火するイベントを設定します。
Permission & eventsからWorkflow jobにチェックを入れます。

最後にリポジトリにAppをインストールします。
Organization>Settings>Integrations>Github Appsから作成したAppを選択、編集します。
リポジトリを選択してインストールすることで、該当リポジトリでランナーを使えるようになります。

STEP4: GIthub Actionsの設定

runs-onの項目を下記のように設定すればOKです。

runs-on: [self-hosted, windows, x64, <設定したラベル名>]  

おわりに

以上、"terraform-aws-github-runner"を使ったSelf-hosted Runnerの構築でした。
今回紹介した機能はまだ一部ですのでぜひみなさん触ってみてはいかがでしょうか?

また、まだ詳しく読めていないのですが下記のような方法もあるようでした。
私自身まだまだ詳しくない領域なので知見を共有していただけると嬉しいです!
HashiCorp NomadでGitHub Actions Self-hosted Runnerを簡単にautoscale運用する

参考リンク

github.com

qiita.com

zenn.dev