DAG-Pipelines statt strikter Stages
In einer klassischen GitLab-Pipeline wartet jede Stage darauf, dass alle Jobs der vorherigen Stage fertig sind, selbst wenn ein Job gar nicht von den anderen abhaengt. Das Keyword needs durchbricht diese starre Reihenfolge und macht aus der Pipeline einen Directed Acyclic Graph, in dem Jobs starten, sobald ihre tatsaechlichen Abhaengigkeiten erfuellt sind, was die Gesamtlaufzeit oft drastisch verkuerzt.
Inhaltsverzeichnis
- 1. Das Problem des klassischen Stage-Modells
- 2. Wie needs den Ausfuehrungsgraphen veraendert
- 3. Parallele Zweige und schnellere Gesamtlaufzeit
- 4. needs ohne stages und die vollstaendige DAG-Pipeline
- 5. Artefakt-Steuerung und needs-Optionen im Detail
- 6. Grenzen: maximale Anzahl an needs und Zyklenpruefung
- 7. Eine bestehende Stage-Pipeline auf needs umstellen
- 8. Wann needs wenig bringt
- 9. Fazit: needs als gezielter Hebel fuer Pipeline-Geschwindigkeit
- 10. Zusammenfassung
- 11. FAQ
1. Das Problem des klassischen Stage-Modells
Im Standard-Ausfuehrungsmodell von GitLab CI ist eine Pipeline in Stages gegliedert, und alle Jobs einer Stage laufen parallel, aber erst die naechste Stage startet, wenn wirklich jeder Job der vorherigen Stage erfolgreich abgeschlossen ist. Dieses Modell ist einfach zu verstehen und fuer kleine Pipelines vollkommen ausreichend, wird aber zum Flaschenhals, sobald eine Stage einen einzelnen langsamen Job enthaelt, der auf mehrere schnelle Jobs in der naechsten Stage keinen inhaltlichen Einfluss hat. Ein typisches Beispiel ist eine Test-Stage mit einem schnellen Unit-Test-Job und einem deutlich langsameren End-to-End-Test-Job, gefolgt von einer Build-Stage, die eigentlich nur vom Unit-Test-Ergebnis abhaengt, aber trotzdem warten muss, bis auch der langsame E2E-Job fertig ist, weil das Stage-Modell keine feinere Abhaengigkeitssteuerung kennt.
Dieses Warten summiert sich in der Praxis erheblich, besonders in Pipelines mit vielen Stages und heterogenen Job-Laufzeiten. Ein Build-Job, der eigentlich in wenigen Sekunden starten koennte, wartet unter Umstaenden mehrere Minuten, nur weil ein voellig unabhaengiger Job in derselben Stage noch laeuft. Bei mehreren aufeinanderfolgenden Stages mit jeweils solchen Ungleichgewichten addiert sich die Wartezeit zu einer Gesamtlaufzeit, die deutlich laenger ist, als es die tatsaechliche Abhaengigkeitskette der Jobs erfordern wuerde. Genau dieses strukturelle Problem loest needs, indem es die Reihenfolge nicht mehr an die Stage-Grenze koppelt, sondern an explizit deklarierte Job-zu-Job-Abhaengigkeiten.
2. Wie needs den Ausfuehrungsgraphen veraendert
Sobald ein Job das Keyword needs mit einer Liste von Job-Namen erhaelt, ignoriert GitLab fuer diesen Job die strikte Stage-Reihenfolge und startet ihn, sobald alle in needs genannten Jobs abgeschlossen sind, unabhaengig davon, ob andere Jobs derselben oder frueherer Stages noch laufen. Die Stage-Zuordnung bleibt dabei fuer die Anzeige in der Pipeline-Ansicht und fuer die logische Gruppierung bestehen, verliert aber ihre Funktion als Ausfuehrungsschranke. Damit wird die Pipeline effektiv zu einem Directed Acyclic Graph, kurz DAG, in dem jeder Job ein Knoten ist und jede needs-Beziehung eine gerichtete Kante, die GitLab beim Pipeline-Start in eine optimale Ausfuehrungsreihenfolge uebersetzt.
Wichtig ist, dass needs nicht nur die Reihenfolge, sondern auch den Artefakt-Fluss steuert: Standardmaessig laedt ein Job mit needs automatisch die Artefakte der genannten Abhaengigkeiten herunter, selbst wenn diese aus einer frueheren Stage stammen, und ignoriert dabei Artefakte aus Jobs, die nicht in der needs-Liste stehen, selbst wenn diese in einer frueheren Stage liefen. Das ist ein bewusster Unterschied zum klassischen Verhalten, bei dem standardmaessig alle Artefakte aller vorherigen Stages verfuegbar sind. Wer von einem klassischen Stage-Modell auf needs umstellt, muss deshalb pruefen, ob ein Job tatsaechlich alle Artefakte bekommt, die er braucht, weil sich der Artefakt-Scope durch die Migration aendert und sich sonst schwer nachvollziehbare Fehler in nachgelagerten Jobs einschleichen koennen.
stages: [build, test, package, deploy]
build_frontend:
stage: build
script: [npm run build]
build_backend:
stage: build
script: [composer install --no-dev]
unit_tests:
stage: test
needs: [build_backend]
script: [vendor/bin/phpunit]
package_app:
stage: package
needs: [build_frontend, unit_tests]
script: [./package.sh]
3. Parallele Zweige und schnellere Gesamtlaufzeit
Der grosse praktische Nutzen von needs zeigt sich, sobald eine Pipeline mehrere unabhaengige Zweige enthaelt, die erst spaeter wieder zusammenlaufen. Im klassischen Modell laufen zum Beispiel Frontend-Build und Backend-Build in derselben Stage parallel, aber die naechste Stage muss auf beide warten, selbst wenn die davon abhaengigen Tests jeweils nur einen der beiden Zweige betreffen. Mit needs kann jeder Test-Job gezielt nur auf den fuer ihn relevanten Build-Job warten, sodass Frontend-Tests loslaufen koennen, sobald der Frontend-Build fertig ist, ganz unabhaengig davon, ob der Backend-Build noch fortlaeuft. Diese Entkopplung fuehrt in der Praxis dazu, dass die Gesamtlaufzeit einer Pipeline naeher an die Laufzeit des laengsten tatsaechlichen Abhaengigkeitspfads rueckt statt an die Summe aller Stage-Laufzeiten.
Fuer Pipelines mit klar trennbaren Komponenten, etwa einem Frontend, einem Backend und einer Infrastruktur-Definition, kann needs die Gesamtlaufzeit um 30 bis 50 Prozent senken, je nachdem wie unausgeglichen die Job-Laufzeiten innerhalb der einzelnen Stages ursprünglich verteilt waren. Der Effekt ist besonders gross, wenn eine Pipeline viele Stages mit jeweils nur wenigen Jobs hat, weil sich dort die Wartezeiten zwischen den Stages am staerksten summieren. Teams, die ihre Pipeline-Laufzeit senken wollen, sollten deshalb zuerst pruefen, welche Jobs tatsaechlich voneinander abhaengen und welche nur zufaellig in derselben Stage-Reihenfolge stehen, weil genau dort das groesste ungenutzte Optimierungspotenzial liegt.
4. needs ohne stages und die vollstaendige DAG-Pipeline
Seit neueren GitLab-Versionen ist das stages-Keyword fuer needs-basierte Pipelines nicht mehr zwingend erforderlich, weil GitLab die Ausfuehrungsreihenfolge vollstaendig aus dem needs-Graphen ableiten kann, ohne dass jeder Job noch einer Stage zugeordnet sein muss. In diesem Modus faellt die Stage-Spalte in der Pipeline-Ansicht weg und stattdessen wird ausschliesslich der Abhaengigkeitsgraph visualisiert, was fuer sehr komplexe Pipelines mit vielen unabhaengigen Zweigen deutlich uebersichtlicher sein kann als eine lange Liste kuenstlich benannter Stages, die eigentlich nur zur Gruppierung dienten.
In der Praxis empfiehlt sich diese vollstaendige DAG-Variante vor allem fuer neu aufgesetzte Pipelines, waehrend bei der Migration einer bestehenden Pipeline oft ein hybrider Ansatz sinnvoller ist: Die Stages bleiben als grobe logische Gruppierung erhalten, aber innerhalb und zwischen den Stages sorgt needs fuer die tatsaechliche Ausfuehrungsreihenfolge. Dieser hybride Ansatz ist leichter zu kommunizieren, weil Teammitglieder weiterhin an bekannten Begriffen wie build, test und deploy orientiert bleiben, waehrend die Performance-Vorteile von needs trotzdem vollstaendig genutzt werden, ohne dass die gesamte Pipeline-Struktur neu gedacht werden muss.
# Vollstaendige DAG-Pipeline ohne explizite Stage-Reihenfolge
lint:
stage: .pre
script: [composer run lint]
build:
needs: []
script: [composer install]
test:
needs: [build]
script: [vendor/bin/phpunit]
deploy:
needs: [test, lint]
script: [./deploy.sh]
5. Artefakt-Steuerung und needs-Optionen im Detail
needs akzeptiert nicht nur eine einfache Liste von Job-Namen, sondern auch eine erweiterte Objekt-Syntax mit den Feldern job, artifacts und optional. Mit artifacts: false laesst sich gezielt verhindern, dass Artefakte einer Abhaengigkeit heruntergeladen werden, obwohl die Ausfuehrungsreihenfolge weiterhin von dieser Abhaengigkeit bestimmt wird, was etwa bei einem Job sinnvoll ist, der nur auf den erfolgreichen Abschluss eines vorherigen Jobs wartet, aber dessen Build-Artefakte gar nicht braucht. Das Feld optional: true erlaubt es, dass eine Abhaengigkeit unter bestimmten rules-Bedingungen gar nicht existiert, ohne dass die Pipeline dadurch fehlschlaegt, was bei bedingt erzeugten Jobs in Kombination mit rules haeufig gebraucht wird.
Zusaetzlich unterstuetzt needs auch Cross-Pipeline- und Cross-Projekt-Abhaengigkeiten ueber das Feld pipeline beziehungsweise project, wodurch ein Job in einer Pipeline auf Artefakte oder den Status eines Jobs aus einer anderen, bereits abgeschlossenen Pipeline warten kann. Diese Faehigkeit wird vor allem in groesseren Organisationen genutzt, in denen mehrere Projekte lose gekoppelt sind, etwa wenn ein Deployment-Repository auf das erfolgreiche Bauen eines Artefakts in einem separaten Build-Repository wartet, ohne dass beide Repositories in einer einzigen Monorepo-Pipeline zusammengefasst werden muessen.
deploy:
stage: deploy
needs:
- job: build
artifacts: true
- job: security_scan
optional: true
- job: lint
artifacts: false
script:
- ./deploy.sh
6. Grenzen: maximale Anzahl an needs und Zyklenpruefung
GitLab begrenzt die Anzahl der needs-Eintraege pro Job standardmaessig auf 50, was fuer die allermeisten Pipelines mehr als ausreichend ist, in extrem verzweigten Monorepo-Pipelines mit vielen Teilprojekten aber theoretisch relevant werden kann. Wird dieses Limit ueberschritten, meldet GitLab bereits beim Parsen der .gitlab-ci.yml einen Fehler, sodass das Problem nicht erst zur Laufzeit auffaellt, sondern schon beim Commit oder in der CI-Lint-Pruefung. In solchen Faellen hilft es meist, die Abhaengigkeiten ueber Zwischenjobs zu buendeln, die selbst mehrere needs-Eintraege zusammenfassen und von nachgelagerten Jobs dann nur noch als eine einzige Abhaengigkeit referenziert werden.
GitLab prueft zudem automatisch, ob der aus needs entstehende Graph zyklenfrei ist, also ob es keine Kette von Abhaengigkeiten gibt, die letztlich auf sich selbst zurueckfuehrt. Ein solcher Zyklus waere logisch unausfuehrbar, weil zwei Jobs gegenseitig aufeinander warten wuerden, und GitLab lehnt eine Pipeline mit einem erkannten Zyklus bereits bei der Validierung ab, bevor auch nur ein einziger Job gestartet wird. Diese eingebaute Pruefung ist besonders wertvoll in grossen, oft von mehreren Teams gepflegten Pipelines, in denen ein versehentlich eingefuehrter Zyklus sonst erst nach einem fehlgeschlagenen Pipeline-Start auffallen wuerde.
7. Eine bestehende Stage-Pipeline auf needs umstellen
Der pragmatische Einstieg fuer eine bestehende Pipeline ist, zunaechst die tatsaechlichen inhaltlichen Abhaengigkeiten zwischen den Jobs zu kartieren, unabhaengig davon, in welcher Stage sie aktuell stehen. Oft zeigt sich dabei, dass die Stage-Reihenfolge historisch eher zufaellig entstanden ist und viele Jobs eigentlich gar keine echte Abhaengigkeit zu allen Jobs der vorherigen Stage haben, sondern nur zu ein oder zwei konkreten Jobs. Diese Kartierung ist der wichtigste Schritt, weil eine falsch gesetzte needs-Liste entweder zu fehlenden Artefakten fuehrt, wenn eine echte Abhaengigkeit vergessen wird, oder zu unveraendert langsamen Pipelines, wenn zu vorsichtig weiterhin auf zu viele Jobs gewartet wird.
Nach der Kartierung empfiehlt sich eine schrittweise Einfuehrung, beginnend mit den Jobs, die den groessten Zeitgewinn versprechen, typischerweise die Jobs am Ende einer langen Stage-Kette, die eigentlich nur von einem einzelnen fruehen Job abhaengen. Die CI/CD-Pipeline-Ansicht in GitLab visualisiert den entstehenden Graphen direkt und macht sichtbar, ob die neue needs-Struktur tatsaechlich zur erwarteten Parallelisierung fuehrt. Ein Vergleich der Pipeline-Dauer vor und nach der Umstellung, sichtbar in der Pipeline-Analytics-Ansicht des Projekts, liefert dabei einen konkreten Beleg fuer den Nutzen und hilft, die Investition gegenueber dem Team zu rechtfertigen.
8. Wann needs wenig bringt
needs entfaltet seinen Nutzen vor allem bei ungleichmaessig verteilten Job-Laufzeiten und mehreren parallelen Abhaengigkeitszweigen. Bei sehr kleinen Pipelines mit nur zwei oder drei Jobs, die ohnehin schon fast vollstaendig sequenziell voneinander abhaengen, bringt die Umstellung kaum messbaren Zeitgewinn, fuehrt aber trotzdem zusaetzliche Komplexitaet in die Pipeline-Datei ein. In solchen Faellen ist es meist sinnvoller, die einfache Stage-Reihenfolge beizubehalten, weil der Wartungsaufwand fuer die needs-Pflege den geringen Zeitgewinn nicht rechtfertigt.
Auch bei Pipelines, in denen Runner-Kapazitaet der eigentliche Engpass ist, etwa weil nur wenige Shared Runner zur Verfuegung stehen, bringt needs weniger als erwartet, weil parallel startbereite Jobs trotzdem auf einen freien Runner warten muessen. In solchen Umgebungen sollte vor der needs-Optimierung zuerst die Runner-Kapazitaet geprueft werden, etwa durch Autoscaling oder zusaetzliche Runner-Tags fuer unterschiedliche Job-Typen, weil andernfalls die theoretische Parallelisierung durch needs in der Praxis an der begrenzten Anzahl gleichzeitig verfuegbarer Runner scheitert und der erhoffte Zeitgewinn ausbleibt.
9. Fazit: needs als gezielter Hebel fuer Pipeline-Geschwindigkeit
needs verwandelt eine starre Stage-Pipeline in einen Directed Acyclic Graph, in dem Jobs so frueh wie moeglich starten, statt auf kuenstliche Stage-Grenzen zu warten, was in Pipelines mit ungleichmaessigen Job-Laufzeiten und mehreren parallelen Zweigen spuerbare Zeitersparnis bringt. Der Umstieg erfordert eine sorgfaeltige Kartierung der tatsaechlichen Abhaengigkeiten und ein Bewusstsein dafuer, dass sich mit needs auch der Artefakt-Scope aendert, ist aber mit dem hybriden Ansatz aus bestehenden Stages plus gezielten needs-Eintraegen risikoarm umsetzbar.
Die folgende Tabelle stellt das klassische Stage-Modell und das needs-basierte DAG-Modell entlang der wichtigsten Kriterien gegenueber, als Entscheidungshilfe fuer die eigene Pipeline.
| Kriterium | Klassisches Stage-Modell | needs-basiertes DAG-Modell | Praxis-Empfehlung |
|---|---|---|---|
| Job-Start | erst wenn gesamte vorherige Stage fertig ist | sobald genannte Abhaengigkeiten fertig sind | needs bei ungleichen Job-Laufzeiten einsetzen |
| Artefakt-Verfuegbarkeit | alle Artefakte aller vorherigen Stages | nur Artefakte der needs-Liste | needs-Liste vor Umstellung sorgfaeltig kartieren |
| Komplexitaet der Konfiguration | gering, lineare Reihenfolge | hoeher, expliziter Graph noetig | bei kleinen Pipelines Stage-Modell beibehalten |
| Skalierung mit vielen Zweigen | Wartezeiten summieren sich | parallele Zweige laufen unabhaengig | besonders bei Monorepos und Multi-Komponenten sinnvoll |
| Runner-Abhaengigkeit | weniger relevant | profitiert von ausreichender Runner-Kapazitaet | Autoscaling pruefen bevor needs eingefuehrt wird |
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
needs und DAG-Pipelines: Das Wichtigste auf einen Blick
Kernidee von needs
Jobs starten sobald ihre expliziten Abhaengigkeiten fertig sind, statt auf das Ende der gesamten vorherigen Stage zu warten.
Groesster Effekt
Deutliche Zeitersparnis bei Pipelines mit mehreren parallelen, ungleich langen Abhaengigkeitszweigen.
Wichtigste Falle
Artefakt-Scope aendert sich mit needs, nur die genannten Jobs liefern automatisch ihre Artefakte.
Migrationstipp
Zunaechst echte Abhaengigkeiten kartieren, dann hybrid mit bestehenden Stages plus needs schrittweise einfuehren.