Introduction
Actions Runner Controller (ARC) is a Kubernetes operator that manages self-hosted GitHub Actions runners. It automatically scales runner pods up and down based on pending workflow jobs, eliminating the need to maintain a fixed pool of idle VMs while keeping CI/CD jobs close to your infrastructure.
What Actions Runner Controller Does
- Provisions ephemeral GitHub Actions runner pods on Kubernetes in response to queued workflow jobs
- Scales runner replicas from zero to the configured maximum based on real-time job demand
- Supports organization-level, repository-level, and enterprise-level runner groups
- Cleans up runner pods after each job completes, ensuring a fresh environment for every workflow run
- Integrates with GitHub's official runner scale set API for reliable job assignment
Architecture Overview
ARC consists of two Helm charts: a controller that watches for pending GitHub Actions jobs, and runner scale sets that define the runner template and scaling parameters. The controller registers with GitHub as a listener for workflow job events. When a job is queued that matches a scale set's labels, the controller creates a runner pod from the configured template. The pod registers itself as a GitHub runner, executes the job, and then terminates. A metrics-based autoscaler adjusts the replica count based on the ratio of pending jobs to available runners.
Self-Hosting & Configuration
- Install the controller and at least one runner scale set using the official Helm charts from ghcr.io
- Authenticate using a GitHub App (recommended) or a personal access token with repo and admin:org scopes
- Customize the runner pod template with init containers, volume mounts, and resource requests for specialized workloads
- Configure Docker-in-Docker or Kubernetes mode for container actions that need to build images inside the runner
- Set minRunners and maxRunners on each scale set to control autoscaling bounds and cost
Key Features
- Scale-to-zero eliminates idle runner costs by terminating all pods when no jobs are pending
- Ephemeral runners ensure each workflow job runs in a clean pod, preventing state leakage between jobs
- Runner groups and labels route specific workflows to specialized runner scale sets with GPUs, ARM architecture, or custom toolchains
- Kubernetes-native runner mode executes each job step in a separate container within the pod, avoiding Docker-in-Docker overhead
- Helm-based deployment integrates with GitOps tools like Argo CD and Flux for declarative runner management
Comparison with Similar Tools
- GitHub-hosted runners — zero maintenance but limited customization and network access; ARC runs on your own infrastructure with full control
- Self-hosted VM runners — static VMs that must be pre-provisioned; ARC autoscales pods and cleans up after each job
- Buildkite — SaaS CI with self-hosted agents; ARC is free, open-source, and tightly integrated with GitHub Actions workflows
- GitLab Runner — autoscales on Kubernetes for GitLab CI; ARC does the same specifically for GitHub Actions
- Jenkins — general-purpose CI server; ARC provides native GitHub Actions compatibility without maintaining a separate CI system
FAQ
Q: Does ARC require a GitHub Enterprise account? A: No. ARC works with GitHub.com free and paid plans, as well as GitHub Enterprise Server and Enterprise Cloud.
Q: How does scale-to-zero work? A: When no jobs are pending, the controller scales the runner scale set to zero replicas. New pods are created within seconds when a matching job is queued.
Q: Can I use Docker inside ARC runners? A: Yes. Configure the runner pod with Docker-in-Docker (DinD) sidecar or use Kubernetes mode, which runs each step as a separate container without requiring a Docker daemon.
Q: What is the difference between ARC and the legacy actions-runner-controller? A: The current ARC (gha-runner-scale-set) is the officially supported version maintained by GitHub. The legacy summerwind/actions-runner-controller is a community project that is no longer recommended.