How to install GitHub Actions Runner Controller on Kubernetes with MicroK8s
In this article we will go over how to install GitHub Actions Runner Controller (ARC) on Kubernetes. For the purpose of this article we will use MicroK8s ↗ which is a lightweight Kubernetes distribution that is easy to install and manage. If you have a standard Kubernetes cluster, you can use it instead and simply remove the microk8s
prefix from the commands.
The variant that we will install is the version ~officially maintained by GitHub, which uses Runner Scale Sets (gha-runner-scale-set-controller
) provided by the GitHub Actions service instead of relying on webhooks emitted by the GitHub API. The advantage of this version is that you do not need to expose any public service to the internet.
This article assumes that you have created a brand new server somewhere, with Ubuntu 24.04 and at least 8GB of RAM. Hetzner Cloud servers are perfect for that.
Install MicroK8s and enable helm
Log into your server, switch to the root
user, and run the following commands:
Log out (exit
) and log back in for the changes to take effect, and run the following command to verify that MicroK8s is running:
You should see something like:
Inspect the nodes in your cluster:
You should see something like:
Enable helm
so that you can deploy the Charts for ARC:
Install the runner controller
You should see something like:
At this point, the runner controller is installed and running in your cluster in the arc-systems
namespace.
Create the arc-runners
namespace
This namespace will host the runners that will be created by the runner scale sets:
Now, before you can create the runner scale sets, you need to create a private GitHub App that will be used to authenticate API calls with GitHub.
Create private GitHub App and register it with ARC
To create a private GitHub App for your ARC deployment, go to your organization settings and click on:
Fill in the form as follows:
Once created:
- Take a note of the App ID.
- Generate a Private Key.
- Click on the “Install App” link in the sidebar, select your organization, and choose the repositories it has access to.
Finally, take a note of the Installation ID in the browser URL. URL format is:
At this point, set the following environment variables on your server:
ORGANIZATION_NAME
: The name of your organization (e.g.runs-on-demo
).APP_ID
: The App ID you got from the GitHub App you created.INSTALLATION_ID
: The Installation ID you got after installing the GitHub App in your organization.PRIVATE_KEY_PATH
: Path to the private key file on your server (upload it first if needed).
You can now create a secret with the private key and application details in your Kubernetes cluster:
Once this secret is created, you can proceed to create the runner scale sets that will be used to run your workflows.
Create one (or multiple) runner scale set(s)
A runner scale set is managed by a single controller, and is used to launch runners of a specific configuration (image, privileges, etc) whenever a new job requests it.
Note that the name you will give to that runner scale set (RUNNER_SCALE_SET_LABEL
in the following commands) will be the label that you must use in your runs-on:
definition in workflow files. Only a single label can be used.
At this point, set the following environment variables on your server:
ORGANIZATION_NAME
: The name of your organization (e.g.runs-on-demo
).RUNNER_SCALE_SET_LABEL
: The label of the runner scale set you want to create (e.g.arc-custom-runners-type1
).
Then create the runner scale set:
You should see something like:
You can verify your Kubernetes resources with the following command:
Which should return something like:
You can now go to your organization settings, click on “Actions” -> “Runners”, and see your new runner scale set coming online.
At this point, you have now two pods running in the arc-systems
namespace, one for the main ARC controller, and one for your runner scale set, which listens for new jobs and launches runners when needed:
Which should return something like:
You can add another runner scale set by simply running the same command with a different label, for example:
You now have 3 pods running in the arc-systems
namespace:
Verify that the installation is working by launching a job
It’s finally time to try to launch a job to see if everything works.
Create a new workflow YAML file in your repository, for example:
Push the file to your repository. You should see your workflow being executed by one of your runners, which will start in the arc-runners
namespace:
Which should return something like:
After a little while, the runner should be up and the job completed:
Removing a runner scale set
If at any point you want to remove a runner scale set, you can do so with the following command:
This will then remove the runner scale set from the GitHub UI as well. Note that it will not work if you have already removed the main controller (from the arc-systems
namespace), so make sure to remove runner scale sets first if you want to uninstall ARC..
Considerations
ARC is quite easy to setup, but there are a few things you should be aware of:
- everything runs in a Docker container, in an image with a very limited set of software installed. You will need to largely adjust your workflows, and create and maintain your own Docker images if you need more software installed.
- a lot of third-party actions will not work.
- it is sometimes hard to comprehend the logs emitted by the controller and the runners, and you don’t get any metrics emitted.
- you must have a kubernetes cluster running, irrespective of whether you have actual jobs running.
- for each variation of runner configuration, you need to create a new runner scale set.
Conclusion
ARC can be a great choice if you are already comfortable with Kubernetes. If you are looking for something as scalable but much easier to install and manage (and with no dangling resources), you can have a look at RunsOn, which provides 1-1 compatible images, real virtual machines, metrics, static IPs, SSH access, custom images, and more.