Terraform で Github Actions の Self Host Runner を作成する

※ 注意、絶対にパブリックリポジトリではこの作業をしないでください。

仕事で Gtihub Actions を使用していて無料枠を使い切りそうで Self Host Runner (以降 Runner)を作成しようと思い、クラウドのリソースを Terraform を使用して管理していたのでその時に作ったものの簡易版をメモがわりに残しておきます。

https://docs.github.com/ja/actions/hosting-your-own-runners/about-self-hosted-runners

前提

以下の知識、環境があることが前提となっています。

  • 既に何かしらのアプリケーションが動く VPC が構築されていること(検証用ならデフォルトでも問題ないです。)
  • Terraform の基本的な構文を理解していること。
  • 今回触れる AWS リソースについて簡単な知識(EC2,ASG等々があれば大丈夫です。)があること。

尚私の環境は以下の構成で行っています。

$ terraform -version
Terraform v0.14.8
+ provider registry.terraform.io/hashicorp/aws v3.33.0

PCに関しても M1 の Mac で動作確認が取れていますので安心してお使いください。

さっそく構築

こちらのリポジトリに簡易的なものを用意しているので今回はこちらのリポジトリを使用して構築をしたいと思います。

https://github.com/yuzujoe/github-actions-runner

Auto Scaling Group

今回は AWS の Auto Scaling Group (以下ASG)を使用して EC2 上で Runner を動かしたいと思います。 最初は ASG のリソースを定義したいと思います。

resource "aws_autoscaling_group" "this" {
  name = var.name

  desired_capacity          = 1
  max_size                  = 1
  min_size                  = 1
  health_check_grace_period = 0
  termination_policies      = ["OldestInstance"]
  vpc_zone_identifier = [
    # Please set your subnet
  ]

  tag {
    key                 = "Name"
    propagate_at_launch = false
    value               = var.name
  }
}

このように定義しておきます。 他に設定する項目もあるのですがまだリソースが未定義なので後々追加していきます。 name の部分は他のリソースも同じように使用するものなので変数として保持しておきます。

variable "name" {
  type    = string
  default = "github-actions-runner"
}

Launch Template

resource "aws_launch_template" "this" {
  name = var.name

  instance_type = "t2.micro"
  # describe latest ami
  # aws ec2 describe-images --region ap-northeast-1 --query 'reverse(sort_by(Images, &CreationDate))[:1]' --owners amazon --filters 'Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2' --output table
  image_id      = "ami-0f27d081df46f326c"

  instance_market_options {
    market_type = "spot"
  }

  block_device_mappings {
    device_name = "/dev/xvda"
    ebs {
      delete_on_termination = true
      volume_size           = 30
      volume_type           = "gp2"
    }
  }
}

resource "aws_security_group" "this" {
  name = var.name

  vpc_id = "example"

  tags = {
    Name = var.name
  }
}

resource "aws_security_group_rule" "egress" {
  from_port         = 0
  protocol          = "-1"
  security_group_id = aws_security_group.this.id
  to_port           = 0
  type              = "egress"
}

Auto Scaling Group で起動する EC2 インスタンスの起動テンプレートを作成します。 注目して欲しいのは instance_market_options でここで spot を指定することでスポットインスタンスとして起動ができるようになります。 Runner として登録する処理が必要になるのですがそれを Userdata に処理させることで別のインスタンスが立ち上がっても自動で登録してくれるようにする処理を後ほど追加します。

ステートフルに持たせたいものがなければ基本的にはスポットインスタンスでの使用をお勧めします。

セキュリティーグループについては特に指定をする必要はないのですが踏み台経由で SSH をしたいケースは設定をする必要があるのでご自身に合った設定をするようにしましょう。

Userdata

#!/bin/bash

# Install
yum -y install jq git

su ec2-user -c 'mkdir $HOME/actions-runner'
su ec2-user -c 'curl -L https://github.com/actions/runner/releases/download/v2.277.1/actions-runner-linux-x64-2.277.1.tar.gz -o $HOME/actions-runner/actions-runner-linux-x64-2.277.1.tar.gz'
su ec2-user -c 'tar xzf $HOME/actions-runner/actions-runner-linux-x64-2.277.1.tar.gz -C $HOME/actions-runner'

aws configure set region ap-northeast-1
export ACCESS_TOKEN=$(aws secretsmanager get-secret-value --secret-id ${your-token-id} --query SecretString --output text | jq -r .GITHUB_ACCESS_TOKEN

# Configure
export RUNNER_TOKEN="$(curl -XPOST -fsSL \
  -H "Authorization: token ${ACCESS_TOKEN}" \
  -H "Accept: application/vnd.github.v3+json" \
  "https://api.github.com/orgs/yourorg/actions/runners/registration-token" \
| jq -r '.token')"
export RUNNER_NAME=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')

su ec2-user -c '$HOME/actions-runner/config.sh \
  --url "https://github.com/<your org>" \
  --token "${RUNNER_TOKEN}" \
  --name "${RUNNER_NAME}"'

作成した EC2 インスタンスGithub Actions の Runner として追加するにはスクリプトを追加する必要があるのですが、 スポットインスタンスを作成するたびに追加するのは面倒な作業です。 userdata にスクリプトを追加することでスポットインスタンスの入れ替わりに合わせて自動的に Runner に追加してくれるので手間が省けます。

今回は Github のオーガナイゼーションを意識したものですが個人で使用される場合は個人のリポジトリを指定しましょう。

この際ですが、Github の アクセストークンを secret manager から取得する処理を追加しているのであらかじめ追加しておきましょう。

必要な権限はこちらになります。

これで準備が整いました。 Terraform を適用して適切に Runner が追加されていれば成功です。

これで Github Actions を Self Host Runner として動かすことで、制限時間などを気にせずに使用できるようになります。 また、終了したスポットインスタンスは Runner として残ってしまうので定期的にお掃除をしてあげる必要がありますが時間があればそちらの定期実行の Actions も紹介できればと思います。

最後まで見ていただいてありがとうございました。