self-hosted runner とは、GitHub Actions の job を自分で用意した機械で走らせる、自前の作業員(runner)です。

  • GitHub がホストする作業員と自前の作業員で、何を誰が持つかの違い
  • 1 job に 1 台の使い捨て(ephemeral)の作業員を、JIT の設定で立てて消す手順
  • AI の席が PR を並べて出す当社で、自前に寄せてから実際に詰まった所(台数・空き時間・Spot の回収・登録の上限・API の上限)

当社は AIエージェント(Claude Code の席)を何十本も同時に動かし、席がそれぞれ PR を出します。席の数を増やすと、先に詰まるのは席ではなく、PR の試験を走らせる GitHub の作業員でした。この頁は、その作業員を自前に寄せた記録です。席を同時に動かす形そのものは Claude Code の並列実行 と マルチエージェント の頁にあります。

GitHub がホストする作業員と、自前の作業員の違い

GitHub の文書は、self-hosted runner を「自分で置いて管理する、GitHub Actions の job を走らせる仕組み」としています。GitHub Actions で使うのは無料ですが、機械を保つ費用は自分持ちで、OS とその他のソフトの更新も自分の受け持ちです。自動で更新されるのは runner のアプリだけです(Self-hosted runners・2026-10-30 に見た)。

見る所GitHub がホストする作業員自前の作業員(self-hosted runner)
機械を用意する人GitHub自分(自前の機械・雲の VM など)
OS とソフトの更新GitHub自分。runner のアプリだけは自動で更新される
使う時の数え方組織の使用量に数えられる。当社は上限に当たって CI が止まった(下の節)GitHub Actions で使うのは無料。機械の費用は自分持ち
台数を増減させる形GitHub に任せる自分で組む。GitHub は、使い続ける(persistent)作業員で台数を増減させる形を勧めていない
1 回で消す形—--ephemeral を付けて登録すると、1 つの job を処理した後に自動で登録が外れる。REST API で ephemeral の JIT の作業員も作れる

出典: Self-hosted runners・Self-hosted runners reference(いずれも 2026-10-30 に見た)。使用量の上限に当たった事は社の実測 2026-10-09(当社の CI の記録)。

きっかけ: 9 日で先月分を超え、CI が止まった

2026-10-09、GitHub がホストする作業員の使用量が、月の 9 日目で先月 1 か月分を超えました。組織の使用量の上限に当たり、CI が止まりました。そこで job を自前の作業員に寄せました(出典: 社の実測 2026-10-09(当社の CI の記録))。

AI の席は PR ごとに試験を走らせるので、席を増やすほど試験の回数も増えます。

寄せた直後は 2〜4 倍遅くなった。原因は CPU ではなく台数

自前に寄せた翌日、CI 1 回の時間は GitHub のころの 2〜4 倍になりました。機械の CPU は 23% 空いていました。遅さの原因は機械の力ではなく、作業員の数が足りず job が待っていた事でした(出典: 社の実測 2026-10-10(当社の CI の記録))。

測った物自前に寄せた直後GitHub のころ
PR の CI 1 回37 分15〜17 分
merge 待ち(統合の列)の CI 1 回36 分
別のリポの PR の CI 1 回62 分

出典: 社の実測 2026-10-10(当社の CI の記録)。

席が一斉に PR を出すと、作業員の台数がそのまま待ちの長さになります。当社が組んだ形は次の節のとおりです。

当社の方式: 1 job に 1 台の使い捨て(ephemeral)

当社は、1 つの job に 1 台の VM を立て、job が終われば VM ごと消す形にしました。台は GCP の Spot VM です。立てる時に JIT の設定(generate-jitconfig で作る)を渡し、runner を 1 回だけ動かして、job が終わったら VM が自分で電源を落とします(出典: 社の実測 2026-10-10(当社の CI の記録))。

JIT の設定は、組織なら POST /orgs/{org}/actions/runners/generate-jitconfig、リポなら POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig で作ります。name・runner_group_id・labels が要り、返りの encoded_jit_config を runner のアプリに起動の時に渡します(REST API endpoints for self-hosted runners・2026-10-30 に見た)。

順やる事当社で決めた線
1job が待っている分だけ、JIT の設定を発行する発行には GitHub の API を使う。発行の口は専用のトークンに分ける(下の節)
2Spot VM を立て、JIT の設定を渡して runner を 1 回だけ動かすVM にはサービスアカウントを付けない。入りは全部拒否の専用の VPC に置く
3自前の作業員に回す job を、ラベルで選ぶdeploy や本番の鍵を使う job にはラベルを付けない。付ける前に、その workflow で secrets.* の参照が 0 本である事を確かめる
4job が終わったら、VM が自分で電源を落とす落ちなかった VM は、寿命の上限 240 分で強制削除する

