Mit dem offiziellen Helm-Chart gitlab/gitlab-runner installierst du einen GitLab Runner in einem eigenen Namespace deines Kubernetes-Clusters. Das Token des Runners liegt dabei in einem Kubernetes-Secret, und jeder CI-Job startet als eigener Pod. Am Ende hast du einen Projekt-Runner mit eng gefassten Rechten und eine erste Pipeline, deren Job im Cluster lief.
Die Anleitung nutzt Chart 0.93.0 mit GitLab Runner 19.4.0 (Stand 1. Oktober 2026). Der Ablauf gilt laut GitLab-Dokumentation für jeden Kubernetes-Cluster, zum Beispiel für einen Managed Kubernetes Cluster von centron. Statt auf geteilten Runnern laufen deine Jobs dann auf Nodes, die du selbst dimensionierst. Dieser Beitrag ist der erste Teil einer geplanten Serie zu CI/CD auf Kubernetes. Wie du in der Pipeline Container-Images baust, ist Thema eines der folgenden Teile.
Was ist ein GitLab Runner mit Kubernetes-Executor?
Ein GitLab Runner mit Kubernetes-Executor ist ein Dienst im Cluster, der bei GitLab nach neuen CI-Jobs fragt und für jeden Job über die Kubernetes-API einen eigenen Pod startet, der nach dem Job wieder entfernt wird.
Das Helm-Chart installiert dazu ein Deployment mit einem Manager-Pod. Dieser Pod holt Jobs aktiv bei der GitLab-API ab. GitLab muss den Cluster also nicht erreichen können, umgekehrt braucht der Cluster aber ausgehenden Zugriff auf deine GitLab-Instanz. Für jeden Job legt der Manager-Pod über die Kubernetes-API einen Job-Pod an. Darin laufen mindestens zwei Container:
| Container | Aufgabe |
|---|---|
build |
führt das script deines Jobs im angegebenen Image aus |
helper |
klont das Repository, stellt Cache und Artefakte bereit und lädt Artefakte nach dem Job zu GitLab hoch |
| Service-Container | nur wenn der Job oder die Runner-Konfiguration services definiert, etwa eine Datenbank für Tests |
graph LR R["Runner-Manager-Pod im Namespace ci-runner"] -->|"fragt Jobs ab (ausgehend)"| G["GitLab-Instanz"] R -->|"legt Job-Pod an"| K["Kubernetes-API"] K --> J["Job-Pod mit den Containern build und helper"] J -->|"Job-Log und Artefakte"| G
Voraussetzungen
- Kubernetes-Cluster mit Version 1.33.1 oder 1.32.4. Das sind laut centron-Docs die Versionen, die du beim centron Managed Kubernetes aktuell wählen kannst, 1.33.1 ist die empfohlene (abgerufen am 1. Oktober 2026). Maßgeblich ist laut centron die Auswahl im Erstellungsdialog.
- kubectl mit höchstens einer Minor-Version Abstand zum Cluster, bei einem 1.33-Cluster also 1.32 bis 1.34. kubectl muss mit dem Cluster verbunden sein. Bei centron lädst du die kubeconfig in der Cluster-Ansicht über „Download Config File“ herunter, setzt die Dateirechte mit
chmod 600und verweist mitexport KUBECONFIG=...darauf. Die Schritte stehen unter Mit dem Cluster verbinden. Wenn kubectl noch fehlt, hilft das Tutorial kubectl installieren und Kubernetes-Cluster verwalten. - Helm 3. Die GitLab-Dokumentation für Runner 19.4.0 beschreibt die Befehle für Helm 3. Helm 3 bekommt laut Helm-Projekt nur noch bis 10. Februar 2027 Sicherheitsupdates, aktuelle Hauptversion ist Helm 4.
- GitLab 19.4 (Self-Managed) oder gitlab.com, und ein Projekt, in dem du die Rolle Maintainer hast. gitlab.com wird laufend aktualisiert, dort empfiehlt GitLab die jeweils neueste Runner-Version. Die Version
major.minordes Runners sollte laut GitLab zur Version von GitLab passen. Ältere oder neuere Runner können funktionieren, einzelne Funktionen stehen dann aber unter Umständen nicht oder nicht korrekt zur Verfügung. Läuft deine Instanz mit einer anderen Version, wählst du im Abschnitt zur Installation eine passende Chart-Version. - Ausgehender HTTPS-Zugriff vom Cluster auf deine GitLab-Instanz und auf die Registries der verwendeten Images. Das Runner-Image kommt laut
values.yamldes Charts vonregistry.gitlab.com, das Job-Imagealpine:3.24von Docker Hub. Der Tag3.24zeigt auf Alpine 3.24.2 (Docker Hub, Stand 18. September 2026).
Zur Abgrenzung beim centron Managed Kubernetes: Laut centron-Docs betreibt centron Control Plane, Cluster-Netzwerk und Cluster Autoscaler. Namespaces, RBAC-Regeln, Secrets und selbst installierte Software wie den GitLab Runner verantwortest du selbst.
Passende Infrastruktur bei centron
Vom Container zum Cluster: Managed Kubernetes von centron mit Control Plane und Traffic inklusive. Managed Kubernetes ansehen →
Projekt-Runner in GitLab anlegen
Den Runner legst du zuerst in GitLab an, denn erst dabei entsteht das Runner-Authentifizierungstoken, mit dem sich der Runner im Cluster später bei GitLab anmeldet.
- Öffne dein Projekt in GitLab und wähle in der linken Seitenleiste Settings > CI/CD.
- Klappe den Abschnitt Runners auf und wähle Create project runner.
- Wähle als Betriebssystem Linux.
- Trage im Feld Tags den Tag
kubernetesein. Lass Run untagged ausgeschaltet. Dann übernimmt der Runner nur Jobs, die diesen Tag ausdrücklich anfordern. - Optional: Gib im Feld Runner description eine Beschreibung ein, zum Beispiel
k8s-ci-runner. - Wähle Create runner.
GitLab zeigt dir danach das Runner-Authentifizierungstoken. Es beginnt mit glrt-. Kopiere es sofort, denn GitLab zeigt es nur kurz an. Die weiteren Installationshinweise auf der Seite brauchst du nicht, denn die Registrierung übernimmt später das Helm-Chart.
Tags, „Run untagged“, die Sperre für andere Projekte („locked“), geschützte Branches („protected“) und das maximale Job-Timeout stellst du ab jetzt nur noch in GitLab ein. Mit einem Authentifizierungstoken wirken diese Werte in der values.yaml laut GitLab-Dokumentation nicht. Setzt du sie trotzdem, verwirft das Startskript von Chart 0.93.0 Tags, „Run untagged“, locked und protected stillschweigend. Ein gesetztes runners.maximumTimeout lässt die Registrierung dagegen mit der Meldung Runner configuration ... is reserved abbrechen.
Zwei Varianten zur Einordnung: Soll der Runner allen Projekten einer Gruppe zur Verfügung stehen, legst du einen Gruppen-Runner unter Build > Runners > Create group runner an. Dafür brauchst du die Rolle Owner in der Gruppe, der restliche Ablauf bleibt gleich. Der ältere Weg über ein Registrierungstoken gilt laut GitLab als Legacy und wird nicht empfohlen. Seit GitLab 17.0 können Administratoren und Gruppen-Owner ihn abschalten.
Namespace und Token-Secret anlegen
Für den Runner legst du einen eigenen Namespace an und speicherst das Token dort in einem Kubernetes-Secret, statt es im Klartext in die values.yaml zu schreiben.
$ kubectl create namespace ci-runner
$ read -rs RUNNER_TOKEN
$ kubectl create secret generic runner-auth \
--namespace ci-runner \
--from-literal=runner-registration-token="" \
--from-literal=runner-token="$RUNNER_TOKEN"
$ unset RUNNER_TOKENWas die Befehle tun:
read -rs RUNNER_TOKENwartet auf deine Eingabe. Füge das Token ein und bestätige mit Enter. Die Eingabe erscheint nicht auf dem Bildschirm, und weil das Token nicht im Befehl selbst steht, landet es auch nicht in der Shell-Historie.- Das Secret
runner-authbraucht genau zwei Schlüssel. Das Chart liest beide aus dem Secret und übergibtrunner-tokenbeim Start als Token an den Runner.runner-registration-tokenbleibt laut GitLab-Dokumentation aus Kompatibilitätsgründen ein leerer String. Erlaubt dein Werkzeug zur Secret-Verwaltung keinen leeren Wert, darfst du einen beliebigen Text eintragen. Er wird ignoriert, solangerunner-tokengesetzt ist. unset RUNNER_TOKENentfernt das Token wieder aus deiner Shell.
Legst du das Secret stattdessen als YAML-Manifest mit Base64-Werten an, achte darauf, dass am Token kein Zeilenumbruch hängt, also echo -n beim Kodieren. Sonst meldet der Runner den Fehler invalid header field for "Private-Token".
Ein Kubernetes-Secret ist nur Base64-kodiert, nicht verschlüsselt. Wer im Namespace ci-runner Secrets lesen darf, kann das Token auslesen. Deshalb bekommt der Runner einen eigenen Namespace, in dem außer dem Runner und seinen Job-Pods nichts anderes läuft.
Welche Rechte braucht der GitLab Runner im Cluster?
Der GitLab Runner braucht im eigenen Namespace nur Rechte auf Pods, deren Unterressourcen attach, exec und log sowie auf Secrets, Services, Service Accounts und Events, aber keine clusterweiten Rechte.
Am einfachsten wäre es, im Chart nur rbac.create: true zu setzen. Ohne eigene Regeln unter rbac.rules erzeugt das Chart dann aber eine Role mit allen Verben auf allen Ressourcen der Core-API-Gruppe im Namespace. Der Runner dürfte damit zum Beispiel jedes Secret und jede ConfigMap im Namespace lesen und ändern. Die Executor-Dokumentation nennt stattdessen eine Liste der nötigen Rechte. Für diese Anleitung reicht dieser Ausschnitt:
| Ressource | Verben | Wofür |
|---|---|---|
pods |
create, delete, get, list, watch | Job-Pods anlegen und entfernen. list und watch braucht der Informer, mit dem der Runner ab Version 17.9 Änderungen am Job-Pod schneller erkennt |
pods/attach |
create, delete, get, patch | Befehle per attach ausführen. Das ist der Standard, weil das Feature-Flag FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY standardmäßig auf false steht |
pods/exec |
create, delete, get, patch | laut Rechtetabelle ohne Bedingung nötig |
pods/log |
get, list | laut Rechtetabelle bei der attach-Strategie nötig |
secrets |
create, delete, get, update | laut Rechtetabelle ohne Bedingung nötig |
serviceaccounts |
get | laut Rechtetabelle ohne Bedingung nötig |
services |
create, get | laut Rechtetabelle ohne Bedingung nötig |
events |
list | Kubernetes-Warnungen zum Job-Pod ins Job-Log schreiben (print_pod_warning_events, standardmäßig an) |
Fehlen list oder watch auf Pods, schreibt der Runner eine Warnung ins Log und verfolgt den Job-Pod auf dem älteren Weg weiter. watch auf Events brauchst du nur, wenn du das Feature-Flag FF_PRINT_POD_EVENTS einschaltest. Weitere Rechte aus der Tabelle, etwa auf Namespaces, ConfigMaps oder PersistentVolumeClaims, gehören zu optionalen Funktionen wie einem eigenen Namespace je Job und sind hier nicht nötig. Die vollständige Tabelle steht in der Dokumentation zum Kubernetes-Executor für Runner 19.4.0.
Den Schalter rbac.clusterWideAccess lässt du auf dem Standardwert false. Dann legt das Chart eine Role im Namespace an und keine ClusterRole. Der Runner darf Job-Pods damit nur in diesem Namespace anlegen, und genau dorthin schickt sie die Zeile namespace in der Runner-Konfiguration.
Auch mit engen Rechten bleibt eine Angriffsfläche, denn der Runner soll ja Pods mit dem Image starten, das ein Job verlangt. Laut GitLab kann jede Person mit der Rolle Developer im Projekt über eine Pipeline die Umgebung des Runners gefährden, ob absichtlich oder nicht. Gib deshalb nur Personen Schreibzugriff auf die Pipeline, denen du Code im Cluster anvertraust. Forks bekommen Projekt-Runner laut GitLab nicht automatisch. Mit allowed_images in der Runner-Konfiguration kannst du die erlaubten Images zusätzlich einschränken.
values.yaml schreiben
In der Datei runner-values.yaml legst du fest, mit welcher GitLab-Instanz sich der Runner verbindet, welche Rechte er im Namespace bekommt und mit welchen Ressourcen die Job-Pods starten.
gitlabUrl: "<gitlab-url>"
concurrent: 4
rbac:
create: true
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "delete", "get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/attach", "pods/exec"]
verbs: ["create", "delete", "get", "patch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "delete", "get", "update"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get"]
- apiGroups: [""]
resources: ["services"]
verbs: ["create", "get"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list"]
serviceAccount:
create: true
runners:
secret: runner-auth
config: |
[[runners]]
[runners.kubernetes]
namespace = "{{ default .Release.Namespace .Values.runners.jobNamespace }}"
image = "alpine:3.24"
cpu_request = "500m"
memory_request = "512Mi"
cpu_limit = "1"
memory_limit = "1Gi"
helper_cpu_request = "100m"
helper_memory_request = "128Mi"Die Schlüssel im Einzelnen:
gitlabUrl: Ersetze<gitlab-url>durch die vollständige URL deiner GitLab-Instanz mit Protokoll, alsohttps://gitlab.comoder zum Beispielhttps://gitlab.example.combei Self-Managed.concurrent: Wie viele Jobs der Runner höchstens gleichzeitig ausführt. Der Standardwert des Charts ist 10. Mehr dazu im Abschnitt zu gleichzeitigen Jobs.rbac.createundrbac.rules: Das Chart legt eine Role mit genau diesen Regeln und ein RoleBinding an. Die Regeln entsprechen der Tabelle im vorigen Abschnitt.serviceAccount.create: Das Chart legt einen eigenen ServiceAccount an, an den die Role gebunden wird. Setzt durbac.createohne diesen Schlüssel, warnt das Chart bei der Installation.runners.secret: Name des Secrets mit dem Token. Das Token steht damit nicht in dervalues.yaml. Den SchlüsselrunnerTokenlässt du deshalb weg, undrunnerRegistrationTokengehört zum Legacy-Weg.runners.config: Die eigentliche Runner-Konfiguration im TOML-Format. Das Chart wertet den Text als Helm-Template aus. Die Zeilenamespaceübernimmt den Release-Namespace, die Job-Pods laufen also inci-runner.image: Standard-Image für Jobs, die selbst keinimageangeben. Ein fester Tag stattalpineohne Tag hält nachvollziehbar, womit ein Job lief.cpu_request,memory_request,cpu_limit,memory_limit: Requests und Limits für den Containerbuild.helper_cpu_requestundhelper_memory_requestgelten für den Containerhelper. Die Werte sind Beispiele, passe sie an deine Jobs an.
Den Schalter privileged setzt du nicht. Privilegierte Container braucht man zum Beispiel für Image-Builds mit Docker-in-Docker. Laut GitLab kann ein Job damit vollen Root-Zugriff auf den Host erlangen. Image-Builds sind deshalb Thema eines folgenden Teils dieser Serie.
GitLab Runner mit Helm installieren
Mit Helm fügst du das Chart-Repository von GitLab hinzu, prüfst die verfügbaren Chart-Versionen und installierst den Runner mit fest angegebener Version in den Namespace ci-runner.
$ helm repo add gitlab https://charts.gitlab.io
$ helm repo update gitlab
$ helm search repo -l gitlab/gitlab-runnerChart und Runner haben getrennte Versionsnummern. Die Liste zeigt deshalb zwei Spalten: CHART VERSION ist die Version des Helm-Charts, APP VERSION die Version des Runners. Für diese Anleitung suchst du die Zeile mit Chart 0.93.0 und App-Version 19.4.0. Läuft deine GitLab-Instanz mit einer anderen Version, wählst du die Chart-Version, deren App-Version zu major.minor deiner GitLab-Version passt.
Wenn du vorher sehen willst, welche Manifeste Helm erzeugt, hängst du an den folgenden Befehl --dry-run --debug an. Dann ändert Helm nichts im Cluster. Installiert wird so:
$ helm install --namespace ci-runner gitlab-runner \
-f runner-values.yaml \
gitlab/gitlab-runner \
--version 0.93.0gitlab-runner ist der Name des Releases. Unter diesem Namen aktualisierst und entfernst du die Installation später. Weil der Release-Name mit dem Chart-Namen beginnt, heißt auch das Deployment gitlab-runner. Nach der Installation gibt Helm die Hinweise des Charts aus. Darin steht die GitLab-URL, gegen die sich der Runner registriert. Fehlt gitlabUrl, warnt das Chart an dieser Stelle.
Prüfen, ob der Runner online ist
Ob die Installation geklappt hat, erkennst du an drei Stellen, nämlich am Pod-Status im Cluster, am Log des Runners und am Status des Runners in GitLab.
$ kubectl get pods --namespace ci-runner
$ kubectl logs deployment/gitlab-runner --namespace ci-runnerWoran du den Erfolg erkennst:
- Pod: Im Namespace läuft ein Pod des Deployments
gitlab-runnermit StatusRunning. Bis er als bereit gilt, kann gut eine Minute vergehen, weil die Readiness-Probe des Charts standardmäßig erst nach 60 Sekunden startet. - Log: Das Startskript des Charts registriert den Runner mit dem Token und schreibt dabei Zeilen wie
Registration attempt 1 of 30. Es versucht es bis zu 30-mal im Abstand von 5 Sekunden. Danach startet der Runner und fragt GitLab nach Jobs. Meldungen mitforbiddenoderreservedführen dich zur Fehlerbehebung weiter unten. - GitLab: Unter Settings > CI/CD > Runners steht dein Runner unter den zugewiesenen Projekt-Runnern. Der Status
onlinebedeutet, dass der Runner in den letzten zwei Stunden Kontakt zu GitLab hatte.never_contactedheißt, dass er sich noch nie gemeldet hat.
Den Namen des Pods zeigt GitLab in der Detailansicht des Runners nicht an. Das ist laut GitLab ein bekanntes Problem des neuen Registrierungswegs mit dem Helm-Chart (Issue 423523).
Erste Pipeline auf dem Cluster ausführen
Eine minimale .gitlab-ci.yml mit einem einzigen Job reicht, um zu prüfen, ob GitLab den Job an deinen Runner gibt und der Runner dafür einen Pod im Cluster startet.
Lege im Wurzelverzeichnis deines Repositorys die Datei .gitlab-ci.yml mit diesem Inhalt an:
cluster-check:
tags:
- kubernetes
image: alpine:3.24
script:
- cat /etc/os-release
- uname -atags wählt den Runner aus. Ein Runner übernimmt einen Job nur, wenn er jeden Tag hat, den der Job verlangt. Tags unterscheiden Groß- und Kleinschreibung. image legt das Image für den Container build fest, script die Befehle. Weil keine stage angegeben ist, läuft der Job in der Standard-Stage test.
Öffne vor dem Commit ein zweites Terminal und beobachte den Namespace:
$ kubectl get pods --namespace ci-runner --watchCommitte und pushe die Datei. GitLab startet die Pipeline, du findest sie unter Build > Pipelines. Im Terminal erscheint neben dem Runner-Pod ein neuer Pod für den Job. Er läuft, solange der Job läuft, und verschwindet danach wieder. Im Job-Log in GitLab siehst du die Ausgabe der beiden Befehle, darunter die Alpine-Version aus /etc/os-release. Mit Strg+C beendest du --watch.
Wie viele Jobs laufen gleichzeitig?
Wie viele Jobs gleichzeitig laufen, begrenzt der Wert concurrent in der values.yaml, und ob die Job-Pods dafür Platz finden, entscheiden ihre Ressourcen-Requests und die freie Kapazität der Nodes.
concurrent ist eine Obergrenze für alle Jobs dieses Runners zusammen. Der Chart-Standard ist 10, in dieser Anleitung steht der Wert auf 4. Wie oft der Runner GitLab nach neuen Jobs fragt, regelt checkInterval, der Standard sind 3 Sekunden.
Jeder Job-Pod fordert die Requests von build und helper zusammen an. Mit den Beispielwerten sind das 600m CPU und 640Mi Arbeitsspeicher je Job. Bei 4 gleichzeitigen Jobs reserviert der Runner also bis zu 2,4 CPU und 2560Mi (2,5 GiB) Arbeitsspeicher. Findet ein Job-Pod keinen Node mit genug freier Kapazität, bleibt er im Status Pending.
Beim centron Managed Kubernetes kannst du dafür den Cluster Autoscaler je Node Pool einschalten. Können Pods mangels Kapazität nicht platziert werden, stellt er laut centron-Docs zusätzliche Nodes bereit. Dauerhaft wenig ausgelastete Nodes entfernt er wieder. Er entscheidet anhand der Requests und nicht anhand der tatsächlichen Auslastung. Ohne Requests in der Runner-Konfiguration kann er den Bedarf deiner Jobs deshalb nicht richtig einschätzen. Das Maximum des Node Pools begrenzt die Kosten nach oben. Wie du Minimum und Maximum festlegst, steht unter Autoscaling aktivieren.
Ein neuer Node braucht laut centron-Docs einige Minuten. Der Runner wartet standardmäßig 180 Sekunden darauf, dass er den Job-Pod erreicht (poll_timeout). Rechnest du damit, dass Jobs öfter auf neue Nodes warten, erhöhst du den Wert unter [runners.kubernetes], zum Beispiel auf poll_timeout = 600.
Fehlerbehebung
Runner bleibt bei never_contacted
Lies zuerst das Log mit kubectl logs deployment/gitlab-runner --namespace ci-runner. Typische Ursachen:
- Token falsch oder nicht vollständig kopiert. Das Token muss mit
glrt-beginnen. Lösche das Secret mitkubectl delete secret runner-auth --namespace ci-runner, lege es wie oben mit dem richtigen Token neu an und starte den Runner danach neu, zum Beispiel mitkubectl rollout restart deployment/gitlab-runner --namespace ci-runner. - Schlüssel im Secret fehlen. Fehlt
runner-tokenoderrunner-registration-token, kann Kubernetes das Secret nicht einbinden. Der Pod bleibt dann inContainerCreating, undkubectl describe podzeigt unterEventseine MeldungFailedMountmit dem Hinweisreferences non-existent secret key. Prüfe die Schlüsselnamen im Secretrunner-auth. - Zeilenumbruch am Token. Die Meldung
invalid header field for "Private-Token"deutet auf ein Token mit angehängtem\nhin. - Reservierte Werte in der values.yaml.
Runner configuration ... is reservedheißt, dass die Registrierung Einstellungen mitschickt, die bei einem Authentifizierungstoken nur GitLab festlegen darf. Bei Chart 0.93.0 ist das typischerweiserunners.maximumTimeoutin dervalues.yaml. Entferne den Wert und setze das Timeout in GitLab. - Falsche gitlabUrl oder kein Netzweg. Prüfe die URL mit Protokoll und ob der Cluster die GitLab-Instanz per HTTPS erreicht. Nutzt deine Self-Managed-Instanz ein selbst signiertes Zertifikat, übergibst du es dem Chart als Secret über
certsSecretName.
Job startet nicht und wartet auf einen Runner
- Der Job verlangt einen Tag, den der Runner nicht hat, oder er hat gar keine
tagsund „Run untagged“ ist aus. Gleiche die Tags in der.gitlab-ci.ymlund in den Runner-Einstellungen ab. - Der Runner ist pausiert. Setze ihn unter Settings > CI/CD > Runners mit Resume fort.
- Die Pipeline läuft in einem Fork. Projekt-Runner sind dort nicht automatisch aktiviert.
forbidden im Job-Log oder Runner-Log
Eine Meldung wie secrets is forbidden: User "system:serviceaccount:..." cannot create resource "secrets" zeigt eine fehlende Regel in der Role. Vergleiche rbac.rules mit der Tabelle oben, korrigiere die values.yaml und spiele sie mit helm upgrade ein (siehe unten). Schaltest du Feature-Flags oder optionale Funktionen ein, prüfe in der Rechtetabelle der Executor-Dokumentation, welche Rechte dafür dazukommen.
Job-Pod bleibt im Status Pending
$ kubectl get pods --namespace ci-runner --field-selector status.phase=Pending
$ kubectl describe pod "<pod-name>" --namespace ci-runnerErsetze <pod-name> durch den Namen aus der ersten Ausgabe. Im Abschnitt Events steht der Grund. Eine Meldung wie Insufficient cpu bedeutet, dass kein Node genug freie Kapazität hat. Mit aktivem Autoscaler sollte dann ein Node dazukommen. Bleibt das aus, ist laut centron-Docs das Maximum des Node Pools erreicht. Prüfe außerdem, ob ein einzelner Job-Pod mehr anfordert, als ein Node überhaupt hat. Dann hilft nur, die Requests zu senken oder größere Nodes zu wählen.
Runner aktualisieren und entfernen
Vor jedem Update und vor dem Entfernen pausierst du den Runner in GitLab und wartest, bis laufende Jobs fertig sind. Laut GitLab-Dokumentation vermeidest du so Autorisierungsfehler, wenn Jobs abgeschlossen werden. Pausieren kannst du unter Settings > CI/CD > Runners im Bereich Assigned project runners mit Pause.
Runner aktualisieren
$ helm repo update gitlab
$ helm search repo -l gitlab/gitlab-runner
$ helm upgrade --namespace ci-runner \
-f runner-values.yaml \
gitlab-runner gitlab/gitlab-runner \
--version "<chart-version>"Ersetze <chart-version> durch die neue Chart-Version aus der Liste. Wähle sie wieder so, dass die App-Version zu deiner GitLab-Version passt. Gib die values.yaml bei jedem Upgrade mit an. Ohne -f übernimmt Helm zwar die Werte des letzten Releases, änderst du aber einzelne Werte nur mit --set, fallen alle übrigen eigenen Werte auf die Standardwerte des Charts zurück. Derselbe Befehl mit unveränderter Version spielt geänderte Werte ein, etwa neue Rechte oder Requests. Beim Neustart gibt Kubernetes dem alten Runner-Pod laut Chart-Standard bis zu 3.600 Sekunden, um laufende Jobs zu beenden. Danach setzt du den Runner in GitLab mit Resume fort.
Runner vollständig entfernen
- Pausiere den Runner in GitLab und warte, bis keine Jobs mehr laufen.
- Entferne das Helm-Release:
$ helm uninstall gitlab-runner --namespace ci-runner- Lösche den Namespace. Damit verschwinden auch das Secret
runner-authmit dem Token und eventuell übrig gebliebene Job-Pods:
$ kubectl delete namespace ci-runner- Lösche den Runner in GitLab unter Settings > CI/CD > Runners im Bereich Assigned project runners mit Remove runner und bestätige mit Remove.
Schritt 4 ist nötig, obwohl das Chart beim Beenden des Pods unregister aufruft (unregisterRunners: true ist Standard). Bei Tokens mit dem Präfix glrt- entfernt das laut Chart nur den Runner-Manager, nicht den Runner selbst.
Was bestehen bleibt: deine Datei runner-values.yaml, der Eintrag gitlab in deiner lokalen Helm-Repository-Liste und die .gitlab-ci.yml im Projekt. Jobs mit dem Tag kubernetes finden ohne Runner keinen Abnehmer mehr. Entferne den Job oder ändere die Tags, wenn du die Pipeline weiter nutzen willst.
Nächste Schritte
- Container-Images bauen: In einem folgenden Teil der Serie geht es darum, in der Pipeline Images zu bauen, ohne dem Runner privilegierte Container zu erlauben.
- Private Registry anbinden: Jobs, die Images aus einer privaten Registry ziehen, brauchen ein Pull-Secret. Für centron Managed Kubernetes beschreiben die Docs das unter Container Registry anbinden. In der Runner-Konfiguration verweist du mit
image_pull_secretsdarauf. - Cache einrichten: Ohne verteilten Cache startet jeder Job-Pod ohne Abhängigkeits-Cache. Das Chart kann einen S3-kompatiblen Cache einbinden. Die Zugangsdaten liegen in einem Secret, das du unter
runners.cache.secretNameangibst, die Einstellungen selbst stehen im Abschnitt[runners.cache]vonrunners.config. Die Optionen stehen in der values.yaml von Chart 0.93.0. - Deployen per GitOps: Wie eine Pipeline Änderungen über Git in den Cluster bringt, zeigt das Tutorial GitOps-basiertes CI/CD auf Kubernetes.
- Überblick: Wie CI/CD-Pipelines auf centron-Infrastruktur zusammenspielen, beschreibt die Seite CI/CD-Pipelines.
Testen Sie Ihr Setup auf ccloud³
Registrieren Sie sich in der ccloud³ und erhalten Sie 200 € Startguthaben für Ihr Projekt – z. B. für eine PostgreSQL-VM mit automatischen Backups.