LuckyStep - stock.adobe.com
CI/CD-Pipelines erklärt: Alles, was man wissen muss
Continuous Deployment (CD) und Continuous Integration (CI) machen Sofwareentwicklung effizienter, doch es gibt viel zu beachten. Alles, was Sie über CI und CD wissen müssen.
Geschwindigkeit ist heute zweifellos der Schlüssel für die moderne Softwareentwicklung. Das monolithische Alles-oder-Nichts-Paradigma der traditionellen Softwareentwicklung – Stichwort Wasserfallprinzip – wurde deshalb inzwischen weitgehend ersetzt. Gefragt sind heute schnelle, iterative Techniken, die die Entwicklung und Veröffentlichung der Software unterstützen. Diese Techniken haben verschiedene Namen, die geläufigsten sind Continuous Integration (CI), Continuous Delivery (CD) und Continuous Deployment (CD).
Auch wenn jede Technik leichte Unterschiede aufweist: Die Gemeinsamkeit liegt auf der Betonung der kontinuierlichen Iteration, die das Wesen und die Leistungsfähigkeit der Softwareentwicklung verändert. Kontinuierliche Iteration bedeutet, dass Projekte oder Vorhaben erstellt und ständig weiterentwickelt und verbessert werden. Unternehmen können mit diesen Techniken Software schneller auf den Markt bringen, innovative neue Funktionen oder Architekturen testen und dabei gleichzeitig Risiken und Kosten minimieren – sowie Produkte im Laufe der Zeit effektiv verfeinern.
Eine kontinuierliche Iteration beruht auf gut geplanten und aktiven Pipelines. Diese müssen so konzipiert sein, dass sie mehrere Iterationen in verschiedenen Phasen des Entwicklungszyklus gleichzeitig unterstützen - und ganze Entwicklungsteams ständig beschäftigen. Das bedeutet: Während ein Build für die Bereitstellung freigegeben wird, wird der nächste Build bereits getestet, während der allerneueste Build im Zyklus gerade codiert wird.
Im Folgenden werfen wir einen genaueren Blick auf diese kontinuierlichen Ansätze. Sie erfahren, wie jeder einzelne Ansatz funktioniert und wir wägen die Ergebnisse ab und betrachten die Best Practices.
Was bedeuten CI und CD?
Die enge Beziehung zwischen Continuous Integration, Continuous Delivery und Continuous Deployment kann manchmal verwirrend sein. Dies gilt vor allem, wenn sie in dem als CI/CD bekannten zyklischen Prozess miteinander kombiniert werden. Es ist deshalb wichtig, die Unterschiede zwischen den einzelnen Ansätzen zu verstehen.
Continuous Integration (CI) konzentriert sich auf die frühen Phasen einer Pipeline für die Softwareentwicklung. In diesen Phasen wird der Code erstellt und ersten Tests unterzogen. Mehrere Entwickler arbeiten gleichzeitig an der gleichen Codebasis und übertragen diese häufig an das Code-Repository. Die Build-Frequenz kann täglich stattfinden oder – zu bestimmten Zeitpunkten im Lebenszyklus des Projekts – sogar mehrmals am Tag. Diese kleinen, häufigen Builds erlauben ein einfaches und risikoarmes Experimentieren. Zudem ermöglichen sie es, unerwünschte Ergebnisse einfach zurückzunehmen oder zu verwerfen.
CI verwendet eine Vielzahl von Tools und Automatisierungstechniken. Sie dienen dazu, Builds zu erstellen und sie durch erste Tests, wie Sniff- oder Unit-Tests, sowie umfassendere Integrationstests zu leiten. CI ist auch für sein schnelles und detailliertes Feedback bekannt. Die begrenzte Anzahl von Iterationen bedeutet, dass Fehler relativ einfach identifiziert, lokalisiert, gemeldet und korrigiert werden können.
Letztlich endet CI, wenn ein Build die ersten Tests erfolgreich abgeschlossen hat und für umfassendere Tests bereit ist. Zu den Vorbereitungen gehört auch das Verpacken des Builds in ein einsatzfähiges Image, zum Beispiel einen Container oder ein Image einer virtuellen Maschine (VM). Danach wird es dedizierten Testern zur Verfügung gestellt.
Continuous Delivery (CD) setzt dort an, wo CI aufhört. CD konzentriert sich auf die späteren Phasen einer Pipeline, in denen ein fertiges Build gründlich getestet, validiert und für die Bereitstellung vorbereitet wird. Continuous Delivery kann – muss aber nicht – ein erfolgreich getestetes und validiertes Build bereitstellen.
CD stützt sich ebenfalls stark auf Tools und Automatisierung, um einen Build durch erweiterte Tests zu führen, einschließlich Funktions-, Benutzerakzeptanz-, Konfigurations- und Belastungstests. Mit diesen Tests soll sichergestellt werden, dass der Build die Anforderungen erfüllt und für den Einsatz in einer Produktionsumgebung bereit ist. Auch hier sorgen kleine, inkrementelle Iterationen dafür, dass alle beim Testen aufgedeckten Probleme – schneller und kostengünstiger als bei der traditionellen Softwareentwicklung – identifiziert und behoben werden.
Continuous Deployment (ebenfalls CD) schließlich folgt denselben grundlegenden Schritten wie Continuous Delivery. Der Hauptunterschied zwischen Delivery (Auslieferung) und Deployment (Bereitstellung) besteht darin, dass bei der kontinuierlichen Bereitstellung – also Continuous Deployment – jeder validierte Build automatisch in die Produktion überführt wird. Im Vergleich dazu werden bei Continuous Delivery die validierten Builds in der Regel nur für die manuelle Bereitstellung oder eine andere menschliche Autorisierung zur Verfügung gestellt.
Continuous Deployment beschleunigt den iterativen Prozess der Softwareentwicklung weiter, weil die Verzögerung zwischen der Validierung des Builds und der Bereitstellung beseitigt wird. Dieses Paradigma kann jedoch dazu führen, dass unentdeckte Fehler oder Schwachstellen durch die Tests schlüpfen und in der Produktion landen. Für viele Unternehmen birgt die automatische Bereitstellung zu viele potenzielle Risiken für die Unternehmenssicherheit und die Einhaltung von Vorschriften. Diese Teams bevorzugen deshalb ein Continuous-Delivery-Paradigma, bei dem Menschen einen validierten Build überprüfen, bevor er freigegeben wird.
Den drei kontinuierlichen Paradigmen ist gemeinsam, dass sie sich stark auf Automatisierung und Tests stützen, um den Prozess voranzutreiben. Im Idealfall braucht ein Entwickler nur den Prozess anzustoßen, um einen neuen Build aus dem Code-Repository durch die Tests und weiter zur Auslieferung oder Bereitstellung zu bringen. Der Erfolg hängt dabei von der Qualität der Tests, der Integrität der Automatisierung und der sorgfältigen Arbeit von Testern und Softwareentwicklern ab.
Vor- und Nachteile einer CI/CD-Pipeline
In einer CI/CD-Pipeline ist alles so konzipiert, dass es gleichzeitig passiert: Einige Software-Iterationen werden kodiert, parallel werden andere Iterationen getestet und wieder andere gehen in die Bereitstellung. Dennoch bringt CI/CD neben den Vorteilen auch Nachteile mit sich.
Zu den Vorteilen einer CI/CD-Pipeline gehöre:
Effiziente Softwareentwicklung. Kleinere Iterationen (Schritte) ermöglichen ein einfacheres und effizienteres Testen. Der begrenzte Umfang des Codes in jeder neuen Iteration sowie der Umfang der Tests erleichtern das Auffinden und Beheben von Fehlern. Funktionen lassen sich besser auf ihre Nützlichkeit und Benutzerakzeptanz hin überprüfen, und weniger nützliche Funktionen können leicht angepasst oder sogar aufgegeben werden, bevor weitere Entwicklungszeit vergeudet wird.
Konkurrenzfähige Softwareprodukte. Herkömmliche Softwareentwicklung kann Monate oder Jahre dauern. Formalisierte Spezifikationen und Anforderungen sind nicht gut geeignet, um sich ändernde Benutzerbedürfnisse und -erwartungen zu erfüllen. Die CI/CD-Entwicklung lässt sich problemlos an neue und sich ändernde Anforderungen anpassen, so dass die Entwickler in der Lage sind, Änderungen in nachfolgenden Iterationen umzusetzen. Damit können via CI/CD entwickelte Softwareprodukte schneller und erfolgreicher auf den Markt kommen.
Freiheit zum Scheitern. Die schnellen Zyklen von CI/CD ermöglicht es Entwicklern, mit innovativen Kodierungsstilen und Algorithmen zu experimentieren – mit weitaus geringerem Risiko als bei traditionellen Paradigmen der Softwareentwicklung. Wenn ein Experiment nicht funktioniert, wird es wahrscheinlich nie in Produktion gehen und kann in der nächsten schnellen Iteration rückgängig gemacht werden. Das Potenzial für wettbewerbsfähige Innovationen ist ein starker Antrieb für Unternehmen, CI/CD einzusetzen.
Bessere Softwarewartung. Die Behebung von Fehlern kann bei der traditionellen Softwareentwicklung Wochen oder Monate dauern. Bei CI/CD macht es der konstante Fluss einer CI/CD-Pipeline einfacher, Fehler schneller und mit größerer Sicherheit zu beheben. Das Produkt wird im Laufe der Zeit stabiler und zuverlässiger.
Bessere Betriebsunterstützung. Regelmäßige Software-Releases halten das Betriebspersonal auf dem Laufenden, was die Anforderungen der Software und die Monitoring-Bedürfnisse betrifft. Die Administratoren sind besser in der Lage, Software-Updates zu verteilen und Rollbacks durchzuführen, ohne dass es zu Fehlern bei der Verteilung oder zu unnötigen Problemen kommt. Gleichermaßen können IT-Automatisierungstechnologien dazu beitragen, die Bereitstellung zu beschleunigen und gleichzeitig Einrichtungs- oder Konfigurationsfehler zu reduzieren.
Trotz dieser überzeugenden Vorteile müssen Unternehmensleiter und Entwicklungsteams einige der Nachteile von CI/CD-Pipelines berücksichtigen:
Einsatz für die Automatisierung. CI/CD beruht auf der Konsistenz eines etablierten Toolsets und einer starken Automatisierung, um jeden Build zu erstellen, zu testen und bereitzustellen. Dies erfordert eine erhebliche intellektuelle Investition, um die Automatisierung zu implementieren und zu verwalten und kann eine steile Lernkurve nach sich ziehen. Änderungen am Entwicklungsprozess oder am Toolset können die CI/CD-Pipeline tiefgreifend beeinflussen, weshalb CI/CD häufig in ausgereiften und aktiven Entwicklungsumgebungen eingesetzt wird.
Personaldisziplin und Planung. Ein CI/CD-Prozess bringt für das Unternehmen nicht den vollen Wert, wenn nicht ständig neue Builds erstellt, Release-Kandidaten getestet und ausgewählte Kandidaten in die Produktion überführt werden. Dies erfordert eine sorgfältige Planung und fachkundige Fähigkeiten beim Projektmanagement. Die Entwickler müssen sich an etablierte Entwicklungsrichtlinien halten, um Qualität, Stil und Architekturstandards zu gewährleisten. In der Zwischenzeit können Unternehmensleiter und Projektbeteiligte mit automatisierten Bereitstellungen in Continuous-Deployment-Paradigmen äußerst unzufrieden sein. Meetings für manuelle Go/No-Go-Entscheidungen zur Bereitstellung können mit Stress wegen unbekannter oder unvorhergesehener Konsequenzen verbunden sein. Dies kann zu unnötigen Verzögerungen führen – und das alles, während neue Builds durch die Pipeline laufen.
Kommunikation und Zusammenarbeit. Keine noch so effiziente Automatisierung und kein noch so leistungsfähiges Tool kann eine gute Kommunikation und Zusammenarbeit zwischen Entwicklern und Projektbeteiligten ersetzen. Diese Interaktionen erleichtern das schnelle und effiziente Experimentieren, das CI/CD so leistungsfähig macht. Automatisierung und Tools sind nur Mittel zum Zweck.
Merkmale einer guten CD/CD-Pipeline
Wie sieht also eine effektive CI/CD aus? Hier sind einige gemeinsame Merkmale eines guten CI/CD-Prozesses:
Geschwindigkeit. Eine CI/CD-Pipeline kann aus zahlreichen Schritten und Teilen bestehen. Ein Build sollte jedoch in der Lage sein, die Pipeline (Integration, Testen, Auslieferung und sogar Bereitstellung) in kurzer Zeit zu durchlaufen, um eine Integration abzuschließen, und ein paar Stunden, um Testzyklen zu beenden. Wenn es Tage dauert, bis ein Build die Pipeline durchläuft, wird wahrscheinlich viel wertvolle Zeit verschwendet, und der Prozess sollte verfeinert werden.
Konsistenz. Die Prozesse und Komponenten, die an einem Ort oder in einem Zyklus verwendet werden, sind an allen Orten und in allen Zyklen genau dieselben. Wenn beispielsweise ein Build zu einem Docker-Container führt, ist dieser Container das Objekt, das getestet und durch die Pipeline bis zur Auslieferung oder Bereitstellung bewegt wird. Entwickler können Skripte schreiben und Automatisierungsprozesse erstellen und sich darauf verlassen, dass diese Bemühungen erfolgreich sind und jedes Mal die gewünschten Ergebnisse liefern. Prozesse, die Variationen oder manuelle Schritte einführen, verlangsamen die Pipeline und fördern Fehler und Ineffizienzen.
Strenge Versionskontrolle. Gut dokumentierte Repositories oder Komponenten und Builds ermöglichen eine schnelle Wiederherstellung früherer Builds. Das ist wichtig, wenn neue Builds oder Implementierungen schief gehen. Eine gute Versionskontrolle ermöglicht ein schnelles, genaues und sicheres Rollback – vielleicht auf die vorherige Arbeitsversion – wann immer dies erforderlich ist.
Automatisierung. Umfassende Automatisierung verschiebt neuen Code durch Integration, Testen und Auslieferung oder Bereitstellung mit wenig oder gar keiner manuellen Interaktion. Im Idealfall macht ein Mensch nicht viel mehr, als den Code zu entwickeln und zu übergeben. Dann muss man nur noch auf einen genehmigten Pull-Request und die Freigabe warten – falls erforderlich – , bevor eine Bereitstellung erfolgt. Eine Pipeline, die von manuellen Schritten und Prozessen abhängt, ist langsam und anfällig für Fehler.
Integrierte Feedback-Schleifen. Eine CI/CD-Pipeline ist eine Schleife, die in unzähligen iterativen Schritten zu einem fertigen Projekt führt – und jede Phase bietet auch eine Schleife zurück zum Anfang. Ein Problem mit dem Quellcode generiert keinen Build. Ein Problem mit dem Build führt nicht zum Testen. Ein Problem beim Testen oder nach der Bereitstellung erfordert Quellcode-Korrekturen. Je früher ein Problem erkannt wird, desto schneller, einfacher und kostengünstiger kann es behoben werden, so dass die gesamte Pipeline in Bewegung bleibt.
Durchgängige Sicherheit. Versäumnisse und Fehler bei der Programmierung und beim Testen können zu Schwachstellen führen und die Software für böswillige Aktivitäten anfällig machen. Daher ist es wichtig, bewährte Sicherheitsverfahren in die gesamte CI/CD-Pipeline einzubauen. Programme zur Schwachstellenprüfung können dabei unterstützen, potenzielle Sicherheitslücken im Code, der die Pipeline durchläuft, zu erkennen. Während der Testphase sollten zusätzliche Sicherheitsbewertungen stattfinden.
Was sind die Phasen einer CI/CD-Pipeline?
Die CI/CD-Pipeline kombiniert kontinuierliche Integration, Auslieferung und Bereitstellung in vier Hauptphasen: Source, Build, Test und Deploy. Typischerweise kommen in jeder Phase sehr detaillierte und spezifische Prozesse, Standards, Tools und Automatisierungsansätze zum Einsatz. So wie physische Produkte, die in einer Fabrik hergestellt werden, von maßgeschneiderten Fertigungsmaschinen profitieren können, werden Softwarepipelines häufig auf die spezifischen Anforderungen des Projekts und des Unternehmens zugeschnitten.
Source. Die erste Phase in einer CI/CD-Pipeline ist die Erstellung des Quellcodes. In dieser Phase setzen Entwickler die Anforderungen in funktionale Algorithmen, Verhaltensweisen und Features um. Welche Tools dabei zum Einsatz kommen, hängt davon ab, ob das Entwicklungsteam in Java, .NET, C#, PHP oder eine der zahlreichen anderen Entwicklersprachen arbeitet. Häufig werden integrierte Entwicklungsumgebungen (Integrated Development Environment, IDE) genutzt, weil sie eine bestimmte Sprache unterstützen und darüber hinaus verschiedene Funktionen für die Codeprüfung bieten. Zu diesen unterstützenden Funktionen gehören etwa die Erkennung grundlegender Fehler, das Scannen von Sicherheitslücken und die Einhaltung etablierter Codierungsstandards. Andere Quellcode- und Pipeline-Tools, darunter Code-Repositories und Systeme zur Versionskontrolle wie Git, bilden in der Regel die Grundlage für die Entwicklungs- und Testphasen.
Für die Erstellung des Quellcodes gibt es keine einheitliche Pipeline. Abhängig von den verschiedenen Projekten, die sich in der Entwicklung befinden, kann ein Unternehmen mehrere Teile der CI/CD-Pipeline für den Quellcode verwenden. Beispielsweise kann eine serverseitige Plattform mit C++ verwendet werden, Website-Anwendungen mit Java und mobile Anwendungen mit Go. Ebenso können sich die Codierungsfunktionen zwischen IDEs und Projekten aufgrund unterschiedlicher Standards oder Schwachstellen zwischen den Projekten unterscheiden, zum Beispiel zwischen Produktionssystemen im Unternehmen und einer Anwendung für den privaten Gebrauch.
Build. Der Build-Prozess bezieht den Quellcode aus einem Repository, stellt Verknüpfungen zu relevanten Bibliotheken, Modulen und Abhängigkeiten her und kompiliert (baut) all diese Komponenten zu einer ausführbaren Datei (.exe). Die in dieser Phase verwendeten Tools erstellen auch Protokolle des Prozesses, weisen auf Fehler hin, die untersucht und korrigiert werden müssen, und benachrichtigen die Entwickler, dass der Build abgeschlossen ist.
Wie bei der Erstellung des Quellcodes hängen auch die Build-Tools normalerweise von der gewählten Programmiersprache ab. Viele IDEs verfügen über solche Build-Funktionen, was bedeutet, dass sie sowohl die Quellcodeerstellung als auch die Build-Phase innerhalb einer CI/CD-Pipeline effektiv unterstützen.
In einer Build-Phase können zusätzliche Tools wie Skripte eingesetzt werden. Diese übersetzen die ausführbare Datei in eine verpackte oder bereitstellbare Ausführungsumgebung. Das kann eine VM (komplett mit Betriebssystem und zugehörigen Komponenten) oder ein Container sein, wie zum Beispiel ein Docker-Container mit Bibliotheken und Abhängigkeiten.
Testen. Nachdem der Quellcode bereits einige statische Tests durchlaufen hat, tritt der fertige Build nun in die nächste CI/CD-Phase ein. In dieser werden umfassende dynamische Tests durchgeführt. Die Tests beginnen in der Regel mit grundlegenden Funktions- oder Unit-Checks, um zu überprüfen, ob neue Funktionen wie beabsichtigt funktionieren. Außerdem werden Regressionstests durchgeführt, die sicherstellen sollen, dass neue Änderungen oder Ergänzungen zuvor funktionierende Funktionen nicht versehentlich zerstört haben. Der Build wird zudem einer Reihe von Tests zur Integration, Benutzerakzeptanz und Leistung unterzogen. Treten während der Tests Fehler auf, werden die Ergebnisse an die Entwickler zur Analyse und Behebung in nachfolgenden Builds zurückgespielt.
In der CI/CD-Testphase ist Automatisierung von entscheidender Bedeutung. In dieser Phase wird ein Build einer enormen Anzahl von Tests und Testfällen unterzogen, um seinen Betrieb zu validieren. Menschliche Tests sind in der Regel zu langsam und unterliegen Fehlern und Versäumnissen, um zuverlässige oder objektive Testergebnisse zu gewährleisten. Testexperten erstellen umfassende Testfälle und -kriterien, sind jedoch auf Test-Tools angewiesen, um die Tests und die Validierung in einer ausgelasteten Pipeline zu implementieren.
Deployment (Bereitstellen). Hat der Build die Testphase überstanden kann er als Kandidat für die Bereitstellung in einer Produktionsumgebung betrachtet werden. In einer Continuous-Delivery-Pipeline wird er an die Beteiligten gesendet, genehmigt und dann bereitgestellt. In einer Continuous-Deployment-Pipeline wird der Build automatisch bereitgestellt, sobald er die Testläufe bestanden hat.
Für den Bereitstellungsschritt muss in der Regel eine Deployment-Umgebung erstellt werden. Dies kann zum Beispiel die Bereitstellung von Ressourcen und Diensten im Rechenzentrum sein, und das Verschieben des Builds zu seinem Bereitstellungsziel wie einem Server. Diese Schritte werden in der Regel in Automatisierungs-Tools mit Skripten oder durch Workflows automatisiert. Deployments sind in der Regel auch mit Fehlerberichts- und Ticketing-Tools verbunden, um unerwartete Fehler nach der Bereitstellung des Builds zu finden und die Entwickler zu alarmieren. Benutzer können auch Bug-Tickets einreichen, um auf tatsächliche oder vermeintliche Fehler in der Version hinzuweisen.
Selbst die optimistischsten Deployment-Kandidaten werden selten ohne Vorbehalt in die Produktion übernommen. In der Praxis umfasst die Bereitstellung häufig zusätzliche Vorsichtsmaßnahmen und Live-Testphasen, einschließlich Betatests, A/B-Tests, Blue/Green-Tests und andere Crossover-Tests. Damit sollen unvorhergesehene Softwareprobleme eingedämmt oder rückgängig gemacht und negative Auswirkungen auf das Unternehmen minimiert werden.
Was ist ein Beispiel für eine CI/CD-Pipeline?
Es gibt nicht den EINEN richtigen Weg, eine CI/CD-Pipeline aufzubauen. Jede Pipeline kann unterschiedliche Tools und Variationen verwenden oder alternative Wege enthalten, um Projekte mit unterschiedlichem Umfang und Anspruch zu unterstützen. Unabhängig vom Ansatz sollte eine ideale CI/CD-Pipeline drei grundlegende Ziele erfüllen:
- Die Qualität der Software verbessern.
- Schnellere und agilere Softwareentwicklung ermöglichen.
- Das Vertrauen in die Softwarebereitstellung für die Produktion erhöhen.
Lassen Sie uns zur besseren Veranschaulichung eine typische CI/CD-Pipeline untersuchen, die Aktivitäten in jeder Phase betrachten und mehrere mögliche Tools zur Problembewältigung vorstellen.
Sourcecode
Entwickler schreiben ihren Code mit Editoren oder IDEs. Ein Entwicklungsteam kann mehrere Editoren oder IDEs verwenden, um mehrere Sprachen für verschiedene Projekte zu unterstützen.
Tools: Beispiele für Software-IDEs sind Atom, Cloud9 IDE, Microsoft Visual C++ oder Visual Studio, PyCharm und Xcode.
Der Quellcode wird in der Regel in einem gemeinsamen Repository, oder Repo, gespeichert. Auf dieses können mehrere Entwickler gleichzeitig zugreifen und sie können an der Codebasis arbeiten. In Repos werden in der Regel auch andere Teile des Softwareentwicklungsprozesses gespeichert. Dazu gehören beispielsweise Artefakte (der Kompilierung und Verknüpfung), Bibliotheken, ausführbare Dateien, Module, Testskripte und -suiten. Repos bieten ein umfassendes Versionskontrollsystem, das sicherstellt, dass die Entwickler mit der neuesten Codebasis arbeiten und die neuesten Komponenten in den Build-Prozess integrieren.
Tools: GitHub, basierend auf Git, ist ein beliebtes Repository; andere Beispiele für Repositories sind GitLab, Cloudsmith Package, Docker Hub für Containerprojekte, JFrog Artifactory, NuGet und SVN.
Sobald ein Entwickler Änderungen an der Codebasis vornimmt, werden diese Änderungen im Versionskontrollsystem im Repository gespeichert, was automatisch einen neuen Build auslöst.
Build
Der Build-Prozess umfasst in der Regel mehrere Schritte: Abrufen der Quellcode-Komponenten aus dem Repo, Kompilieren des Codes und Verknüpfen mit Bibliotheken und anderen Modulen. Das Ergebnis ist eine einfache ausführbare Datei oder eine komplexere Baugruppe wie ein bereitstellbarer Container oder eine VM. Alle am Build-Prozess beteiligten Artefakte werden in der Regel im Repository aufbewahrt. Treten beim Build Probleme oder Fehler auf, wird der Prozess angehalten und die Probleme werden zur Behebung an die Entwickler zurückgemeldet. Typische Probleme sind funktionale Fehler, wie zum Beispiel ein mathematischer Fehler beim Teilen durch Null, oder fehlende Komponenten, zum Beispiel eine erforderliche Bibliothek oder ein Modul, welche nicht im Build-Manifest enthalten sind.
Tools: Viele IDEs enthalten Build Tools, die von Haus aus auf die ausgewählte Programmiersprache zugeschnitten sind. Alternativ dazu gibt es eigenständige Build Tools wie Ant, Gradle, Make, Maven, Meister, Phing und Rake. Jenkins ist eine beliebte CI-Engine, aber es gibt auch Alternativen zu Jenkins wie Atlassian Bamboo, AWS CodePipeline, CircleCI, GitHub Actions und TeamCity.
Die Build-Phase kann auch einige grundlegende Tests auf Schwachstellen beinhalten, wie beipielsweise Software Composition Analysis (SCA) und Static Application Security Testing (SAST).
Tools: Beispiele für SAST-Tools sind Arctic Wolf Vulnerability Assessment, Fortify Static Code Analyzer und Netsparker. Zu den Anbietern von SCA-Tools gehören Checkmarx, Kiuwan, Snyk, Synopsys und Veracode.
Wenn der Build erfolgreich abgeschlossen wurde und er die ersten Testscans bestanden hat, geht er in die CI/CD-Testphase über.
Test
Einige Tests sind zwar Bestandteil des Build-Prozesses, doch die meisten finden nach dem erfolgreichen Abschluss des Builds statt. Diese komplexe Phase umfasst zahlreiche Schritte und Ziele, darunter:
- Unit-Tests validieren neue Merkmale und Funktionen, die dem Build hinzugefügt wurden.
- Dynamische Tests für die Anwendungssicherheit (Dynamic Application Security Testing, DAST) überprüfen den Build auf Sicherheitsmängel, zum Beispiel auf schwache Passwörter oder fehlende Anmeldedaten.
- Interaktive Tests für die Anwendungssicherheit (Interactive Application Security Testing, IAST) analysieren den Datenverkehr und den Ausführungsfluss, um Sicherheitsprobleme zu erkennen, auch in Drittanbieter- oder Open-Source-Komponenten.
- Regressionstests stellen sicher, dass Änderungen oder Ergänzungen frühere Funktionen nicht beeinträchtigen.
- Integrationstests stellen sicher, dass der Build mit anderen Anwendungen oder Diensten funktioniert.
- Tests für die Benutzerakzeptanz prüfen, ob die User die neuen Merkmale und Funktionen wie vorgesehen verwenden können.
- Leistungstests stellen sicher, dass der Build auch unter Last wie gewünscht funktioniert.
Entwickler und Spezialisten für Softwaretests erstellen Testbedingungen, die Eingaben für den Build liefern, und vergleichen die tatsächliche Reaktion oder Ausgabe mit der erwarteten Reaktion. Stimmen sie überein, gilt der Test als erfolgreich und der Build wird zum nächsten Test weitergeleitet. Stimmen sie nicht überein, wird die Abweichung registriert, und die Fehlerinformationen werden zur Untersuchung und Behebung an das Entwicklungsteam zurückgeschickt.
Tools: Es gibt Hunderte von Tools, die für diese Tests eingesetzt werden können. Jedes Werkzeug unterstützt ein gewisses Maß an Automatisierung, und einige können mehrere Arten von Tests durchführen. Zu den beliebtesten Test-Tools gehören Appian, Katalon, Kobiton, Kualitee, Micro Focus, Qaprosoft, Sauce Labs, Selenium, Telerik Test Studio und TestArchitect.
Nicht alle Builds, die die Testphase erfolgreich abschließen, wechseln in die Bereitstellungsphase. Einige Builds stellen lediglich Zwischenschritte dar, die validiert werden müssen, aber noch nicht bereit für das Deployment sind. So können Entwickler beispielsweise eine unvollständige Funktionsuntermenge testen, die verbleibende Funktionsuntermenge aber in einem späteren Build ausbauen und dann vollständig bereitstellen.
Deployment (Bereitstellung)
Ein Build, der die Tests erfolgreich durchläuft, kann zunächst auf einem Testserver bereitgestellt werden. Dies wird manchmal als Testbereitstellung oder Vorproduktionsbereitstellung (Pre-Production Deployment) bezeichnet. Dabei kopiert ein Skript ein Build-Artefakt aus dem Repo auf einen gewünschten Testserver und richtet dann Abhängigkeiten und Pfade ein.
Auf dem Testserver kann der Build so konfiguriert werden, dass er eine Produktionsumgebung simuliert. So kann beispielsweise der Zugriff auf Testdatenbanken und andere Anwendungen für Funktions- und Leistungsbewertungen unter realen Bedingungen aktiviert werden. Vieles davon beruht auf Automatisierung, aber es können auch menschliche Tests erforderlich sein, um Nuancen des Builds herauszufinden. Dies wird manchmal als Alpha- oder Entwicklungsversion bezeichnet und bezieht nur eine kleine Gruppe von gut informierten Testern und Benutzern ein.
Das Pre-Production Deployment ist in der Regel der Endpunkt einer Continuous Delivery Pipeline. Sobald der Build vollständig validiert ist und die Beteiligten Vertrauen in die Stabilität und Integrität des Builds haben, kann er in einer tatsächlichen Produktionsumgebung eingesetzt werden. In einer Continuous-Deployment-Pipeline wird der Build, sobald er die Pre-Deployment-Tests bestanden hat, automatisch in der Produktion bereitgestellt.
Zur Verbesserung der Sicherheit und zum Schutz vor unvorhergesehenen Folgen kann ein neuer Build parallel zum aktuellen Build in einer A/B-Konfiguration bereitgestellt werden, auch Betatest genannt. Diese Tests werden schrittweise auf größere Benutzergruppen ausgeweitet, bis alle Benutzer mit dem neuen Build arbeiten. Zu diesem Zeitpunkt wird der vorherige Build außer Betrieb genommen und seine Rechenressourcen werden für andere Anwendungen freigegeben.
Tools: Es gibt viele spezielle Bereitstellungs-Tools, darunter Ansible Tower, Chef, Codeship, ElectricFlow, Jenkins, Octopus Deploy, Spinnaker und TeamCity. Bei der Bereitstellung können auch Tools zur Überwachung der Anwendungsleistung (Application Performance Monitoring, APM) und andere Arten von Instrumenten zum Einsatz kommen, um den Zustand einer Anwendung zu überprüfen und darüber zu berichten.
Wie implementiert man eine CI/CD-Pipeline?
Für die Einrichtung einer CI/CD-Pipeline gibt es keine einheitliche Methode. Die genauen Schritte hängen von den einzelnen Tools und dem zu implementierenden Prozess ab – und das ist durchaus gewollt. Schließlich soll eine hoch agile Pipeline entstehen, die allen Anforderungen des Unternehmens und seiner Projekte entspricht.
Dennoch gibt es in jeder Phase des Pipeline-Aufbaus allgemeine Schritte und Entscheidungen, die für jeden CI/CD-Prozess gelten:
- Wählen Sie ein Versionskontrollsystem aus, um Code-Repositories zu verwalten. Bestimmen Sie, ob Sie eine gehostete Version oder einen Hosting-Anbieter benötigen. Große Cloud-Provider bieten hier ebenfalls Optionen an, wie zum Beispiel Azure DevOps.
- Erstellen Sie Repositories zum Ablegen von Quellcode und Pipelines.
- Legen Sie fest, welcher Build- oder CI-Server verwendet werden soll. Dabei kann es sich um einen selbst gehosteten Server wie Jenkins oder um den Server eines Drittanbieters wie GitHub Actions, CircleCI oder Azure Pipelines handeln.
- Implementieren Sie eine Aufgabe in der Pipeline, die den Quellcode der Anwendung zu einem Build kompiliert. In einigen Konfigurationen wird dadurch ein Docker-Image erzeugt.
- Führen Sie grundlegende Tests für den Code durch (statische Analyse, Stilprüfungen), um seine Qualität und die Übereinstimmung mit den Unternehmensrichtlinien sicherzustellen.
- Der Build sollte nun ein Artefakt oder Container-Image erzeugen, das in einem Store oder einer Registry veröffentlicht wird.
- Initiieren Sie weitere Tests für den Build, wie zuvor beschrieben (Funktionalität, Sicherheit, Benutzerakzeptanz und so weiter). Wenn die vorher festgelegten Schwellenwerte nicht erreicht werden, wird die Phase abgebrochen. Veröffentlichen Sie die Ergebnisse der Tests, damit sie leicht verfügbar sind.
- Sobald der Software-Build die Tests bestanden hat, ist er bereit für die endgültigen Maßnahmen zur Produktionsbereitstellung. Dies kann mehrere gestaffelte Umgebungen umfassen, zum Beispiel Blue/Green und Canary Deployments.
Beachten Sie, dass CI/CD in der Cloud im Grunde genommen gleich funktioniert wie in einer lokalen Umgebung, sich aber stark auf die Tools und Dienste der Cloud-Anbieter-Plattform stützt. Dies kann spezifische Schritte erfordern.
Auch die CI/CD-Implementierung ist mit einigen spezifischen Herausforderungen verbunden. Hier sind zwei der wichtigsten, auf die Sie achten sollten:
Begrenzte Tests. Ein häufiges Problem für CI/CD-Pipelines ist das Zuweisen und Koordinieren von Ressourcen und der mentale Aufwand für das Konfigurieren von Testumgebungen und das Erstellen von Testfällen. Kontinuierliche Entwicklung umfasst mehrere Code-Commits und parallele Testanforderungen. Diese führen häufig zu Konfigurationskonflikten und begrenzten oder vergessenen Testfällen. Die Folge ist oft, dass Fehler durch die Testphase rutschen und die Effizienz der Pipeline beeinträchtigt wird. Es gibt keinen Ersatz für qualifizierte und sachkundige Softwaretester und gut dokumentierte Anforderungen und Ziele.
Behebung von Fehlern. Pipelines sind so konzipiert, dass sie Feedback-Schleifen zu den Entwicklern bilden, die Fehler in einem neuen Build beheben können. Es ist einfach, einen Fehler zu finden, aber es kann schwierig sein, den Entwickler zu finden, der für die Fehlerbehebung des betreffenden Codeabschnitts verantwortlich ist. Dies macht es schwieriger, Entwickler für ihre Arbeit verantwortlich zu machen, und kann den Bedarf an weiteren Schulungen verschleiern. Protokollierung, Teamkommunikation und umfangreiche Dokumentation können dabei unterstützen, den Ort des Fehlers zu bestimmen und die Entwickler zu identifizieren, die an der Lösung des Problems beteiligt sein müssen.
Bewährte Verfahren für CI/CD-Pipelines
Ein Unternehmen und seine Entwicklungsteams können mehrere Methoden anwenden, um das Optimum aus einer CI/CD-Pipeline herauszuholen. Die im Folgenden vorgestellten bewährten CI/CD-Verfahren können Unternehmen unterstützen, einen noch größeren Nutzen daraus zu ziehen.
Fangen Sie klein an. CI/CD bringt Schnelligkeit und Agilität mit sich. Geben Sie dem Prozess also Zeit, sich zu entwickeln, und ermöglichen Sie es Entwicklern, verschiedene Tools und Schritte auszuprobieren. Ein Unternehmen kann mit einer CI-Pipeline beginnen und später CD hinzufügen. Kleine Füllprojekte sind ideal, um neue Tools und Techniken auszuprobieren.
Definieren Sie den Erfolg. Werden Sie sich über die angestrebten Vorteile klar, zum Beispiel die schnellere Codeerstellung oder die geringeren Fehler-/Nachbearbeitungsraten. Implementieren Sie Metriken zur Messung dieser Kriterien. Vergleichen Sie die Metriken mit der Pre-Pipeline Performance und verfolgen Sie diese Metriken, während sich die Pipeline weiterentwickelt. Auf diese Weise ist es einfacher, den Wert der Pipeline zu erkennen, Probleme im Laufe der Zeit zu erkennen und in Möglichkeiten zum Aufbau und zur Verbesserung der CI/CD-Pipeline zu investieren.
Dokumentieren Sie Prozesse. Die Dokumentation wird oft übersehen und unterschätzt, sie ist aber ein wesentlicher Bestandteil der Entwicklungspipeline. Die Dokumentation legt den Prozess und die Werkzeuge für alle Entwickler und Geschäftsanwender fest und erklärt, wie alles zusammenhängt und konfiguriert ist. Außerdem kann sie bei der Fehlerbehebung helfen. Die Dokumentation trägt auch zur Einhaltung von Vorschriften und zur Sicherheit eines Unternehmens bei, da sie es den Verantwortlichen ermöglicht, Aktivitäten zu überprüfen.
Denken Sie an den Betrieb. Agile Entwicklungsparadigmen wie DevOps und Continuous Deployment umfassen sowohl die Betriebs- als auch die Entwicklungsrolle. Die Entwickler müssen sowohl die Bereitstellung als auch den Betrieb verstehen und mehr Verantwortung für die Zuverlässigkeit und Leistung der Software übernehmen. Geschäfts- und Projektleiter müssen diese Änderung der Einstellung fördern und verstärken.
Legen Sie den Fokus auf Feedback. Feedback innerhalb der CI/CD-Pipeline ist am effektivsten, wenn jeder Schritt – und jeder Teilnehmer – aktiv daran arbeitet, Probleme zu erkennen und zu beheben, um Zeit zu sparen und effizient zu arbeiten. Dies beginnt mit dem Aufspüren von Fehlern im Quellcode und setzt sich während der gesamten Testphase und der Bereitstellung fort. Finden und beheben Sie zum Beispiel einen Syntaxfehler im Quellcode in der Build-Phase, anstatt Zeit und Mühe in der Testphase zu verschwenden. Das Kategorisieren und Analysieren von Fehlern kann Unternehmen auch dabei unterstützen, die Entwicklungsfähigkeiten und -prozesse zu verbessern.
Sorgen Sie für Sicherheit. Sicherheitsscanner auf Codeebene (SAST- und SCA-Tools) sind praktisch für eine frühzeitige Schwachstellen- und Fehlerdiagnose, können aber eine große Anzahl falsch positiver Ergebnisse liefern. Sicherheitsscans auf Testebene (DAST- und IAST-Tools) setzen voraus, dass die Software erstellt und ausgeführt wird, was bedeutet, dass Fehler erst später in der Pipeline entdeckt werden. In dieser Phase sind Fehlerbehebungen zeit- und kostenaufwendiger. Wählen Sie die besten Sicherheitsscan-Tools für die anstehenden Aufgaben aus und verwenden Sie diese Tools, um das System zur Fehlerverfolgung automatisch zu aktualisieren und automatisch Tickets für eine schnelle Prüfung und Behebung zu erstellen.
Denken Sie an die Sicherheit der Pipeline selbst: Eine unsachgemäße Autorisierung und Authentifizierung kann Tools und Repositories für böswillige Aktionen anfällig machen. Sichern Sie Tools und Repositories, verwenden Sie Protokolle, um den Benutzerzugriff auf sie zu verfolgen, und markieren Sie ungewöhnliche Aktivitäten, wie zum Beispiel Downloads auf IP-Adressen außerhalb des Unternehmens-LAN.
Setzen Sie auf kontinuierliche Tests. Führen Sie während der Quellcode- und Build-Phase SCA-, SAST- und andere grundlegende Code-Scans durch. Wenn der Build abgeschlossen ist, wenden Sie eine Reihe von festgelegten Testbedingungen mit Unterstützung von Test-Tools an. Beginnen Sie mit einer einfachen funktionalen Validierung und erweitern Sie die Tests systematisch auf komplexere und umfassendere Integration, tiefgreifende Sicherheit (wie DAST) und Leistung. Die Mitarbeiter sollten Tests und Testfälle sorgfältig konstruieren, um die Features und die Funktionalität jedes neuen Builds zu validieren, wenn sich die Builds, das Projekt und sogar die Anforderungen des Projekts weiterentwickeln. Häufig hinzugefügte neue Funktionen erfordern häufige Tests und Testfälle.
Fördern Sie die Kommunikation. Integration und Bereitstellung arbeiten zusammen, werden aber oft getrennt voneinander implementiert. Sie werden oft auch von verschiedenen Teams bearbeitet, zum Beispiel Programmierern und Testern. Eine reibungslos funktionierende CI/CD-Pipeline erfordert eine rechtzeitige und klare Kommunikation und Zusammenarbeit zwischen den verschiedenen Teams innerhalb der Pipeline. Andernfalls kann es leicht zu unnötigen Verzögerungen kommen.
Vermeiden Sie Verschwendung. Die Erstellung und Pflege einer CI/CD-Pipeline verursacht verschiedene Kosten für Tools, Infrastruktur und Ressourcen. Eine ineffiziente Nutzung eines dieser Faktoren – nicht ausreichend genutzte oder ungenutzte Tools, übermäßig zugewiesene IT-Infrastruktur für Tests und Bereitstellungen, schlechte Koordination, unzureichende Bewertung von Prozessen oder Tools – kann die Entwicklung verlangsamen und die Produktivität der Entwickler beeinträchtigen. Bedenken Sie: CI/CD-Pipelines sind dynamische Gebilde, die häufige Verfeinerungen und regelmäßige Entwicklerschulungen erfordern, um effizient und zuverlässig zu arbeiten.
Dies bedeutet auch, weniger offensichtliche Bereiche der Ineffizienz zu vermeiden. Erstellen Sie nicht zehn verschiedene Builds am selben Tag, wenn es keine praktische Möglichkeit gibt, diese 10 Builds am selben Tag zu testen und bereitzustellen. Teams und Projektaufwand müssen die effektivste Nutzung der Pipeline widerspiegeln.
Verbessern Sie das Ökosystem. CI/CD und andere agile Pipelines sind Ökosysteme. Sie bestehen aus Tools, die mit Prozessen und Automatisierung verbunden sind, mit unzähligen alternativen Pfaden und Schritten für verschiedene Produkte. Teams sollten stets neue Tools evaluieren und die Prozesse verfeinern, um die gesamte Pipeline so reibungslos und effizient wie möglich zu gestalten.