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 に見た)。
| 順 | やる事 | 当社で決めた線 |
|---|---|---|
| 1 | job が待っている分だけ、JIT の設定を発行する | 発行には GitHub の API を使う。発行の口は専用のトークンに分ける(下の節) |
| 2 | Spot VM を立て、JIT の設定を渡して runner を 1 回だけ動かす | VM にはサービスアカウントを付けない。入りは全部拒否の専用の VPC に置く |
| 3 | 自前の作業員に回す job を、ラベルで選ぶ | deploy や本番の鍵を使う job にはラベルを付けない。付ける前に、その workflow で secrets.* の参照が 0 本である事を確かめる |
| 4 | job が終わったら、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 回撃ち直します。
- 結果が failure である
- 失敗の理由が lost communication である
- その 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)。
出典
- GitHub Docs「Self-hosted runners」 https://docs.github.com/en/actions/concepts/runners/self-hosted-runners(2026-10-30 に見た・self-hosted runner の定義・無料で機械の費用は自分持ち・OS とソフトの更新の受け持ち)
- 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 の作業員での台数の増減を勧めない事) - 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) - GitHub Docs「Actions limits」 https://docs.github.com/en/actions/reference/limits(2026-10-30 に見た・runner group ごとの同時の登録 10,000・個人の認証の上限 1 時間 5,000)
- 社の実測 2026-10-09(当社の CI の記録・使用量が 9 日で先月分を超え上限に当たった事)
- 社の実測 2026-10-10(当社の CI の記録・寄せた直後の CI の時間と CPU の空き・1 job 1 台の方式と線・1 本目の検証)
- 社の実測 2026-10-11(当社の CI の記録・Spot の回収と撃ち直し・merge 待ちの列から落ちた PR)
- 社の実測 2026-10-13(当社の CI の記録・VM の空き時間・最初の 6 分の台数・JIT の発行と API の上限)
- 社の実測 2026-10-15(当社の CI の記録・約 2 分で落ちる VM と見張りの直し)
- 社の実測 2026-10-16(当社の CI の記録・登録の上限と掃除・知らせる口)