Skip to content
SYS.DOCS // DOCS

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.

  • 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).
  1. Open a cluster and go to Actions.
  2. Select Install controller.
  3. Choose the GitHub integration this cluster should use to register private runners.
  4. 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.

  1. Open Cluster > Actions > Scale Sets.
  2. Select Add scale set.
  3. Set Name / runs-on label. This is the default label you use in GitHub workflow jobs.
  4. Optionally add extra runner labels, such as linux, gpu, or private-network.
  5. Select a GitHub repository, or choose Custom GitHub URL for an organization or repository URL.
  6. Set Min runners and Max runners.
  7. Choose a runner namespace. The default is ci.
  8. Choose the container mode, resources, and placement options.
  9. In Docker-in-Docker mode, optionally turn on Persistent BuildKit under Advanced to keep Docker image layers between jobs. See Persistent BuildKit.
  10. 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.

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 test

If 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 test

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 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.

  • 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/nodepool selector.
  • 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.

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-on labels, 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.

Every scale set has its own page with five tabs.

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.

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.

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.

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.

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.