GitHub Actions Runners
GitHub Actions runners let workflow jobs run inside your Edka cluster instead of on GitHub-hosted runners. Edka installs and manages GitHub Actions Runner Controller (ARC), then creates private runner scale sets that are scoped to a GitHub repository or organization through your connected GitHub App.
Use private runners when CI jobs need access to cluster-local services, private network routes, custom node pools, larger machines, or Docker builds that you want to run inside your own infrastructure.
Requirements
Section titled “Requirements”- A connected GitHub integration with access to the repositories that will use the runners.
- An active cluster where you have write access.
- Enough worker capacity for the minimum and maximum runner counts you plan to configure.
- For Kubernetes container mode, a storage class if you want to override the default work volume storage.
- The VictoriaMetrics app installed on the cluster if you want the Metrics tab of a scale set (pod usage, job counts, and job analytics).
Install the controller
Section titled “Install the controller”- Open a cluster and go to Actions.
- Select Install controller.
- Choose the GitHub integration this cluster should use to register private runners.
- Confirm the install.
Edka installs the GitHub Actions Runner Controller add-on in the arc-systems
namespace. This add-on is managed from Cluster > Actions, not from the
generic Add-ons workflow, because the controller depends on the selected GitHub
App installation.
The Actions overview shows the controller add-on status, configured scale sets, maximum runner capacity, observed runner pods, and whether the Actions cache is on.
Create a runner scale set
Section titled “Create a runner scale set”- Open Cluster > Actions > Scale Sets.
- Select Add scale set.
- Set Name / runs-on label. This is the default label you use in GitHub workflow jobs.
- Optionally add extra runner labels, such as
linux,gpu, orprivate-network. - Select a GitHub repository, or choose Custom GitHub URL for an organization or repository URL.
- Set Min runners and Max runners.
- Choose a runner namespace. The default is
ci. - Choose the container mode, resources, and placement options.
- In Docker-in-Docker mode, optionally turn on Persistent BuildKit under Advanced to keep Docker image layers between jobs. See Persistent BuildKit.
- Save the scale set.
Each scale set creates an ARC gha-runner-scale-set installation in the runner
namespace. Edka also creates the required service account and GitHub App
credential secret for that namespace.
After the save, the scale set has its own page under Scale Sets with Overview, Metrics, Events, Logs, and Settings tabs. See Scale set pages.
Workflow usage
Section titled “Workflow usage”Copy the runs-on value shown in the Actions overview or on the scale set
page and use it in your workflow job.
jobs: build: runs-on: default steps: - uses: actions/checkout@v4 - run: pnpm install && pnpm testIf you configure extra runner labels, use the label set shown by Edka:
jobs: build: runs-on: [linux, private-network] steps: - uses: actions/checkout@v4 - run: pnpm testContainer modes
Section titled “Container modes”Docker-in-Docker
Section titled “Docker-in-Docker”Docker-in-Docker is the default mode. It starts a runner container and, when enabled, a privileged Docker daemon sidecar so workflows can build container images with Docker. The runner container and the Docker sidecar each have their own CPU, memory, and disk requests and limits.
Use this mode for workflows that need Docker commands such as docker build,
docker run, or image publishing. To keep image layers between jobs, turn on
Persistent BuildKit for the scale set.
Kubernetes jobs
Section titled “Kubernetes jobs”Kubernetes mode runs jobs through ARC’s Kubernetes container mode and uses a PVC for runner work storage.
Use this mode when workflows do not need a Docker daemon and you want job execution to fit more directly into Kubernetes scheduling and storage controls. Set Work PVC storage and, when needed, a storage class. The build cache is not available in this mode.
Switching the container mode of an existing scale set replaces its runners. Let running jobs finish first.
Placement and scaling
Section titled “Placement and scaling”- Min runners keeps warm runner capacity available for faster job starts.
- Max runners caps the number of concurrent runners ARC can create for the scale set.
- Runner container and DinD container set the CPU, memory, and ephemeral disk requests and limits for the pod. Requests reserve capacity on the node; limits cap what a job can use.
- Node pool pins runner pods to a specific Edka node pool by adding the
edka.io/nodepoolselector. - Apply taint tolerations lets runners schedule onto a selected tainted node pool.
Dedicated node pools are useful for isolating CI workloads, using larger build nodes, or keeping privileged Docker-in-Docker jobs away from application workloads.
Runtime visibility
Section titled “Runtime visibility”Use the Actions tabs to inspect and troubleshoot the runners:
- Overview: controller status, scale set count, maximum runners, observed pods, cache status, and a workflow snippet.
- Scale Sets: configured
runs-onlabels, scale windows, pod counts, CPU and memory usage, node pool placement, mode, and namespace. Select a scale set to open its page. - Runners: live runner pod status and runtime details.
- Cache: the in-cluster Actions cache settings, statistics, and stored entries.
- Logs: controller or runner pod logs with target, pod, container, tail, and follow controls.
Scale set pages
Section titled “Scale set pages”Every scale set has its own page with five tabs.
Overview
Section titled “Overview”The Overview tab shows the runs-on label with a copy button, ready pods, CPU
and memory usage, runner group, node pool, container mode, namespace, runner
image, resource requests and limits, work storage, build cache state, chart
version, and release status. A failed apply or a failing Helm install job shows
its error at the top of the page. Both raise a notification, as does a scale
set whose controller add-on has been uninstalled.
Below the facts you get the runner pods with per-pod logs, a workflow snippet for this label, and a Runners on GitHub link that opens the runner settings of the repository, organization, or enterprise the scale set is registered with.
Metrics
Section titled “Metrics”The Metrics tab needs the VictoriaMetrics app on the cluster. Pick a range from 5 minutes to 7 days.
- Pod resources: CPU, memory, and runner pod count over the range.
- Jobs: running and queued jobs, busy, idle, and desired runners, completed and failed jobs per interval, and the median queue and execution time.
- Jobs by repository, workflow, or job: completed runs, failed runs with the failure rate, median and 95th percentile duration, total execution time, and the median queue time from assignment to a runner picking the job up. Rows are sorted by total execution time.
Job metrics appear once jobs complete inside the selected range. A field shows a dash when its query could not be answered, with the reason listed under the charts.
Events
Section titled “Events”The Events tab lists Kubernetes events from the runner namespace and from the controller namespace, where the scale set listener runs. Use Warnings only to filter out normal scheduling and pull events.
The Logs tab streams logs from the runner pods of this scale set and from its listener pod, with pod, container, tail, and follow controls. The listener is where registration problems show up: a rejected token, a wrong GitHub URL, or a runner group the scale set cannot join.
Settings
Section titled “Settings”The Settings tab holds the same form as the create dialog, plus the Persistent BuildKit settings. Save applies the change to the cluster; changes are accepted once any running operation on the scale set finishes. Delete scale set removes the runners and their registration on GitHub after you type the confirmation phrase.
Security notes
Section titled “Security notes”GitHub workflows can execute arbitrary commands from the repositories allowed to use a runner scale set. For production clusters:
- Scope the GitHub integration to only the repositories that need private runners.
- Avoid running untrusted pull request workflows on privileged Docker-in-Docker runners.
- Prefer dedicated node pools for high-trust or resource-heavy CI workloads.
- Keep runner namespaces separate from application namespaces when possible.