出典: 社の実測 2026-10-10(当社の CI の記録)。

切り替えた後の 1 本目の検証では、PR の 15 の job のうち 5 本が GCP の作業員で走って緑になりました。job が作業員に拾われるまでの待ちは 241〜522 秒でした(出典: 社の実測 2026-10-10(当社の CI の記録))。

立てた VM が遊ぶ時間を減らす

使い捨ての形は、立てた VM が job を拾わずに時間を使うと、その分が無駄になります。同じ形の試しの列で、直す前と後を比べました(出典: 社の実測 2026-10-13(当社の CI の記録))。

測った物直す前直した後
立てた VM のうち、job を走らせている時間の割合38%72〜73%
1 本も job を拾わない VM の時間13%0〜1%
最初の 6 分に立てる台数24 台8 台

出典: 社の実測 2026-10-13(当社の CI の記録・同じ形の試しの列で比べた)。

立っては約 2 分で落ちる VM

その後、立った VM が約 2 分で落ちる事が続きました。起動に 46 秒、最初の job を待つ見切りが 90 秒で、列に 18〜31 本の job が在るのに、拾わずに電源を落としていました。見張りは VM ごとに gcloud を起こしていて、1 周に数分かかっていました(出典: 社の実測 2026-10-15(当社の CI の記録))。

見張りは curl 1 回に替え、1 台 0.3 秒にしました。合わせて、最初の job を待つ見切りを 90 秒から 240 秒に、次の JIT を待つ上限を 60 秒から 300 秒にしました。直した後、立った 90 台のうち 6 台(6.7%)が 1 本も拾わずに終わりました。目標の 5% には 1.7 点届いていません(出典: 社の実測 2026-10-15(当社の CI の記録))。

Spot の回収で job が赤になる

Spot VM は走っている途中で回収されます。回収されると、その job は「runner lost communication」で、試験の結果が 0 のまま赤になります。1 本 11 分の job でした(出典: 社の実測 2026-10-11(当社の CI の記録))。

当社は、回収の監査ログ(compute.instances.preempted)を 30 秒おきに見て、次の 3 つが揃った job だけを 1 回撃ち直します。

  1. 結果が failure である
  2. 失敗の理由が lost communication である
  3. その run が終わっている

ただし、撃ち直しでは merge 待ちの列から落ちた PR を戻せません。落ちた 1〜4 分後には、その PR はもう列から外れています(出典: 社の実測 2026-10-11(当社の CI の記録))。統合の列で成功を何で確かめるかは、GitHub MCP の頁に当社の記録を載せています。

登録が 10000 件たまり、全部の車線が約 50 分止まった

GitHub の文書は、1 つの runner group に同時に登録できる作業員を 10,000 としています(Actions limits・2026-10-30 に見た)。当社はこの上限に当たりました。

VM の台本の 1 行に不具合がありました。bash 3.2 で set -u を付けていると、空の配列が unbound variable で落ちます。そのため JIT を発行した直後に組が毎回即死し、消されない offline の登録が 24 時間で runner group に 10000 件たまりました。上限に当たって、全部の車線が約 50 分止まりました。ログには毎分「max limit of 10000」が出ていたのに、それを知らせる口がありませんでした(出典: 社の実測 2026-10-16(当社の CI の記録))。

そこで 2 つを足しました(出典: 社の実測 2026-10-16(当社の CI の記録))。

足した物中身試した結果
掃除300 秒おきに、offline で、job を持たず、名前の時刻から 600 秒を超えた登録を消す捨てた登録は 20 分 4 秒で消えた
知らせる口JIT の発行の失敗が 5 分続くか、登録が 8000 を超えたら知らせる試しで 5 分 34 秒で知らせが出た

出典: 社の実測 2026-10-16(当社の CI の記録)。

JIT の発行も、API の上限を食う

JIT の設定の発行は、GitHub の REST API を 1 回撃つ事です。当社では 10 分で 31 本の JIT の発行が、全員で共有している 1 つの口座の上限(1 時間 5000)を食っていました。上限が切れている間は、VM が登録できません。そこで JIT の発行だけを、専用の GitHub App のトークンに分けました(出典: 社の実測 2026-10-13(当社の CI の記録))。

