3 Min. Lesezeit
Selbst gehostete GitHub-Runner in Kubernetes
Die von GitHub gehosteten Runner sind bequem, aber sie werden pro Minute abgerechnet, erreichen nichts in deinem Netzwerk und starten jedes Mal auf einer leeren Maschine. Wenn du schon einen Kubernetes-Cluster betreibst, kannst du die Jobs dort laufen lassen. Actions Runner Controller (ARC) startet für jeden Job einen frischen Runner-Pod und entfernt ihn danach wieder.
Diese Notiz verwendet das aktuelle Setup, das GitHub selbst pflegt: die Charts gha-runner-scale-set. Ältere Anleitungen nutzen den Community-Controller summerwind mit RunnerDeployment-Ressourcen. Misch die beiden nicht.
Was du brauchst
- Einen Kubernetes-Cluster und Zugriff darauf mit
kubectl. Ein Cluster auf Bare Metal funktioniert gut. - Helm 3.
- Owner-Rechte in der GitHub-Organisation, die die Runner bekommen soll.
1. Eine GitHub App erstellen
ARC braucht Zugangsdaten, um Runner zu registrieren. Eine GitHub App ist besser als ein Personal Access Token: Sie hängt an keiner Person, und ihre Berechtigungen sind eng.
In den Einstellungen der Organisation unter Developer settings → GitHub Apps → New GitHub App:
- Gib ihr einen Namen und eine beliebige Homepage-URL. Schalte den Webhook aus.
- Setz unter Organization permissions den Punkt Self-hosted runners auf Read and write.
- Erstelle die App und erzeuge dann einen Private Key. Eine
.pem-Datei wird heruntergeladen. - Installier die App in deiner Organisation.
Notier dir drei Werte:
- die App ID auf der Einstellungsseite der App,
- die Installation ID, die Zahl am Ende der URL, wenn du die installierte App in den GitHub Apps-Einstellungen der Organisation öffnest,
- den Pfad zur Datei mit dem Private Key.
Die Schlüsseldatei gehört in kein Repository.
2. Den Controller installieren
Der Controller bekommt einen eigenen Namespace:
helm install arc \
--namespace arc-systems \
--create-namespace \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller
Ohne --version installiert Helm das neueste Chart. Fixier eine Version, sobald es läuft, damit ein Upgrade dann passiert, wenn du es entscheidest.
3. Die Zugangsdaten der App ablegen
Die Runner bekommen einen zweiten Namespace. Das Secret muss im selben Namespace liegen wie das Runner Scale Set:
kubectl create namespace arc-runners
kubectl create secret generic arc-github-app \
--namespace arc-runners \
--from-literal=github_app_id=<APP_ID> \
--from-literal=github_app_installation_id=<INSTALLATION_ID> \
--from-file=github_app_private_key=<PFAD_ZUM_PRIVATE_KEY.pem>
Die Schlüsselnamen (github_app_id, github_app_installation_id, github_app_private_key) sind fest. ARC sucht genau nach diesen.
4. Ein Runner Scale Set installieren
Ein Runner Scale Set ist ein Pool von Runnern für eine Organisation. Sein Installationsname wird zum Label, das du in Workflows verwendest:
helm install arc-runner-set \
--namespace arc-runners \
--set githubConfigUrl="https://github.com/<ORGANISATION>" \
--set githubConfigSecret=arc-github-app \
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
5. Prüfen, ob es läuft
helm list -A
kubectl get pods -n arc-systems
Der Controller und ein Listener-Pod sollten Running sein. Das Scale Set erscheint ausserdem in den Einstellungen der Organisation unter Actions → Runners.
Runner-Pods gibt es noch keine. Sie starten, wenn ein Job ankommt.
6. In einem Workflow verwenden
Setz runs-on auf den Installationsnamen:
name: Runner test
on:
workflow_dispatch:
jobs:
hello:
runs-on: arc-runner-set
steps:
- run: echo "Running on $(hostname)"
Starte den Workflow im Tab Actions und beobachte die Pods:
kubectl get pods -n arc-runners -w
Ein Runner-Pod erscheint, führt den Job aus und verschwindet wieder.
Gut zu wissen
- Jeder Job bekommt einen frischen Pod. Zwischen den Jobs bleibt nichts erhalten. Das ist gut für die Sicherheit und schlecht für Caches. Nutze
actions/cacheoder einen Registry-Cache für Build-Layer. - Das Standard-Runner-Image hat keinen Docker-Daemon. Jobs, die Images bauen, brauchen beim Scale Set
containerModeaufdind(Docker in Docker) oderkubernetes. Lies dievalues.yamldes Charts, bevor du wählst. - Selbst gehostete Runner und öffentliche Repositories passen nicht zusammen. Ein Pull Request aus einem Fork könnte Code auf deinem Cluster ausführen. Nutze sie nur für private Repositories.