Self-Hosted GitHub Action Runner on Kubernetes
I recently set up a self-hosted GitHub Action Runner on Kubernetes using the Action Runner Controller, aiming for more control over my CI/CD pipeline. This involved configuring Kubernetes with DNS, ingress, and microk8s, and securing my private Docker registry with TLS and a custom Certificate Authority.
Create GitHub App and Secrets#
On your repository, go to Developer settings and create and install a GitHub App. You will obtain the necessary details for creating a Kubernetes secret:
kubectl create secret generic controller-manager -n actions
--from-literal=github_app_id=YOUR_GITHUB_APP_ID
--from-literal=github_app_installation_id=YOUR_INSTALLATION_ID
--from-literal=github_app_private_key=YOUR_PRIVATE_KEY
Helm Chart Values#
Below is an example of the values you might use for the Helm chart to deploy the Action Runner Controller:
githubWebhookServer:
enabled: true
replicaCount: 1
secret:
enabled: true
create: true
name: "github-webhook-server"
github_webhook_secret_token: "GITHUB_WEBHOOK_TOKEN"
ingress:
enabled: true
ingressClassName: ""
annotations:
kubernetes.io/ingress.class: traefik-ingress-class
kubernetes.io/tls-acme: "true"
hosts:
- host: github-runner.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: github-runner-cert
hosts:
- github-runner.yourdomain.com
When setting up your GitHub Action Runner on Kubernetes, focus on two crucial steps:
- Update the ingress section in your YAML with your actual domain name, ensuring GitHub can reach your webhook server.
- Use
tls-acme: "true"
to integrate cert-manager.
GitHub Webhook#
Set the Payload URL in your repository’s webhook settings to github-runner.yourdomain.com
, which should point to your Kubernetes-hosted GitHub Action Runner’s address. The webhook settings are found under the repository’s “Settings” tab, under “Webhooks”.
Image and Cert-Manager Configuration#
image:
repository: "summerwind/actions-runner-controller"
actionsRunnerRepositoryAndTag: "summerwind/actions-runner:latest"
dindSidecarRepositoryAndTag: "docker:dind"
pullPolicy: IfNotPresent
certManagerEnabled: true
- The
certManagerEnabled: true
parameter activates Cert-Manager within the Kubernetes cluster, which automates the issuance and renewal of TLS certificates for secure communications. - The
image
section outlines the Docker images used by the self-hosted GitHub Actions runner, including the controller, runner, and Docker-in-Docker sidecar images.
Install Helm Chart#
Add and update the Helm repository:
helm repo add actions-runner-controller https://actions-runner-controller.github.io/actions-runner-controller
helm repo update
Fetch the chart and prepare your values file:
helm fetch actions-runner-controller/actions-runner-controller --untar --untardir ./mychart
cp ./mychart/actions-runner-controller/values.yaml ./custom-values.yaml
Modify custom-values.yaml
as needed, then install:
helm install actions-runner-controller actions-runner-controller/actions-runner-controller -f custom-values.yaml
Create Runner Deployment#
If you use a private repository with SSL, you need to import your SSL certificate into a Kubernetes secret:
kubectl create secret generic ca-cert --from-file=ca.crt -n actions
Example RunnerDeployment manifest:
apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
annotations:
karpenter.sh/do-not-evict: "true"
name: self-hosted-runner-deployment
namespace: actions
spec:
template:
spec:
repository: githubuser/repository
labels:
- self-hosted-linux
resources:
requests:
cpu: 1500m
memory: 2000Mi
volumes:
- name: certs
secret:
secretName: ca-cert
items:
- key: ca.crt
path: ca.crt
dockerVolumeMounts:
- mountPath: /etc/docker/certs.d/yourprivaterepo.intranet
name: certs
readOnly: true
Apply the deployment:
kubectl apply -f runnerdeployment.yml
Scaling Deployments#
You can use a HorizontalRunnerAutoscaler to automatically scale your runners:
apiVersion: actions.summerwind.dev/v1alpha1
kind: HorizontalRunnerAutoscaler
metadata:
name: self-hosted-runner-deployment-autoscaler
namespace: actions
spec:
maxReplicas: 30
minReplicas: 0
scaleTargetRef:
kind: RunnerDeployment
name: self-hosted-runner-deployment
scaleUpTriggers:
- duration: 30m
githubEvent:
workflowJob: {}
This configuration dynamically adjusts the number of self-hosted GitHub Actions runners between 0 and 30, scaling up in response to workflow job events.
Testing with GitHub Runners#
After installation, when you run a CI/CD pipeline, you should see your GitHub runners online and available to execute jobs.