GitHub の文書も、個人の認証の上限を 1 時間 5,000 としています(Actions limits・2026-10-30 に見た)。1 つの口座を全員で共有していると、席の仕事と作業員の発行が同じ上限を取り合います。

自前に寄せる前に確かめる事

当社の記録から、寄せる前に確かめておけば止まらずに済んだ所を並べます。

  • 遅くなったら、まず CPU ではなく作業員の台数と待ちの時間を見る(社の実測 2026-10-10)
  • 本番の鍵を使う job は自前に回さない。ラベルを付ける前に secrets.* の参照を数える(社の実測 2026-10-10)
  • 登録の数と JIT の発行の失敗に、知らせる口を付ける。ログに出ているだけでは誰も気づかない(社の実測 2026-10-16)
  • JIT の発行のトークンを、席の仕事のトークンと分ける(社の実測 2026-10-13)
  • Spot の回収で赤になった job の撃ち直しを用意する。merge 待ちの列から落ちた PR は別に戻す(社の実測 2026-10-11)

席が書いた試験そのものの任せ方は AI テスト自動化 の頁にあります。

よくある質問

self-hosted runner は無料ですか?

GitHub の文書では、GitHub Actions で使うのは無料で、作業員の機械を保つ費用は自分持ちです(Self-hosted runners・2026-10-30 に見た)。当社は GitHub がホストする作業員の組織の使用量の上限に当たったのを機に、自前に寄せました(社の実測 2026-10-09)。

ephemeral runner とは何ですか?

1 つの job を処理した後に、GitHub Actions が自動で登録を外す作業員です。--ephemeral を付けて登録するか、REST API で JIT の作業員を作ります(Self-hosted runners reference・2026-10-30 に見た)。当社は 1 job に 1 台の VM を立て、job の後に VM ごと消しています。

自前の作業員にしたのに CI が遅くなりました

台数が足りずに job が待っている事があります。当社では寄せた直後に CI 1 回が GitHub のころの 2〜4 倍になり、CPU は 23% 空いていました(社の実測 2026-10-10)。当社は 1 job に 1 台の使い捨ての作業員を立てる形にしています(社の実測 2026-10-10)。

Spot VM で job が「runner lost communication」で落ちます

走っている途中で VM が回収されると、その job は lost communication で赤になります。当社は回収の監査ログを 30 秒おきに見て、failure で lost communication で run が終わった job だけを 1 回撃ち直しています(社の実測 2026-10-11)。

runner group の登録の上限は何件ですか?

GitHub の文書では、1 つの runner group に同時に登録できるのは 10,000 です(Actions limits・2026-10-30 に見た)。当社は消されない offline の登録が 24 時間でこの上限にたまり、全部の車線が約 50 分止まりました(社の実測 2026-10-16)。

出典

  1. GitHub Docs「Self-hosted runners」 https://docs.github.com/en/actions/concepts/runners/self-hosted-runners(2026-10-30 に見た・self-hosted runner の定義・無料で機械の費用は自分持ち・OS とソフトの更新の受け持ち)
  2. GitHub Docs「Self-hosted runners reference」 https://docs.github.com/en/actions/reference/runners/self-hosted-runners(2026-10-30 に見た・--ephemeral と 1 job の後の自動の登録外し・REST API の JIT の作業員・persistent の作業員での台数の増減を勧めない事)
  3. GitHub Docs「REST API endpoints for self-hosted runners」 https://docs.github.com/en/rest/actions/self-hosted-runners(2026-10-30 に見た・generate-jitconfig の道・要る項目・encoded_jit_config)
  4. GitHub Docs「Actions limits」 https://docs.github.com/en/actions/reference/limits(2026-10-30 に見た・runner group ごとの同時の登録 10,000・個人の認証の上限 1 時間 5,000)
  5. 社の実測 2026-10-09(当社の CI の記録・使用量が 9 日で先月分を超え上限に当たった事)
  6. 社の実測 2026-10-10(当社の CI の記録・寄せた直後の CI の時間と CPU の空き・1 job 1 台の方式と線・1 本目の検証)
  7. 社の実測 2026-10-11(当社の CI の記録・Spot の回収と撃ち直し・merge 待ちの列から落ちた PR)
  8. 社の実測 2026-10-13(当社の CI の記録・VM の空き時間・最初の 6 分の台数・JIT の発行と API の上限)
  9. 社の実測 2026-10-15(当社の CI の記録・約 2 分で落ちる VM と見張りの直し)
  10. 社の実測 2026-10-16(当社の CI の記録・登録の上限と掃除・知らせる口)