Martin Koníček
Blog
Self Hosted GitHub Action Runner on Kubernetes
Introduction
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 repository click on Developer settings and create and install an app. You should get all details below for creating a 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
githubWebhookServer:
enabled: true
replicaCount: 1
secret:
enabled: true
create: true
name: "github-webhook-server"
### GitHub Webhook Configuration
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: First, update the ingress section in your YAML with your actual domain name, ensuring GitHub can reach your webhook server. Second, use tls-acme: "true" to integrate cert-manager.
GitHub Webhook
One would input github-runner.yourdomain.com as the Payload URL, corresponding to yours Kubernetes-hosted GitHub Action Runner's address. The webhook settings are found under the repository's "Settings" tab, and choosing "Webhooks" from the sidebar will navigate to this page.
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, to manage and execute CI/CD jobs.
Install Helm Chart
helm repo add actions-runner-controller https://actions-runner-controller.github.io/actions-runner-controller
helm repo update
This will add a helm repo
helm fetch actions-runner-controller/actions-runner-controller --untar --untardir ./mychart
cp ./mychart/actions-runner-controller/values.yaml ./custom-values.yaml
Now you will get helm chart values and you can modify it with values above
helm install actions-runner-controller actions-runner-controller/actions-runner-controller -f custom-values.yaml
Create runner deployment
kubectl create secret generic ca-cert --from-file=ca.crt -n actions
If you use private repository with SSL (I use ingress for SSL) you need to import SSL certificate into secret above.
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
Create a file runnerdeployment.yml above with modifying yourprivaterepo.intranet and apply it.
kubectl apply -f runnerdeployment.yml
Scaling deployments
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 YAML configuration defines a HorizontalRunnerAutoscaler in Kubernetes, which dynamically adjusts the number of self-hosted GitHub Actions runners between 0 and 30. It scales up in response to workflow job events.
Testing with GitHub runners
After installing you should see when run CI/CD pipeline GitHub runners Online.