Moderne CI/CD-Tools (GitHub, GitLab usw.) basieren heute alle auf Pipelines, die auf einer Vielzahl von Docker-Containern laufen. So könnt ihr eure Pipelines modular gestalten und teamübergreifend nutzen, damit sie übersichtlich bleiben. Der Hauptgrund dafür, eure Pipelines auf diese Weise auszuführen, ist jedoch, das altbekannte Problem „Läuft auf meinem Rechner“ zu lösen.
Tatu Kairi
Principal Consultant
Tatu enjoys piña coladas, getting caught in the rain, is not into yoga and has half a brain.
Meistens beobachten wir: Je größer das Projekt – und die Pipelines, die es bauen und testen – wird, desto mehr Aufwand müssen Teams in deren Wartung investieren. Das führt dazu, dass die CI/CD die einzige Möglichkeit ist, die Software zu bauen und zu testen, weil sie nur auf einer einzigen Maschine funktioniert.
Wenn eure CI/CD-Tools also ausfallen, kann das für euer Team katastrophale Folgen haben: Ohne eure Tools kommt die gesamte Entwicklung zum Stillstand. Aber selbst wenn dieses Szenario nie eintritt, ist die Migration auf neuere, fortschrittlichere Tools schwierig – vielleicht sogar unmöglich. Und müssen wir wirklich begründen, warum ihr immer bessere Tools haben wollt?
In diesem Blog habe ich einige Tipps zusammengestellt, wie ihr das Problem „funktioniert auf meiner Maschine“ vermeidet und künftig neue CI/CD-Tools nutzen könnt.
Jeden Schritt containerisieren
Kurz gesagt: Das Konzept der Containerisierung zwingt euch dazu, über die Eingabeargumente und das gewünschte Ergebnis nachzudenken. In containerisierten Schritten zu denken, ist bei der Arbeit mit CI/CD vergleichbar mit dem Einsatz von Funktionen beim Programmieren.
Die Containerisierung jedes Schritts bietet mehrere Vorteile:
Die Versionsverwaltung wird einfacher, da ihr nachvollziehen könnt, wie sich jeder Schritt entwickelt hat, und mehrere Versionen desselben Elements in unterschiedlichen Kontexten, etwa Projekten, nutzen könnt.
Containerisierung vereinfacht Tests und Debugging, da ihr den Container bei Problemen in der Pipeline einfach auf eurer Entwicklungsmaschine ausführen könnt.
Docker, ein beliebtes Tool zur Containerisierung, fördert die Erstellung schlanker Container – also Schritte – und sorgt so für eine extrem schnelle Performance.
Wenn die einzelnen Komponenten gut modularisiert sind, können wir die verschiedenen Schritte auch parallelisieren. Weitere Informationen findet ihr im Directed Acyclic Graph (DAG).
Die interne Logik in Containern kann komplex sein – darauf gehe ich später noch ein. Die Logik, die außerhalb des Containers wirkt, sollte jedoch immer einfach bleiben. Diese Best Practice solltet ihr stets befolgen.
Ein Drittanbieter-Tool nutzen, um sie in eurer Organisation bereitzustellen
Ein Repository mit allen containerisierten CI/CD-Schritten eurer Organisation fördert die Auffindbarkeit und Wiederverwendung. Eure Teams müssen also keinen zusätzlichen Aufwand betreiben, wenn die Schritte bereits vorhanden sind. Das verbessert wiederum die Zusammenarbeit in der gesamten Organisation.
Auch wenn eure CI/CD ausfällt, könnt ihr mit wenigen `docker pull`-Befehlen dieselben Schritte ausführen wie in eurer CI/CD. Eure Arbeit wird also nie unterbrochen.
Task-Tools nutzen, um komplexe Logik zu kapseln
Bash ist großartig, aber als 50 Jahre alte Programmiersprache zeigt es sein Alter. Inzwischen gibt es neue, modernere Programmiersprachen, die wir ohnehin bereits in unseren Projekten verwenden, um komplexe Logik abzubilden. Und seien wir ehrlich: Jeder behauptet, Bash zu beherrschen, aber wirklich tun es die wenigsten – mich eingeschlossen.
Wenn ihr also komplexe Logik – mehr als einfache If-Else-Verzweigungen – in euren Build-Pipelines benötigt, könnt ihr diese Tools verwenden, um sie in der Programmiersprache zu schreiben, die ihr aus eurem Projekt bereits kennt.
Für jede Sprache gibt es Task-Tools. Einige bekannte Beispiele sind:
NPM für Node
Invoke für Python
Rake für Ruby
Maven für Java
Bazel für C
Verwendet diese Task-Tools in euren Containern, statt Bash-Skripte zu schreiben. So könnt ihr weitere Best Practices der Softwareentwicklung, etwa Unit-Tests, nutzen und sicherstellen, dass eure Logik zuverlässig funktioniert – ohne zwischen dem „eigentlichen“ Code und dem CI/CD-Code den Kontext wechseln zu müssen.
Secrets und Umgebungsvariablen außerhalb der CI/CD
Secrets und Umgebungsvariablen nehmen im Laufe eines Projekts zu und erhöhen dessen Komplexität. Deshalb sollten sie in zwei separate Kategorien unterteilt werden:
Build-Time: Diese werden während des CI/CD-Prozesses benötigt, um das Projekt in nutzbare Artefakte zu verpacken. Ihr solltet ihre Anzahl immer so gering wie möglich halten, ganz loswerden werdet ihr sie aber nie.
Run-Time: Diese werden beim Start der Anwendung benötigt – oder während sie läuft. Davon gibt es viele, und sie werden häufig in CI/CD hinterlegt. Besser wäre es jedoch, wenn sie dort gar nicht erst wären. Oft werden beispielsweise Zugangsdaten und URLs für die Datenbankverbindung in CI/CD integriert. Was aber, wenn ihr sie ändern müsst, während die Software bereits live ist? Wenn sie in eurem CI/CD liegen, müsst ihr ein neues Release erstellen. Das ist deutlich umständlicher, als sie in einem Drittanbietersystem wie HashiCorp Vault zu bearbeiten. Wenn ihr sie aus der Gleichung entfernt, verringert sich auch die Auswirkung eines Ausfalls von CI/CD.
Fazit
Wenn ihr jeden der oben genannten Schritte umsetzt, seid ihr auf dem richtigen Weg zu schnellerem CI/CD – und alles wird deutlich einfacher. Natürlich ist das leichter gesagt als getan. Aber zumindest sind diese Schritte keine allzu abschreckende Aufgabe!
- CI/CD
Subscribe to our newsletter
Related blogs