GitHub Actions ランナーのオートスケール運用:Kubernetes/actions-runner-controller 実践
GitHub Actions のワークフローを実行する際、GitHub が提供するホストランナーだけでは性能やコストの面で課題に直面することがあります。特に大規模な開発チームでは、セルフホストランナーを Kubernetes 上で運用し、必要に応じて自動でスケールさせる仕組みが求められるでしょう。
本記事では、Kubernetes 上で GitHub Actions ランナーをオートスケール運用するための実践的な方法を、actions-runner-controller(ARC)を使って詳しく解説していきます。実際の設定例やトラブルシューティングまで含めて、すぐに実践できる内容をお届けしますね。
背景
GitHub Actions とセルフホストランナーの関係性
GitHub Actions は、CI/CD パイプラインを自動化するための強力なプラットフォームです。ワークフローを実行するためには「ランナー」と呼ばれる実行環境が必要になります。
GitHub が提供する標準のホストランナーは、Linux、Windows、macOS など複数の環境が用意されており、すぐに使い始められるのが魅力です。しかし、実際の開発現場では以下のようなニーズが生まれてきます。
セルフホストランナーを導入することで、自社のインフラ上でワークフローを実行でき、より柔軟な環境設定やコスト最適化が可能になるのです。
Kubernetes による運用の利点
Kubernetes は、コンテナオーケストレーションのデファクトスタンダードとして広く採用されています。GitHub Actions のセルフホストランナーを Kubernetes 上で運用することで、以下のメリットが得られるでしょう。
| # | 項目 | 説明 |
|---|---|---|
| 1 | リソース効率化 | ノードプールを共有し、他のワークロードと統合管理できる |
| 2 | 自動復旧 | Pod の異常時に自動で再起動し、可用性を向上させる |
| 3 | スケーラビリティ | HPA や VPA による柔軟なスケーリングが可能 |
| 4 | 宣言的管理 | YAML マニフェストで設定を管理し、GitOps と連携できる |
| 5 | マルチテナント | Namespace による論理的な分離で複数チームに対応 |
図の意図:GitHub Actions ワークフローがどのように Kubernetes クラスタ上のランナーで実行されるかを示します。
mermaidflowchart TB
dev["開発者"] -->|push/PR| gh["GitHub<br/>リポジトリ"]
gh -->|webhook| ghapi["GitHub Actions<br/>API"]
ghapi -->|ジョブ割り当て| runner1["Runner Pod 1"]
ghapi -->|ジョブ割り当て| runner2["Runner Pod 2"]
ghapi -->|ジョブ割り当て| runner3["Runner Pod 3"]
subgraph k8s["Kubernetes クラスタ"]
runner1
runner2
runner3
end
runner1 -->|結果報告| ghapi
runner2 -->|結果報告| ghapi
runner3 -->|結果報告| ghapi
ghapi -->|ステータス更新| gh
gh -->|通知| dev
この図が示すように、開発者がコードをプッシュすると、GitHub Actions API がジョブを Kubernetes クラスタ上のランナー Pod に割り当て、実行結果を GitHub に返す流れとなります。
actions-runner-controller の登場
actions-runner-controller(ARC)は、Kubernetes 上で GitHub Actions のセルフホストランナーを管理するための Kubernetes Operator です。GitHub 社の公式サポートを受けており、エンタープライズ環境でも安心して利用できますね。
ARC は以下の機能を提供しています。
- 自動登録:ランナーを GitHub リポジトリ/Organization に自動登録
- オートスケール:ワークフローのキュー状況に応じて Pod 数を調整
- ライフサイクル管理:ジョブ実行後のクリーンアップと再利用
- マルチテナント対応:複数のリポジトリや Organization を一元管理
課題
ホストランナーの制限事項
GitHub が提供するホストランナーには、いくつかの制約が存在します。実際の開発現場では、これらの制限に直面することが少なくありません。
実行時間の制限
パブリックリポジトリでは 1 ジョブあたり最大 6 時間、プライベートリポジトリでは月間の実行時間に上限があります。大規模なビルドやテストを実行する場合、この制限がボトルネックになることがあるでしょう。
カスタマイズの難しさ
特定のツールやライブラリがプリインストールされていない場合、毎回のワークフロー実行時にインストール作業が必要になります。これは実行時間の増加とコストの増大につながりますね。
セキュリティとコンプライアンス
プライベートな Docker レジストリや内部 API へのアクセスが必要な場合、ホストランナーからは接続できないケースがあります。企業のセキュリティポリシーによっては、外部環境でのコード実行が許可されないこともあるでしょう。
セルフホストランナーの運用課題
セルフホストランナーを導入すれば上記の制限は解消できますが、今度は運用面での新たな課題が生まれます。
図の意図:セルフホストランナーを手動運用する際の課題を示します。
mermaidflowchart LR
job["ワークフロー<br/>ジョブ"] -->|待機| queue["ジョブキュー"]
queue -->|実行要求| check{ランナー<br/>空きあり?}
check -->|Yes| exec["実行"]
check -->|No| wait["待機状態"]
wait -->|タイムアウト| fail["失敗"]
style wait fill:#ffcccc
style fail fill:#ff6666
スケーリングの難しさ
固定数のランナーを用意すると、ピーク時にはリソース不足、閑散時には無駄なコストが発生します。手動でのスケーリングは運用負荷が高く、現実的ではありません。
メンテナンスの負担
ランナーのバージョンアップ、セキュリティパッチの適用、環境のクリーンアップなど、継続的なメンテナンス作業が必要です。複数のランナーを個別に管理するのは非効率的ですね。
リソース管理の複雑さ
CPU、メモリ、ディスク容量などのリソース配分を適切に行わないと、ジョブの失敗やノード全体のパフォーマンス低下を招きます。特に複数のワークフローが並行実行される環境では、リソース競合が発生しやすくなるでしょう。
以下の表に、主な運用課題をまとめました。
| # | 課題カテゴリ | 具体的な問題 | 影響 |
|---|---|---|---|
| 1 | スケーラビリティ | 手動でのランナー数調整が必要 | 開発速度の低下、コスト増 |
| 2 | 可用性 | ランナー障害時の自動復旧なし | ワークフロー失敗率の上昇 |
| 3 | セキュリティ | 使用済みランナーのクリーンアップ漏れ | 情報漏洩リスク |
| 4 | 運用効率 | バージョン管理やパッチ適用の手間 | 運用コストの増大 |
| 5 | 可視性 | ランナーの状態監視が困難 | トラブルシューティングの遅延 |
解決策
actions-runner-controller による統合管理
これらの課題を解決するのが、actions-runner-controller(ARC)です。ARC は Kubernetes の宣言的な管理の仕組みを活用し、GitHub Actions ランナーのライフサイクル全体を自動化してくれます。
Custom Resource Definition(CRD)による管理
ARC は Kubernetes の CRD を利用して、ランナーの設定を YAML マニフェストで定義できるようにします。これにより、インフラのコード化(Infrastructure as Code)が実現し、バージョン管理や変更履歴の追跡が容易になりますね。
Webhook ベースのオートスケール
GitHub からの Webhook を受信して、リアルタイムにワークフローのキュー状況を把握します。待機中のジョブ数に応じて、自動的にランナー Pod を増減させることができるのです。
図の意図:ARC がどのように GitHub Actions と連携してオートスケールを実現するかを示します。
mermaidflowchart TB
gh["GitHub Actions"] -->|webhook| arc["ARC<br/>Controller"]
arc -->|監視| hpa["HorizontalRunner<br/>Autoscaler"]
hpa -->|スケール指示| deployment["RunnerDeployment"]
deployment -->|Pod作成/削除| pods["Runner Pods"]
subgraph k8s["Kubernetes クラスタ"]
arc
hpa
deployment
pods
end
pods -->|ジョブ取得| gh
pods -->|結果送信| gh
style arc fill:#e1f5ff
style hpa fill:#fff4e1
style deployment fill:#e8f5e8
主要コンポーネントの役割
| # | コンポーネント | 役割 |
|---|---|---|
| 1 | Controller Manager | CRD リソースの監視と調整ループの実行 |
| 2 | RunnerDeployment | ランナー Pod のテンプレートと複製数の管理 |
| 3 | RunnerSet | ステートフルなランナーの管理(永続ボリューム対応) |
| 4 | HorizontalRunnerAutoscaler | メトリクスベースでの自動スケーリング |
| 5 | Webhook Server | GitHub からの Webhook 受信とスケール判定 |
主要な設定リソース
ARC を使用する際に理解しておくべき主要なリソースタイプを紹介します。
RunnerDeployment リソース
最も基本的なリソースで、ステートレスなランナー群を管理します。Kubernetes の Deployment と同様の概念で、指定した複製数の Runner Pod を維持してくれますね。
HorizontalRunnerAutoscaler リソース
RunnerDeployment と組み合わせて使用し、ワークフローのキュー状況に基づいて自動的にランナー数を調整します。最小・最大レプリカ数を指定でき、急激なスケールアウトやコスト超過を防げるでしょう。
認証方式の選択
ARC は複数の認証方式をサポートしています。
- Personal Access Token(PAT):個人アカウントベースの認証
- GitHub App:Organization レベルでの管理に適した方式
- GitHub Enterprise Server:オンプレミス環境向け
本番環境では、セキュリティと管理性の観点から GitHub App による認証が推奨されます。
スケーリング戦略
ARC は複数のスケーリング戦略を提供しており、ワークフローの特性に応じて選択できます。
パーセンテージベーススケーリング
現在の実行中ジョブ数に対する割合で、追加するランナー数を決定します。安定したトラフィックパターンを持つ環境に適していますね。
Webhook ドリブンスケーリング
GitHub からの workflow_job Webhook をリアルタイムに受信し、即座にスケールアウトします。レスポンスタイムを最小化したい場合に有効な戦略です。
スケジュールベーススケーリング
時間帯や曜日に応じて、事前にランナー数を調整します。定期的なバッチ処理やピーク時間が予測可能な場合に便利でしょう。
具体例
環境構築の前提条件
実際に ARC を導入する手順を見ていきましょう。以下の環境が整っていることを前提とします。
| # | 項目 | 要件 |
|---|---|---|
| 1 | Kubernetes クラスタ | v1.24 以上(推奨:v1.28 以上) |
| 2 | kubectl | クラスタへのアクセス権限を持つ設定済み CLI |
| 3 | Helm | v3.8 以上 |
| 4 | GitHub アカウント | Organization の管理者権限 |
| 5 | cert-manager | Webhook 用の証明書管理(オプション) |
GitHub App の作成
まず、ARC が GitHub API にアクセスするための GitHub App を作成します。この方法が最もセキュアで、Organization レベルでの管理に適しています。
GitHub App の登録手順
- GitHub Organization の Settings を開く
- Developer settings → GitHub Apps → New GitHub App をクリック
- 必要な情報を入力
以下の permissions が必要になります。
yaml# Repository permissions
actions: read
administration: read/write
checks: read
metadata: read
# Organization permissions
self_hosted_runners: read/write
Webhook の設定
GitHub App には Webhook URL を設定し、workflow_job イベントを購読するようにします。この設定により、ジョブの状態変化をリアルタイムに検知できるようになりますね。
textWebhook URL: https://your-arc-webhook.example.com/webhook
Webhook secret: <安全なランダム文字列>
Subscribe to events:
- Workflow job (workflow_job)
App の秘密鍵とインストール
GitHub App を作成したら、秘密鍵(Private Key)を生成してダウンロードします。この鍵は後ほど Kubernetes Secret として登録することになります。
作成した App を Organization にインストールし、アクセスを許可するリポジトリを選択しましょう。
Helm による ARC のインストール
Helm チャートを使用して、ARC を Kubernetes クラスタにデプロイします。まずは Helm リポジトリの追加から始めますね。
bash# ARC の Helm リポジトリを追加
helm repo add actions-runner-controller \
https://actions-runner-controller.github.io/actions-runner-controller
# リポジトリ情報を更新
helm repo update
Namespace の作成
ARC 専用の Namespace を作成し、リソースを論理的に分離します。
bash# actions-runner-system という Namespace を作成
kubectl create namespace actions-runner-system
GitHub App の認証情報を Secret に登録
ダウンロードした秘密鍵を Kubernetes Secret として登録します。
bash# GitHub App の秘密鍵を Secret に登録
kubectl create secret generic controller-manager \
-n actions-runner-system \
--from-literal=github_app_id=123456 \
--from-literal=github_app_installation_id=78901234 \
--from-file=github_app_private_key=path/to/private-key.pem
ここで、github_app_id は GitHub App の ID、github_app_installation_id は Organization にインストールした際に割り振られた ID です。これらは GitHub の App 設定ページから確認できますね。
ARC Controller のインストール
values.yaml ファイルを作成し、必要な設定をカスタマイズします。
yaml# values.yaml
authSecret:
enabled: true
create: false
name: 'controller-manager'
# GitHub Webhook の設定
githubWebhookServer:
enabled: true
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
# リソース制限の設定
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 200m
memory: 256Mi
次に、この values.yaml を使用して Helm チャートをインストールします。
bash# ARC Controller をインストール
helm install actions-runner-controller \
actions-runner-controller/actions-runner-controller \
-n actions-runner-system \
-f values.yaml \
--wait
インストールが完了したら、Pod が正常に起動しているか確認しましょう。
bash# ARC Controller の状態確認
kubectl get pods -n actions-runner-system
# ログを確認してエラーがないかチェック
kubectl logs -n actions-runner-system \
-l app.kubernetes.io/name=actions-runner-controller
RunnerDeployment の設定
ARC がインストールできたら、実際にランナーをデプロイする設定を作成します。まずはシンプルな RunnerDeployment から始めますね。
yaml# runner-deployment.yaml
apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
name: example-runner
namespace: actions-runner-system
spec:
# レプリカ数(HPA を使う場合は指定不要)
replicas: 1
template:
spec:
# Organization レベルでランナーを登録
organization: your-organization
# ランナーグループの指定(オプション)
runnerGroup: default
この設定では、your-organization という Organization に対してランナーを登録します。リポジトリ単位で登録する場合は、repository: owner/repo-name という形式で指定できますね。
ランナーのラベル設定
ワークフローから特定のランナーを指定できるよう、ラベルを設定します。
yaml# runner-deployment.yaml(ラベル設定を追加)
spec:
template:
spec:
organization: your-organization
# カスタムラベルの設定
labels:
- self-hosted
- linux
- x64
- kubernetes
ワークフロー側では、runs-on フィールドでこれらのラベルを指定できます。
yaml# .github/workflows/example.yml
jobs:
build:
runs-on: [self-hosted, kubernetes]
steps:
- uses: actions/checkout@v4
- run: echo "Running on Kubernetes!"
Docker イメージのカスタマイズ
デフォルトのランナーイメージには基本的なツールしか含まれていません。プロジェクトに必要なツールをプリインストールしたカスタムイメージを使用することで、ワークフローの実行時間を短縮できるでしょう。
yamlspec:
template:
spec:
organization: your-organization
labels:
- self-hosted
- kubernetes
- nodejs
# カスタム Docker イメージの指定
image: ghcr.io/your-org/custom-runner:latest
imagePullPolicy: Always
# プライベートレジストリ用の認証
imagePullSecrets:
- name: ghcr-secret
カスタムイメージの Dockerfile 例を示します。
dockerfile# Dockerfile
FROM ghcr.io/actions/actions-runner:latest
# 必要なツールをインストール
USER root
RUN apt-get update && apt-get install -y \
build-essential \
curl \
git \
&& rm -rf /var/lib/apt/lists/*
この Dockerfile では、actions-runner の公式イメージをベースに、追加のビルドツールをインストールしています。
Node.js などの特定のランタイムを追加する場合は、以下のように記述します。
dockerfile# Node.js のインストール
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs \
&& npm install -g yarn
USER runner
オートスケール設定
RunnerDeployment だけでは固定数のランナーしか起動しません。HorizontalRunnerAutoscaler リソースを追加して、動的なスケーリングを実現しましょう。
yaml# runner-hpa.yaml
apiVersion: actions.summerwind.dev/v1alpha1
kind: HorizontalRunnerAutoscaler
metadata:
name: example-runner-autoscaler
namespace: actions-runner-system
spec:
# スケール対象の RunnerDeployment
scaleTargetRef:
kind: RunnerDeployment
name: example-runner
# 最小・最大レプリカ数
minReplicas: 1
maxReplicas: 10
この設定により、ランナー数は 1 から 10 の範囲で自動調整されます。最小レプリカ数を 1 以上にすることで、ジョブの初回実行時の待機時間を短縮できますね。
Webhook ベースのスケーリング設定
より高度なスケーリングには、GitHub からの Webhook を活用します。
yamlspec:
scaleTargetRef:
kind: RunnerDeployment
name: example-runner
minReplicas: 1
maxReplicas: 10
# Webhook ベースのスケーリング
scaleUpTriggers:
- githubEvent:
workflowJob: {}
amount: 1
duration: '5m'
scaleDownDelaySecondsAfterScaleOut: 300
この設定では、workflow_job イベントを受信するたびに 1 つのランナーを追加し、5 分間その状態を維持します。スケールアウト後、300 秒(5 分)経過してから段階的にスケールダウンを開始する仕組みですね。
メトリクスベースのスケーリング
ジョブキューの長さに応じてスケールする設定も可能です。
yamlspec:
scaleTargetRef:
kind: RunnerDeployment
name: example-runner
minReplicas: 2
maxReplicas: 20
# メトリクスベースのスケーリング
metrics:
- type: TotalNumberOfQueuedAndInProgressWorkflowRuns
repositoryNames:
- your-organization/repo1
- your-organization/repo2
この設定では、指定したリポジトリのキュー中および実行中のワークフロー数に基づいてスケールします。待機中のジョブが増えると、自動的にランナーが追加されるでしょう。
リソース制限の設定
各ランナー Pod に適切なリソース制限を設定することで、Kubernetes クラスタ全体の安定性を保てます。
yaml# runner-deployment.yaml(リソース設定を追加)
spec:
template:
spec:
organization: your-organization
# Pod レベルのリソース設定
resources:
limits:
cpu: '4'
memory: '8Gi'
ephemeral-storage: '20Gi'
requests:
cpu: '1'
memory: '2Gi'
ephemeral-storage: '10Gi'
ここでは、各ランナーが最大 4 コア、8GB メモリ、20GB のエフェメラルストレージを使用でき、最低でも 1 コア、2GB メモリが保証されます。
ボリュームマウントの設定
Docker-in-Docker(DinD)を使用してコンテナビルドを行う場合、適切なボリューム設定が必要です。
yamlspec:
template:
spec:
organization: your-organization
# DinD を有効化
dockerEnabled: true
dockerdWithinRunnerContainer: true
# ボリュームマウント
volumeMounts:
- name: work
mountPath: /home/runner/_work
volumes:
- name: work
emptyDir: {}
この設定により、ワークディレクトリが emptyDir ボリュームとしてマウントされ、ジョブ実行時のディスク I/O パフォーマンスが向上しますね。
実際のデプロイと動作確認
ここまで作成した YAML マニフェストを適用して、実際にランナーをデプロイしましょう。
bash# RunnerDeployment を適用
kubectl apply -f runner-deployment.yaml
# HorizontalRunnerAutoscaler を適用
kubectl apply -f runner-hpa.yaml
デプロイ後、ランナーの状態を確認します。
bash# RunnerDeployment の状態確認
kubectl get runnerdeployments -n actions-runner-system
# Runner Pod の状態確認
kubectl get runners -n actions-runner-system
# Pod の詳細を確認
kubectl get pods -n actions-runner-system \
-l app.kubernetes.io/name=example-runner
図の意図:リソース適用からランナーが GitHub に登録されるまでの流れを示します。
mermaidsequenceDiagram
participant User as 管理者
participant K8s as Kubernetes API
participant ARC as ARC Controller
participant Pod as Runner Pod
participant GH as GitHub API
User->>K8s: kubectl apply<br/>RunnerDeployment
K8s->>ARC: リソース作成イベント
ARC->>K8s: Pod 作成リクエスト
K8s->>Pod: Pod 起動
Pod->>GH: ランナー登録API
GH-->>Pod: 登録トークン
Pod->>GH: ランナー認証
GH-->>User: ランナーがオンライン
この図から、管理者が YAML を適用してから、実際に GitHub にランナーが登録されるまでの一連の流れが理解できますね。
GitHub UI での確認
GitHub の Organization 設定ページで、ランナーが正常に登録されているか確認できます。
- Organization の Settings を開く
- Actions → Runners メニューに移動
- Self-hosted runners セクションにランナーが表示される
ランナーのステータスが「Idle」になっていれば、ジョブを受け付ける準備ができています。
テストワークフローの実行
簡単なワークフローを実行して、セルフホストランナーが正常に動作するか確認しましょう。
yaml# .github/workflows/test-runner.yml
name: Test Self-Hosted Runner
on:
workflow_dispatch:
jobs:
test:
runs-on: [self-hosted, kubernetes]
steps:
- name: Echo hostname
run: echo "Running on $(hostname)"
- name: Check resources
run: |
echo "CPU cores: $(nproc)"
echo "Memory: $(free -h | grep Mem | awk '{print $2}')"
echo "Disk space: $(df -h / | tail -1 | awk '{print $4}')"
このワークフローを手動実行(workflow_dispatch)し、ログに Pod 名やリソース情報が表示されれば成功です。
トラブルシューティング
実際の運用では、さまざまな問題に遭遇することがあります。代表的なエラーとその解決方法を紹介しますね。
エラー 1: ランナーが GitHub に登録されない
textError: POST https://api.github.com/orgs/your-org/actions/runners/registration-token: 401 Unauthorized
このエラーは、GitHub App の認証情報が正しくないか、権限が不足していることを示しています。
解決手順
- GitHub App の秘密鍵が正しく Secret に登録されているか確認
- GitHub App ID と Installation ID が正しいか検証
- GitHub App に必要な permissions が付与されているか確認
bash# Secret の内容を確認(値は表示されない)
kubectl describe secret controller-manager -n actions-runner-system
# ARC Controller のログでエラー詳細を確認
kubectl logs -n actions-runner-system \
-l app.kubernetes.io/name=actions-runner-controller \
--tail=100
エラー 2: Pod が ImagePullBackOff 状態
textError: Failed to pull image "ghcr.io/your-org/custom-runner:latest":
rpc error: code = Unknown desc = failed to pull and unpack image:
failed to resolve reference: unauthorized
プライベートコンテナレジストリへの認証に失敗しています。
解決手順
まず、コンテナレジストリへの認証情報を含む Secret を作成します。
bash# GitHub Container Registry(GHCR)用の Secret 作成
kubectl create secret docker-registry ghcr-secret \
-n actions-runner-system \
--docker-server=ghcr.io \
--docker-username=your-username \
--docker-password=your-token \
--docker-email=your-email@example.com
次に、RunnerDeployment で imagePullSecrets を指定します。
yamlspec:
template:
spec:
imagePullSecrets:
- name: ghcr-secret
エラー 3: スケールアウトが機能しない
Webhook を設定したのに、ジョブが実行待ちになっているにもかかわらずランナーが増えないケースがあります。
解決手順
Webhook Server が正常に動作しているか確認します。
bash# Webhook Server の Pod を確認
kubectl get pods -n actions-runner-system \
-l app.kubernetes.io/component=webhook-server
# Webhook Server のログを確認
kubectl logs -n actions-runner-system \
-l app.kubernetes.io/component=webhook-server \
--tail=50
GitHub 側の Webhook 設定も確認しましょう。
- GitHub App の Settings を開く
- Webhook セクションで Recent Deliveries を確認
- Response が 200 OK でない場合は、URL や Secret が正しいか検証
エラー 4: ジョブ実行後にランナーがクリーンアップされない
使用済みのランナー Pod が残り続け、リソースを消費し続けることがあります。
解決手順
RunnerDeployment にクリーンアップポリシーを設定します。
yamlspec:
template:
spec:
# ジョブ実行後に Pod を削除
ephemeral: true
# タイムアウト設定
workVolumeClaimTemplate:
storageClassName: standard
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
ephemeral: true を設定することで、ジョブ完了後に自動的に Pod が削除され、次のジョブには新しい Pod が起動されますね。
監視とメトリクス収集
ARC の運用状態を可視化するために、Prometheus と Grafana を使った監視を設定しましょう。
Prometheus ServiceMonitor の作成
ARC は Prometheus メトリクスをエクスポートします。ServiceMonitor リソースを作成して、メトリクスを収集する設定を行います。
yaml# servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: actions-runner-controller
namespace: actions-runner-system
spec:
selector:
matchLabels:
app.kubernetes.io/name: actions-runner-controller
endpoints:
- port: metrics
interval: 30s
この設定により、30 秒ごとに ARC のメトリクスが収集されます。
主要なメトリクス
ARC が提供する重要なメトリクスをまとめました。
| # | メトリクス名 | 説明 |
|---|---|---|
| 1 | runner_pods_total | 現在稼働中のランナー Pod 数 |
| 2 | runner_jobs_queued | GitHub のジョブキューに待機中のジョブ数 |
| 3 | runner_jobs_running | 実行中のジョブ数 |
| 4 | runner_reconciliation_duration_seconds | コントローラーの調整ループ実行時間 |
| 5 | runner_deployment_spec_replicas | RunnerDeployment で指定されたレプリカ数 |
これらのメトリクスを Grafana でダッシュボード化すると、スケーリングの状況やリソース使用率が一目で把握できるようになりますね。
アラート設定例
Prometheus のアラートルールを設定して、異常を早期検知できるようにします。
yaml# prometheus-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: arc-alerts
namespace: actions-runner-system
spec:
groups:
- name: actions-runner-controller
interval: 30s
rules:
- alert: RunnerJobQueueTooLong
expr: runner_jobs_queued > 10
for: 5m
labels:
severity: warning
annotations:
summary: 'ジョブキューが長時間滞留'
description: '{{ $value }}個のジョブが5分以上待機しています'
このアラートは、10 個以上のジョブが 5 分間キューに滞留した場合に発火し、スケールアップが追いついていない可能性を通知してくれます。
まとめ
本記事では、Kubernetes 上で GitHub Actions のセルフホストランナーをオートスケール運用する方法を、actions-runner-controller(ARC)を使って実践的に解説してきました。
GitHub が提供するホストランナーの制限を克服し、自社のインフラ上で柔軟かつコスト効率の良い CI/CD 環境を構築できることがお分かりいただけたのではないでしょうか。
ARC を導入することで得られる主なメリットをまとめると、以下のようになります。
運用面での改善
- ワークフローのキュー状況に応じた自動スケーリングによる待機時間の削減
- Kubernetes の宣言的な管理による設定の標準化とバージョン管理
- Pod ベースのクリーンな実行環境による セキュリティリスクの低減
コスト面での最適化
- 必要な時だけランナーを起動することでクラウドリソースの効率的活用
- カスタムイメージの使用によるワークフロー実行時間の短縮
- 既存の Kubernetes クラスタを活用した追加インフラ投資の削減
開発生産性の向上
- プライベートリソースへのアクセスによる開発フローの改善
- チーム固有のツールをプリインストールした環境の提供
- ビルド時間の短縮によるフィードバックループの高速化
実際の導入にあたっては、まず小規模な RunnerDeployment から始めて、段階的にオートスケール機能を追加していくアプローチがおすすめです。運用を通じて得られたメトリクスを分析し、スケーリング戦略を最適化していくことで、より効率的な CI/CD 環境が実現できるでしょう。
GitHub Actions と Kubernetes を組み合わせることで、モダンな開発ワークフローを支える強固な基盤を構築できます。ぜひ本記事の内容を参考に、皆さんの環境でも実践してみてくださいね。
関連リンク
articleGitHub Actions ランナーのオートスケール運用:Kubernetes/actions-runner-controller 実践
articleGitHub Actions のジョブ分割設計:needs と outputs でデータを安全に受け渡す
articleGitHub Actions コンテキスト&式の早見表:fromJson/toJson/hashFiles まで
articleGitHub Actions で PostgreSQL/Redis を services で立ち上げるテスト基盤レシピ
articleGitHub Actions 署名戦略を比べる:SHA ピン留め vs タグ参照 vs バージョン範囲
articleGitHub Actions のキャッシュがヒットしない原因 10 と対処レシピ
articleHaystack で最小の検索 QA を作る:Retriever + Reader の 30 分ハンズオン
articleJest のフレークテスト撲滅作戦:重試行・乱数固定・リトライ設計の実務
articleGitHub Copilot セキュア運用チェックリスト:権限・ポリシー・ログ・教育の定着
articleGrok で社内 FAQ ボット:ナレッジ連携・権限制御・改善サイクル
articleGitHub Actions ランナーのオートスケール運用:Kubernetes/actions-runner-controller 実践
articleClips AI で書き出しが止まる時の原因切り分け:メモリ不足・コーデック・権限
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来