Linux-Magazin-Autor Peter Förger arbeitet für die IT der Deutschen Bahn und erklärt, wie die Teams seines Arbeitgebers Gitlab CI als Plattform für Continuous-Integration- und Deployment-Prozesse verwenden.
Der Wandel schreitet manchmal rasch voran: War noch vor einem Jahr Jenkins der unangefochtene Platzhirsch im Bereich CI/CD in unseren Teams, gibt es inzwischen erste Gruppen, die Gitlab CI mit Begeisterung nutzen.
Der vorliegende Artikel beleuchtet die Gründe. Die dabei geschilderten Best Practices resultieren aus der täglichen Arbeit als Netzwerk von Devops-Experten. Wir betreuen die Transformation von Teams, die künftig als Devops-Teams arbeiten möchten oder es bereits tun.
Gitlab kann mehr als SCM
Mit jeder neuen Release hält eine beeindruckende Anzahl neuer Features Einzug in die Gitlab-Varianten [1]. Das Kernteam hat sich offenkundig auf die Fahnen geschrieben, den gesamten Softwarelebenszyklus abzubilden und zum Schweizer Messer für Devops-Teams zu werden. Von der Planung bis zum Monitoring bietet die Sourcecode-Management-Software (SCM) diverse Komponenten, deren Ausbaustufe je nach Edition variiert.
Der Artikel bezieht sich auf die frei verfügbare Gitlab Community Edition [2]. Er beschreibt außerdem Szenarien, die vor allem für die Devops-Teams von DB Systel große Relevanz besitzen und bereits erfolgreich mit Hilfe von Gitlab umgesetzt wurden, also vor allem CI/CD, Security und Compliance.
CI/CD und SCM
Gitlab CI ist Bestandteil der Gitlab Community Edition und damit quelloffen. Das macht das Feature immens wertvoll, da es von und mit der Community lebt. Vor allem die Integration in Gitlab erhöht im Vergleich zum Einsatz mehrerer autarker Applikationen das Benutzererlebnis und reduziert Einarbeitungs- sowie Schulungsaufwände.
Weil es dank Gitlab für die einzelnen Schritte in der Pipeline Container-Images heranzieht, kann das Devops-Teams die Lieferzeiten beschleunigen. Der Einsatz sauber definierter und versionierter Container erlaubt Pipelines mit weitgehend voneinander entkoppelten Schritten. Dedizierte Container zum Bauen, Testen und Ausliefern von Anwendungen lassen sich schnell in andere Pipelines einbinden und über Teamgrenzen hinweg verwenden. Dabei deckt jeweils ein Container einen Schritt in der Pipeline ab.
Die Basis jeder CI/CD-Pipeline bildet ein Quellcode-Repository. Auf dem Weg in Richtung Gitops [3] und dem damit verbundenen “Everything as Code”-Paradigma kommt kein Devops-Team ohne Versionsverwaltung aus. Über die Git-Integration und daran gekoppelte Features wie Code Reviews, Kommentarfunktionen, bis hin zu Web-GUIs, die das Bearbeiten direkt im Browser erlaubt, deckt Gitlab die Anforderungen voll ab.
Agile Methoden
Mit seinen Modulen, zum Beispiel dem Issue Tracker und dem Issue Board (Abbildung 1), unterstützt Gitlab derzeit von Scrum über Kanban bis zu Safe alle gängigen Methoden agiler Software-Entwicklung. Im Gitlab-Blog findet sich ein Post [4] zum Thema Gitlab für agile Software-Entwicklung, er liefert einen guten Überblick darüber, wie Teams agile Prozesse auf Gitlab-Features abbilden können.
Da jedoch nicht alle Module in der Community Edition stecken, lohnt sich oft auch ein Blick auf die existierenden Schnittstellen zu Drittanbietersoftware. Von diesen verwenden wir unter anderem die Jira-Integration. Ergänzt ein Entwickler die Issue-ID von Jira in einem Merge Request, landet der automatisch als Kommentar in Jira.
Zugleich fügt Gitlab über die Jira-Schnittstelle einen Link zum Commit ein, was ein leichtes Navigieren zwischen beiden Systemen gewährleistet. Gibt der Entwickler im Beschreibungsfeld des Merge Request ein »Closes Jira-Issue-ID« ein, schließt Jira nach dem erfolgtem Merge im Gitlab die zugehörige Story – nicht aber, ohne einen Verweis auf den entsprechenden Commit zu hinterlassen.
Unterschiedliche Auszeichnungen lassen sich zudem bündeln. Diese so genannten Smart Commit Commands [5] helfen dabei, einem Commit gleichzeitig Anweisungen zu Kommentar, Status und Zeitbuchung mit auf den Weg zu geben.
Gitlab Runner
Ein grundlegender Baustein der Gitlab-CI-Architektur ist der Gitlab Runner [6]. Nach dem Pull-Prinzip kommuniziert er über ein API mit dem Gitlab-Server, führt deklarierte Jobs aus und sendet Ergebnisse zurück an den Gitlab-Server.
Runner laufen in den unterschiedlichsten Umgebungen, Docker und Kubernetes zählen jedoch zu den von uns präferierten. Sie fügen sich nahtlos in unser Zielbild einer Shared-Nothing-Architektur ein. Indem wir verschiedene Runner und Umgebungen kombinieren, bilden wir Anforderungen an Security und Compliance in einer Pipeline ab. Ein dediziertes Team stellt auf dieser Basis Continuous Delivery as a Service (CDaaS) für die Integration von Gitlab CI in AWS und Open Shift bereit. Über parametrisierte Deployment-Templates konfigurieren wir die Runner und rollen sie auf den entsprechenden Plattformen aus.
Indem wir Runner taggen und dank entsprechender Deklarationen im Pipeline-Job ordnen wir sie unterschiedlichen Umgebungen zu. Die Konfiguration selbst legen wir dabei im Toml-Format [7] an. Einen umfassenden Überblick der vorhandenen Parameter bietet die Runner-Dokumentation [8].
Runner lassen sich in den drei Ausprägungen Shared, Specific oder Group registrieren. Shared Runner eignen sich im Gegensatz zur Specific-Variante für Projekte mit identischen Anforderungen. Group Runner bieten allen Projekten einer Gruppe Zugang zu den definierten Runnern. Und alle Runner-Typen verstehen dabei die Option »Protected«. Ist diese gesetzt, führen sie nur in geschützten Branches oder Tags deklarierte Pipeline-Jobs aus.
Look Ma, no Scripting!
Die CI/CD-Pipeline konfigurieren wir deklarativ in einer Yaml-Datei. Wir definieren dabei nur das “Was”, Gitlab CI kümmert sich um das “Wie” [9].
»Jobs« bilden das Top-Level-Objekt einer Pipeline-Definition und müssen mindestens den »Script«-Parameter enthalten. An dieser Stelle ist Vorsicht geboten: Die Möglichkeiten, die eine »Script«-Anweisung bietet, verleitet schnell dazu, den deklarativen Ansatz zu vergessen und Pipeline-Logik zu implementieren. Aus dem “Was” wird dann ein “Wie”.
Um dem entgegenzuwirken, etabliert die Bahn gerade eine zentral gepflegte und für alle DB-Systel-Mitarbeiter verfügbare Container Library für CI/CD als Inner Source. Diese Bibliothek fungiert als Grundlage für sprachspezifische Builder-Images, die idealerweise auf leichtgewichtigen Basis-Images wie Alpine Linux [10] basieren. Alle benötigten Zertifikate, Umgebungsvariablen, Binaries und Buildtools zum Bauen der Anwendung stecken in den Images selbst. Auch Helper-Images, die etwa Routinen mitbringen, um eine neue Softwareversion zu berechnen, sind Bestandteil der Container Library.
Aufbauend auf dem von Docker geprägten Ansatz, je einen Prozess pro Container auszuführen, lassen sich diese Images einfach in der Jobdefinition verlinken. Der Gitlab Runner startet dann automatisch den jeweiligen Container und terminiert ihn, sobald er den Pipeline-Schritt abgearbeitet hat.
So integrieren wir auch Testautomation in die CI/CD-Kette. Neue Anwendungsversionen landen ohne langwierige manuelle Tests beim Nutzer. Analog zu den während der Buildphase erzeugten Images (Abbildung 2), landen auch diese Images in einer Container Registry. Gitlab bietet eine eigene an, bringt aber auch Schnittstellen zu externen Registries wie Artifactory [11] mit.
Eine Pipeline-Definition wächst schnell auf über einige Hundert Zeilen, was sie unübersichtlich und nicht mehr wartbar macht. Jede Gitlab-Installation beinhaltet ein Lint-Tool, um die Yaml-Konfiguration zu prüfen.
Abseits dieser Syntaxprüfung hilft es, thematisch gleiche Blöcke zu clustern und in separate Dateien auszulagern. Mit der seit Gitlab 11.3 im Kern vorhandenen »include«-Anweisung fügen Entwickler externe Konfigurationen ein. Technisch ist das über einen Deep-Merge realisiert. Auf diesem Weg lassen sich einfach Standardkonfigurationen einfügen, um diese notfalls mit projektspezifischen Anforderungen zu überschreiben. Die »include«-Anweisungen binden auch Remote-Dateien ein, was weitere Möglichkeiten eröffnet. Auf dieser Basis evaluiert ein Team gerade den Ansatz von kuratierten Pipelines als Service.
Während der Pipeline-Ausführung erzeugte Build-Artefakte lassen sich per Deklaration dauerhaft verfügbar machen und in anhängigen Jobs wiederverwenden. Zudem bietet das Web-GUI die recht komfortable Möglichkeit, durch die Job-Artefakte zu browsen oder diese herunterzuladen.
Pipeline-Jobs, die aufgrund ihrer Komplexität extrem lange Laufzeiten aufweisen, lassen sich über den Gitlab Scheduler, einer Art Cron-Daemon, in separate Pipelines auslagern. Diese laufen dann außerhalb der Entwicklungsphasen (zum Beispiel Nightly Builds).
Auto Devops
Der Grundgedanke hinter Gitlab Auto Devops besteht darin, die Komplexität, die mit der vollautomatisierten Auslieferung von Software einhergeht, ein Stück zu minimieren. Zu diesem Zweck akkumuliert Gitlab Auto Devops die nötigen Anforderungen und bildet sie über eine Pipeline ab.
Die Erkennung der Programmiersprachen funktioniert bereits für eine Vielzahl gängiger Sprachen und wird kontinuierlich erweitert. Automatische Softwarebuilds auf Basis von Docker oder Heroku Buildpacks sind bereits implementiert. Pipeline-Jobs zu Applikationstests und QA stehen ebenso bereit wie Routinen zum Paketieren und Monitoring. Deployment-Mechanismen über Helm-Charts [12] vervollständigen das Konzept.
Um sich mit Konventionen und Best Practises einer Gitlab-CI-Pipeline vertraut zu machen, lohnt ein Blick auf die Auto Devops Pipeline aus dem Gitlab-Repository [13]. Gitlab selbst setzt auf eine native Kubernetes-Integration und Googles Kubernetes Engine (GKE) als Zielplattform. Da es Cloud-agnostisch arbeitet, lassen sich sowohl Auto Devops als auch manuell erzeugte Pipelines mit jeder Cloudplattform und den darunterliegenden Orchestrierungs-Werkzeugen nutzen. Das verhindert einen Vendor Lock-in.
Zurzeit nutzt keines der Teams, die wir betreuen, Gitlab Auto Devops. Der Knackpunkt: Die Anforderungen des DB-Konzerns an Security und Compliance lassen sich über Auto Devops nicht vollumfänglich abbilden. Auch unterstützt das Konzept nicht von Haus aus alle von uns benötigten Applikations-Stacks.
Dennoch entwickelt sich Auto Devops zu einem sinnvollen Feature, das Mehrwert generiert. Es gibt Teams eine strukturierte Blauspause an die Hand, die es ihnen ermöglicht, schnell in einen Devops-zentrierten Arbeitsmodus zu gelangen.
Security & Compliance
Eine weitere Herausforderung, vor der auch unsere Devops-Teams stehen, sind die Anforderungen an Sicherheit und Compliance. Auf dem Weg zu einer Self-Service-Infrastruktur, die standardisierte Prozesse in einer CI/CD-Umgebung bereitstellt, ist “Compliant by Default” ein Eckpunkt für eine vollautomatisierte Pipeline.
In jüngster Zeit hat Gitlab seinen Fokus stark in Richtung Security ausgebaut. Viele der in dem Bereich benötigten Methoden und Funktionalitäten hat das Gitlab-Kernteam in seiner Roadmap gebündelt. Die Vision für Gitlabs Produkt enthält unter anderem eine so genannte Secure Stage, die das Unternehmen in einer weiteren Ausbaustufe um eine Defense Stage ergänzen will.
Das Static Application Secuity Testing (SAST) überprüft den Sourcecode auf vorhandene Schwachstellen wie Buffer Overflows oder unsichere Funktionsaufrufe. Das Dynamic Application Security Testing (DAST) testet gegen eine laufende Applikation, die so genannte Review App [14]. Diese Tests starten mit jedem Merge Request und erlauben so das frühe Auffinden von Sicherheitslücken während der Laufzeit. Das Interactive Application Security Testing (IAST) will beleuchten, wie die Applikation mit Security-Scans umgeht, die direkt aus der Applikation herauskommen. Für diesen Usecase liefert Gitlab einen so genannten Agent im Deployment mit aus, der sich in die Applikation integriert und die Scans umsetzt.Technisch geschieht dies, indem Gitlab ein entsprechendes Open-Source-Scan-Tool integriert. Die Entwickler wollen die Anzahl der unterstützten Sprachen permanent erweitern.
Secret Detection scannt zum Beispiel den Commit auf Zugangsdaten und Geheimnisse. Die Ergebnisse landen in existierenden Reports. Beim Dependency Scanning prüft Gitlab die eingesetzten Paketmanager auf Sicherheitslücken. Diese Technologie ist ebenfalls quelloffen und basiert auf Gemnasium [15].
Im Container Scanning kommen weitere Open-Source-Tools zum Einsatz. Das Core-OS-Projekt Clair [16] sammelt Informationen zu Schwachstellen von Apps und Docker-Containern in seiner Datenbank. Mit Hilfe des Clair-Scanners [17] ist die Pipeline in der Lage, Container-Images gegen den Clair-Server zu validieren, noch bevor sie die Images in die Registry pusht.
Nicht zuletzt soll ein Licence Management helfen, Compliance-Vorgaben einzuhalten, indem die Pipeline den Code auf Lizenzverstöße überprüft.
Die genannten Techniken lassen sich schon heute in Pipelines integrieren. Sie existieren bereits, wenn auch nur in der Enterprise-Ausgabe. Es besteht Hoffnung, dass Gitlab diese Komponenten künftig in die Community Edition integriert. Aktuell ist noch Handarbeit gefragt, um die Funktionen, die größtenteils auf Open-Source-Software basieren, selbst zu implementieren.
Ausblick
Lag der Fokus von Gitlab CI in den vergangenen Jahren primär auf Sourcecode Management und Continuous Integration, hat sich das Unternehmen für 2019 vorgenommen, die Themen Projektmanagement, CD und Release Automation, Application Security Testing und Value Stream Mapping voranzutreiben. Auf der Roadmap für 2019 stehen mehr als zwei Dutzend Features (Abbildung 3).

