cron-Syntax, Variablen und der Unterschied zum Server-Cronjob
Nicht jede Pipeline muss durch einen Push oder Merge Request ausgeloest werden. Naechtliche Security-Scans, wiederkehrende Aufraeumjobs oder regelmaessige Abhaengigkeits-Updates laufen am besten zeitgesteuert, unabhaengig davon, ob an dem Tag ueberhaupt jemand Code committet hat. GitLabs Scheduled Pipelines bieten dafuer einen in die Plattform integrierten Cron-Mechanismus. Dieser Artikel zeigt die Einrichtung, die cron-Syntax, den Umgang mit Pipeline-Variablen und warum eine Scheduled Pipeline etwas grundlegend anderes ist als ein klassischer Cronjob auf einem Server.
Inhaltsverzeichnis
- 1. Wozu zeitgesteuerte Pipelines gut sind
- 2. Einrichtung: Ein Schedule in der GitLab-Oberflaeche anlegen
- 3. Die cron-Syntax im Detail und die Rolle der Zeitzone
- 4. Pipeline-Schedule-Variablen fuer unterschiedliche Laeufe nutzen
- 5. Scheduled Jobs mit rules gezielt von normalen Pipelines abgrenzen
- 6. Warum eine Scheduled Pipeline kein klassischer Server-Cronjob ist
- 7. Anwendungsfall: Naechtliche Security-Scans
- 8. Anwendungsfall: Wiederkehrende Wartungsjobs
- 9. Best Practices und Vergleich mit Alternativen
- 10. Zusammenfassung
- 11. FAQ
1. Wozu zeitgesteuerte Pipelines gut sind
Die klassischen Pipeline-Trigger in GitLab, also Push, Merge Request und manuelle Ausloesung, decken den Alltag der Softwareentwicklung gut ab, lassen aber eine wichtige Kategorie von Aufgaben aussen vor: alles, was regelmaessig und unabhaengig von Code-Aenderungen passieren muss. Ein nächtlicher Security-Scan soll auch dann laufen, wenn tagsueber niemand committet hat. Ein woechentliches Dependency-Update soll pruefen, ob neue Versionen verfuegbar sind, ganz ohne dass jemand die Pipeline manuell startet.
Genau fuer diese Faelle gibt es Scheduled Pipelines. Sie werden im Projekt unter CI/CD > Schedules konfiguriert und ausgeloest GitLab die hinterlegte .gitlab-ci.yml so, als waere ein Pipeline-Trigger von aussen eingetroffen, allerdings mit CI_PIPELINE_SOURCE gleich schedule statt push. Damit lassen sich in derselben Pipeline-Datei sowohl normale Commit-Pipelines als auch die zeitgesteuerten Laeufe unterscheiden und mit unterschiedlichem Job-Umfang versehen, ohne zwei getrennte Pipelines pflegen zu muessen.
2. Einrichtung: Ein Schedule in der GitLab-Oberflaeche anlegen
Ein neuer Schedule wird unter Build > Pipeline schedules angelegt und besteht im Kern aus vier Angaben: einer Beschreibung, dem cron-Ausdruck fuer den Zeitpunkt, der Zeitzone sowie dem Ziel-Branch oder -Tag, auf dem die Pipeline ausgefuehrt wird. Zusaetzlich koennen pro Schedule eigene CI/CD-Variablen hinterlegt werden, die nur bei diesem konkreten Schedule gesetzt sind und in keiner anderen Pipeline auftauchen. Wichtig ist, dass der ausfuehrende Nutzer, unter dessen Identitaet die Pipeline laeuft, ausreichende Berechtigungen fuer alle referenzierten Jobs haben muss.
Nach dem Anlegen laesst sich der Schedule jederzeit ueber den Button Run now manuell ausloesen, was fuer das Testen der Konfiguration unverzichtbar ist. Erst wenn ein manueller Testlauf erfolgreich durchlaeuft, sollte man sich darauf verlassen, dass der cron-Ausdruck wie erwartet zuenden wird. GitLab fuehrt Scheduled Pipelines mit einer gewissen, technisch bedingten Verzoegerung von bis zu wenigen Minuten aus, was bei zeitkritischen Anwendungsfaellen einkalkuliert werden sollte.
# .gitlab-ci.yml
nightly-security-scan:
stage: test
script:
- echo "Running nightly security scan"
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
3. Die cron-Syntax im Detail und die Rolle der Zeitzone
GitLab nutzt fuer Schedules die klassische Fuenf-Felder-cron-Syntax: Minute, Stunde, Tag des Monats, Monat und Wochentag, jeweils getrennt durch ein Leerzeichen. Der Ausdruck 0 2 * * * bedeutet demnach jeden Tag um zwei Uhr nachts, waehrend 0 3 * * 1-5 nur an Werktagen um drei Uhr feuert. Sternchen stehen fuer jeden moeglichen Wert des jeweiligen Feldes, Kommas trennen mehrere konkrete Werte und Bindestriche definieren Bereiche wie 1-5 fuer Montag bis Freitag.
Ein haeufig uebersehener Punkt ist die Zeitzone: Sie wird beim Anlegen des Schedules separat ausgewaehlt und ist unabhaengig von der Zeitzone des GitLab-Servers oder der Runner. Wer versaeumt, sie explizit auf die eigene Zielzeitzone zu setzen, wundert sich mitunter, warum der nächtliche Lauf mitten am Tag oder mehrere Stunden verschoben stattfindet, insbesondere bei GitLab.com, wo standardmaessig UTC verwendet wird. Bei der Umstellung von Sommer- auf Winterzeit kann sich der tatsaechliche Ausfuehrungszeitpunkt zudem um eine Stunde verschieben, was bei besonders zeitkritischen Jobs beruecksichtigt werden sollte.
4. Pipeline-Schedule-Variablen fuer unterschiedliche Laeufe nutzen
Jeder Schedule kann eigene CI/CD-Variablen mitbringen, die nur waehrend dieses spezifischen zeitgesteuerten Laufs gesetzt sind. Das erlaubt es, denselben Job in der .gitlab-ci.yml fuer unterschiedliche Zwecke wiederzuverwenden, etwa einen generischen Scan-Job, der je nach Schedule entweder einen schnellen taeglichen oder einen umfassenden woechentlichen Scan durchfuehrt, gesteuert ueber eine Variable wie SCAN_DEPTH. So muessen keine separaten Job-Definitionen fuer jede zeitliche Variante gepflegt werden.
In der Praxis bewaehrt es sich, mehrere Schedules mit klar sprechenden Beschreibungen anzulegen, zum Beispiel Nightly Quick Scan und Weekly Deep Scan, statt einen einzigen Schedule mit komplexer interner Verzweigungslogik zu ueberladen. Das macht die Konfiguration in der GitLab-Oberflaeche selbsterklaerend und erleichtert es neuen Teammitgliedern, auf einen Blick zu verstehen, welcher Schedule wofuer zustaendig ist, ohne die Pipeline-Definition im Detail lesen zu muessen.
# .gitlab-ci.yml
dependency-scan:
stage: test
variables:
SCAN_DEPTH: "quick"
script:
- echo "Running dependency scan with depth $SCAN_DEPTH"
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
5. Scheduled Jobs mit rules gezielt von normalen Pipelines abgrenzen
Der Schluessel zur Unterscheidung zwischen einer normalen Commit-Pipeline und einem zeitgesteuerten Lauf ist die vordefinierte Variable CI_PIPELINE_SOURCE. Sie nimmt bei Scheduled Pipelines den Wert schedule an, waehrend sie bei einem gewoehnlichen Push push und bei einem Merge Request merge_request_event enthaelt. Mit einer rules-Bedingung wie if: $CI_PIPELINE_SOURCE == schedule laesst sich ein Job gezielt nur bei zeitgesteuerten Laeufen aktivieren oder umgekehrt bei normalen Commit-Pipelines gezielt deaktivieren.
Besonders nuetzlich ist die Kombination mehrerer rules-Bedingungen, um zwischen unterschiedlichen Trigger-Arten fein zu differenzieren: Ein umfangreicher, mehrere Minuten dauernder Integrationstest laeuft dann etwa nur bei Scheduled Pipelines, waehrend bei jedem normalen Push lediglich ein schneller Unit-Test-Lauf stattfindet. Das haelt die Feedback-Zeit fuer Entwickler kurz, ohne auf die gruendlichere, aber zeitaufwendigere Pruefung zu verzichten, die dann eben nachts automatisch erfolgt.
6. Warum eine Scheduled Pipeline kein klassischer Server-Cronjob ist
Auf den ersten Blick wirkt eine Scheduled Pipeline wie ein simpler Ersatz fuer einen crontab-Eintrag auf einem Server, doch die Unterschiede sind erheblich. Ein klassischer Cronjob laeuft direkt auf dem Zielserver, mit dessen lokaler Umgebung, dessen installierten Paketen und dessen Dateisystem, ganz ohne Containerisierung oder Isolation. Eine Scheduled Pipeline dagegen startet einen vollstaendigen GitLab-Runner-Job, typischerweise in einem frischen Docker-Container, inklusive Checkout des Repositories, Cache-Wiederherstellung und allem, was auch eine normale Pipeline mitbringt.
Das hat handfeste praktische Konsequenzen: Eine Scheduled Pipeline hat automatisch Zugriff auf Pipeline-Logs, Artifacts, den vollstaendigen Job-Verlauf in der GitLab-Oberflaeche und kann bei Fehlschlag ueber die gleichen Benachrichtigungsmechanismen wie jede andere Pipeline alarmieren, etwa per E-Mail oder Slack-Integration. Ein klassischer Server-Cronjob dagegen protokolliert bestenfalls in eine Logdatei oder per Mail an root, ohne die strukturierte Nachvollziehbarkeit, die GitLabs Pipeline-Historie von Haus aus mitbringt. Dafuer eignet sich ein echter Cronjob besser fuer Aufgaben, die direkt und ohne Container-Overhead auf dem Zielsystem selbst laufen muessen, etwa eine Datenbank-Wartung auf demselben Host.
7. Anwendungsfall: Naechtliche Security-Scans
Ein besonders verbreiteter Anwendungsfall fuer Scheduled Pipelines sind vollstaendige Security-Scans, die tagsueber zu lange dauern wuerden, um sie bei jedem Push auszufuehren. Waehrend ein schneller SAST-Scan durchaus bei jedem Merge Request Sinn ergibt, kann ein umfassender Dependency- oder Container-Scan mit vollstaendiger Datenbank-Aktualisierung mehrere Minuten in Anspruch nehmen. Ein naechtlicher Schedule um zwei oder drei Uhr sorgt dafuer, dass diese Grundlichkeit trotzdem taeglich stattfindet, ohne die Entwickler-Feedback-Schleife tagsueber zu verlangsamen.
Ergaenzend bietet es sich an, das Ergebnis eines solchen naechtlichen Scans automatisiert in einen Slack-Kanal oder per E-Mail an das Security-Team zu senden, wenn neue kritische Findings auftauchen, statt sich darauf zu verlassen, dass jemand taeglich manuell in die Pipeline-Uebersicht schaut. Ein einfacher Job am Ende der Pipeline, der bei Fehlschlag eine Webhook-Benachrichtigung ausloest, schliesst diese Lücke zuverlaessig und stellt sicher, dass kritische Funde nicht erst Tage spaeter auffallen.
# .gitlab-ci.yml
notify-on-finding:
stage: notify
script:
- |
if [ "$SCAN_RESULT" = "critical" ]; then
curl -X POST -H 'Content-type: application/json' \
--data '{"text":"Kritischer Security-Fund im naechtlichen Scan"}' \
"$SLACK_WEBHOOK_URL"
fi
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
needs: ["dependency-scan"]
8. Anwendungsfall: Wiederkehrende Wartungsjobs
Neben Security-Scans eignen sich Scheduled Pipelines hervorragend fuer Wartungsaufgaben, die regelmaessig, aber nicht bei jedem Commit erfolgen sollen. Beispiele sind das Aufraeumen alter, nicht mehr benoetigter Docker-Images in der eigenen Container-Registry, das Loeschen abgelaufener Feature-Branch-Umgebungen, das Erneuern von SSL-Zertifikaten ueber Let's Encrypt oder das Erstellen und Verifizieren regelmaessiger Datenbank-Backups mit anschliessendem Restore-Test in einer isolierten Umgebung.
Der Vorteil gegenueber einem externen Cron-Tool ist, dass diese Wartungsjobs direkt im selben Repository und in derselben Versionierung wie der restliche Anwendungscode liegen. Aenderungen an der Backup-Strategie oder der Bereinigungslogik durchlaufen denselben Merge-Request-Review-Prozess wie jede andere Code-Aenderung, was die Nachvollziehbarkeit und Qualitaetssicherung fuer sicherheitsrelevante Wartungsaufgaben deutlich verbessert im Vergleich zu einem isoliert gepflegten Skript auf irgendeinem Server.
9. Best Practices und Vergleich mit Alternativen
Ein solider Umgang mit Scheduled Pipelines beginnt damit, jeden Schedule mit einer aussagekraeftigen Beschreibung zu versehen und regelmaessig zu pruefen, ob er noch benoetigt wird. Verwaiste Schedules, deren urspruengliche Aufgabe laengst obsolet ist, verbrauchen unnoetig CI-Minuten und sorgen fuer Verwirrung. Ebenso wichtig ist, Fehlschlaege von Scheduled Pipelines nicht stillschweigend zu ignorieren, sondern eine Benachrichtigung einzurichten, da sonst ein nächtlicher Sicherheitsscan wochenlang unbemerkt fehlschlagen kann.
Im Vergleich zu Alternativen wie einem klassischen Server-Cronjob oder einem Kubernetes CronJob-Objekt bietet GitLab den Vorteil der einheitlichen Oberflaeche, der Versionierung der Job-Definition im selben Repository und der nahtlosen Integration in bestehende Pipeline-Variablen und Secrets. Die folgende Tabelle stellt die drei Ansaetze anhand ihrer wichtigsten Eigenschaften gegenueber, um die Entscheidung fuer den jeweiligen Anwendungsfall zu erleichtern.
| Ansatz | Ausfuehrungsort | Nachvollziehbarkeit | Typischer Einsatz |
|---|---|---|---|
| GitLab Scheduled Pipeline | GitLab-Runner, containerisiert | Volle Pipeline-Historie und Logs | Naechtliche Scans, Repository-nahe Wartung |
| Server-Cronjob (crontab) | Direkt auf dem Zielserver | Nur Logdatei oder Mail an root | Serverlokale Aufgaben ohne Container-Overhead |
| Kubernetes CronJob | Innerhalb des Kubernetes-Clusters | kubectl logs, Cluster-Events | Wiederkehrende Jobs in Cluster-nativen Setups |
| Externer Scheduler-Dienst | Ausserhalb von GitLab und Server | Abhaengig vom jeweiligen Tool | Cross-System-Orchestrierung ueber mehrere Plattformen |
Mironsoft
CI/CD-Pipelines, Zero-Downtime-Deployments und Release-Automatisierung
Deployments, die ohne Ausfallzeit und ohne Nervenkitzel laufen?
Wir prüfen bestehende GitLab-Pipelines auf fragile Deployment-Schritte und fehlende Absicherung und bauen daraus einen Release-Prozess mit Zero-Downtime-Deployments, automatisierten Checks und einem Rollback, dem ihr im Ernstfall vertrauen könnt.
Pipeline-Review
Bestehende .gitlab-ci.yml auf Fragilität, fehlende Stages und Sicherheitslücken prüfen.
Zero-Downtime-Deployment
Symlink-Releases, Health-Checks und Rollback-Strategien für Magento-Shops aufbauen.
CI/CD-Automatisierung
Tests, Security-Scans und Deployments zu einer zuverlässigen Pipeline verbinden.
10. Zusammenfassung
GitLab Scheduled Pipelines: Das Wichtigste auf einen Blick
Zeitgesteuert statt Push
Scheduled Pipelines laufen nach cron-Zeitplan, unabhaengig davon, ob an dem Tag committet wurde.
CI_PIPELINE_SOURCE
Die Variable schedule unterscheidet zeitgesteuerte Laeufe zuverlaessig von normalen Commit-Pipelines.
Kein Server-Cronjob
Scheduled Pipelines laufen containerisiert im Runner, mit voller Log- und Artifact-Historie in GitLab.
Typische Anwendungsfaelle
Naechtliche Security-Scans, Registry-Aufraeumung, Backup-Verifikation und Zertifikatserneuerung.