Abbildung 3: Für 2019 verschiebt das Gitlab-Projekt seinen Fokus unter anderem auf Continuous Deployment und Security Testing.
Zu den aus Devops-Sicht interessantesten Neuheiten zählen sicherlich Features wie Incident Management und Serverless, aber auch das erwähnte IAST sowie Runtime Application Self Protection (RASP). Einige dieser Features stehen heute bereits in der Alpha- oder Beta-Version zur Evaluation bereit.
Das Gitlab-Team plant jedenfalls, die Software nicht mehr nur im Devops-Bereich einzusetzen, sondern als Single Application auch für andere Arbeitsbereiche zu etablieren. Hierzu zählen die Security, QA, Product Owner, Tester und UX-Designer.
Sowohl für die Community- als auch die Enterprise-Ausgabe existieren dabei öffentlich zugängliche Issue-Tracker ([18], [19]) Deren Existenz motiviert Nutzer von Gitlab dazu, Feedback, Feature Requests oder Code beizutragen. Diese Form der Transparenz bildet nicht nur die Grundlage einer schnellen Feedback-Schleife, sondern macht Gitlab immer mehr zu einem Schweizer Messer für Devops-Teams (kki).
Infos
-
Gitlab: https://gitlab.com
-
Gitlab Community Edition: https://gitlab.com/gitlab-org/gitlab-ce/
-
Gitops: https://www.weave.works/blog/gitops-operations-by-pull-request
-
Agil entwickeln mit Gitlab: https://about.gitlab.com/2018/03/05/gitlab-for-agile-software-development/
-
Smart Commits: https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html
-
Gitlab Runner: https://docs.gitlab.com/ee/ci/runners/
-
Toml-Format: https://github.com/toml-lang/toml)
-
Gitlab-Runner-Dokumentation: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscache-section
-
Pipeline-Konfiguration: https://docs.gitlab.com/ee/ci/yaml/README.html
-
Alpine: https://alpinelinux.org/about/
-
Artifactory: https://jfrog.com/artifactory/
-
Helm Charts: https://github.com/helm/charts
-
Auto Devops Pipeline: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-Devops.gitlab-ci.yml
-
Review Apps: https://docs.gitlab.com/ee/ci/review_apps/index.html#doc-nav
-
Gemnasium: https://docs.gitlab.com/ee/user/project/import/gemnasium.html
-
Clair-Scanner: https://github.com/arminc/clair-scanner
-
Issue Tracker CE: https://gitlab.com/gitlab-org/gitlab-ce/issues
-
Issue Tracker EE: https://gitlab.com/gitlab-org/gitlab-ee/issues








