Die moderne Softwareentwicklung ist schnell, aber manuelle Test-, Entwicklungs- und Bereitstellungsprozesse sind es nicht. Continuous Integration/Continuous Deployment (CI/CD) automatisiert diese kritischen Arbeitsabläufe und ermöglicht es den Teams, Funktionen schnell bereitzustellen und dabei die Qualität zu erhalten und Produktionsprobleme zu minimieren. Während sich CI auf das automatische Testen und Erstellen von Codeänderungen konzentriert, kann CD entweder Continuous Delivery (Vorbereitung von Code für die Veröffentlichung) oder Continuous Deployment (automatische Freigabe für die Produktion) bedeuten. Das Verständnis dieser Unterscheidung ist entscheidend für die Implementierung der richtigen Strategie für Ihr Team.
Dieser Artikel führt Sie durch die Grundlagen von CI/CD, stellt bewährte Best Practices vor und untersucht fortgeschrittene Techniken, die Ihren Entwicklungs-Workflow verändern können, einschließlich der Frage, wie moderne Plattformen wie Upsun Ihre CI/CD-Pipeline mit produktionsähnlichen Vorschauumgebungen verbessern können.
Das CI in CI/CD steht für Continuous Integration, d. h. die automatische Durchführung von Tests und die Erstellung von Code auf einem Remote-Server, sobald Änderungen vorgenommen werden. Dieser Prozess stellt sicher, dass die letzte Übertragung in jedem Zweig alle Prüfungen besteht und sicher freigegeben oder in den Hauptzweig zusammengeführt werden kann.
Zu den gängigen Plattformen für die Ausführung von CI gehören Jenkins, GitLab CI und GitHub Actions. Die Beispiele in diesem Artikel verwenden GitLab CI.
Der grundlegende CI-Prozess umfasst die Überprüfung des Codes, die Durchführung verschiedener Arten von Tests und die Erstellung des Projekts. Bei GitLab CI würde eine solche Pipeline wie folgt aussehen (unter Verwendung des Node-Ökosystems zur Veranschaulichung):
# .gitlab-ci.yml
stages: # stages werden in Reihenfolge abgearbeitet
- build
- test
- deploy
build-code: # Job Name
stage: build
script:
- npm install # install dependencies
- npm run build # build code
code-style:
stage: test
script:
- npm install # install dependencies
- npm run lint # check code style
unit-tests:
stage: test
script:
- npm install # install dependencies
- npm run test:unit # run unit tests
Die Automatisierung der Code-Prüfung spart Zeit und erhöht die Sicherheit der Veröffentlichung, da Fehler frühzeitig erkannt werden. Dies kratzt jedoch nur an der Oberfläche dessen, was CI leisten kann. Bei größeren Projekten gehen CI-Pipelines oft weit über drei Stufen hinaus.
Der Aufbau einer CI-Pipeline für eine komplexe Codebasis kann Folgendes umfassen:
Dies sind nur einige Beispiele. Eine gut konzipierte CI-Pipeline kann auf spezifische Projektanforderungen zugeschnitten werden, von der Verbesserung der Build-Leistung bis hin zur Verbesserung der Codequalität und der Teamzusammenarbeit.
Nachdem der Code in der CI-Phase erstellt und getestet wurde, wird der Build in der Continuous Delivery (CD) aus dem Integrationsschritt übernommen und für die Veröffentlichung vorbereitet. Dazu gehört die Bereitstellung des Builds in der Staging- oder Produktionsumgebung, die Durchführung einer weiteren Reihe von End-to-End-Tests und das Hochladen der Binärdatei in eine interne Registrierung.
Die Beispiele hier verwenden GitLab CI und das Node-Ökosystem, aber die gleiche Logik kann auf jeder CI/CD-Plattform wie Bitbucket Pipelines oder GitHub Actions implementiert werden.
Um das vorherige Codebeispiel mit CD zu erweitern, würden Sie Deploy-Stages hinzufügen, um den Build in die Staging- oder Produktionsumgebung zu übertragen:
stages:
- test
- build
- deploy-to-staging
- deploy-to-production
deploy-to-staging:
stage: deploy-to-staging
script:
- npm install # install dependencies
- npm run deploy:staging # deploy to staging
deploy-to-production:
stage: deploy-to-production
when: manual # Diese Stage kann nur manuell gestartet werden
script:
- npm install # install dependencies
- npm run deploy:production # deploy to production
Einfache automatisierte Deployments, wie der Deploy-to-Staging-Schritt im obigen Beispiel, sind ein guter Ausgangspunkt für kleinere Projekte oder unkomplizierte Anwendungsfälle. Größere oder komplexere Projekte erfordern jedoch in der Regel zusätzliche Techniken, um die Sicherheit und Kontrolle zu verbessern; darüber werden Sie später mehr erfahren.
Der Schritt vom Deployment zur Produktion in diesem Beispiel ist nicht automatisiert, sondern manuell. Die Entscheidung zwischen automatisierten und manuellen Bereitstellungen hängt von mehreren Faktoren ab, darunter die Häufigkeit der gewünschten Releases, die Zuverlässigkeit der Tests, gesetzliche Anforderungen und Managementpraktiken.
Die Verwendung von CD und die Automatisierung der Bereitstellungsprozesse ermöglichen eine schnellere Rückmeldung über die Qualität der Releases, was zu risikoärmeren und besser vorhersehbaren Releases führt.
Continuous Deployment ist eine Form der kontinuierlichen Bereitstellung, bei der jede Codeänderung, die alle Prüfungen besteht, automatisch für die Produktion bereitgestellt wird. Während es bei der kontinuierlichen Bereitstellung darauf ankommt, dass jede Änderung bereit für die Bereitstellung ist, geht die kontinuierliche Bereitstellung noch einen Schritt weiter, indem sie den manuellen Genehmigungsschritt vollständig eliminiert.
Um die kontinuierliche Bereitstellung mit der Pipeline aus dem vorherigen Abschnitt zu implementieren, entfernen Sie das Flag when: manual
aus der Phase deploy-to-production
. Wenn Sie das Deployment in die Staging-Umgebung nicht benötigen (vorausgesetzt, Sie vertrauen auf die CI-Tests als primäre Sicherung der Codequalität), können Sie den Schritt deploy-to-staging
auch weglassen:
deploy-to-production:
stage: deploy-to-production
script:
- npm install # install dependencies
- npm run deploy:production # deploy to production
Continuous Deployment bietet dieselben Vorteile wie Continuous Delivery: geringerer manueller Aufwand, verbesserte Konsistenz der Releases und die Möglichkeit, kontinuierlich hochwertige Updates zu liefern. Es erfordert jedoch robuste automatisierte Tests und Überwachung, da Codeänderungen ohne manuelle Überprüfung bereitgestellt werden, was das Risiko von Problemen in der Produktion erhöht. Außerdem sind erhebliche Investitionen in Infrastruktur und Prozesse erforderlich, um die Zuverlässigkeit zu gewährleisten und bei Bedarf schnelle Rollbacks zu ermöglichen.
Hinweis: Obwohl sowohl Continuous Delivery als auch Continuous Deployment das Akronym "CD" verwenden, wird im folgenden Teil dieses Artikels "CD" für Continuous Deployment verwendet.
Im Folgenden wird beschrieben, wie kontinuierliche Integration und Bereitstellung in einer DevOps-Pipeline normalerweise funktionieren:
Wie Sie sehen, umfasst eine vollständige Pipeline viele Systeme:
Hinter den Kulissen startet jeder Code-Push:
Die Pipeline-Ausführung umfasst mehrere parallele Prozesse:
Dies ist nur ein Beispiel für eine Pipeline; je nach den Anforderungen Ihrer Anwendung können weitere Komponenten erforderlich sein.
Wie bereits erwähnt, wäre bei einem kleineren Projekt eine einfache automatisierte Bereitstellung, wie das zuvor verwendete Beispiel, ein guter Ausgangspunkt. Bei größeren oder komplexeren Projekten sind jedoch in der Regel zusätzliche Techniken erforderlich, um die Sicherheit und Kontrolle zu verbessern.
Ein Ansatz ist die Verwendung von Feature Flags, um Code mit Funktionen bereitzustellen, die vor den Benutzern verborgen bleiben, bis sie als stabil eingestuft werden, so dass inkrementelle Veröffentlichungen und ein einfaches Rollback möglich sind, falls erforderlich. Es gibt verschiedene Arten von Feature Flags, wie z. B. Release Toggles, die eine schrittweise Einführung von Funktionen ermöglichen, und Experiment Flags, die für A/B-Tests verwendet werden. Eine E-Commerce-Website könnte z. B. einen neuen Suchfilter entwickeln, diesen aber hinter einem Feature Flag verstecken, bis gründliche Tests abgeschlossen sind, damit er sofort aktiviert werden kann, wenn er fertig ist.
Sie können auch "Canary Releases" und Rollbacks verwenden, um das Risiko von Fehlern, Performanceproblemen oder unbeabsichtigten Auswirkungen auf die Benutzer bei der Einführung neuer Funktionen zu verringern. Bei einem "Canary Release" wird zunächst eine kleine Gruppe von Benutzern einbezogen. So können Sie Metriken sammeln und sicherstellen, dass die Funktion wie erwartet funktioniert. Wenn Probleme auftreten, können Sie die Freigabe für diese kleine Gruppe zurücknehmen, wodurch der Prozess schneller und weniger riskant wird. Sie können noch einen Schritt weiter gehen, indem Sie Rollbacks auf der Grundlage der zuvor ausgewählten Metriken automatisieren. Durch die Automatisierung können Sie auch die manuelle Durchführung von Datenbankmigrationen bei Rollbacks vermeiden. Mit diesen Techniken können Sie Ihren Benutzern reibungslose, schrittweise Implementierungen anbieten.
Überwachungs- und Feedback-Tools sind unerlässlich, um einen umfassenden Überblick über Ihre Dienste zu erhalten und so einen sicheren Rollout zu gewährleisten und schnelle Rollbacks zu ermöglichen, wenn Probleme auftreten. Tools wie Blackfire.io sind wertvolle Ergänzungen des Release-Prozesses. Zu den wichtigsten Metriken, die es zu überwachen gilt, gehören Fehlerraten, Anfragelatenz, Bereitstellungsfortschritt (insbesondere bei Canary-Bereitstellungen), Erfolgs- und Misserfolgsraten bei Feature-Flags sowie Metriken zur Benutzerbindung. Anhand dieser Daten lassen sich Probleme, wie z. B. eine erhöhte Fehlerquote oder die Abkehr der Benutzer, erkennen, so dass gegebenenfalls ein Rollback erforderlich ist. Überwachungs-Tools ermöglichen außerdem konfigurierbare Warnmeldungen und Rollout-spezifische Dashboards, um kritische Metriken zu verfolgen und so die Beobachtbarkeit zu verbessern und zu einer sicheren und effizienten Veröffentlichung von Updates beizutragen.
Es gibt auch einige Best Practices, die Sie befolgen können, um Arbeitsabläufe zu verbessern und gleichzeitig die Zuverlässigkeit und Sicherheit des CI/CD-Prozesses zu erhöhen.
Die Testautomatisierung in CI/CD stellt sicher, dass Änderungen ohne manuelle Eingriffe vollständig getestet werden, was Zeit spart und das Risiko verringert. In Anlehnung an die Testpyramide, mit Unit-Tests an der Basis, Integrationstests in der Mitte und End-to-End-Tests (E2E) an der Spitze, werden Abdeckung und Geschwindigkeit ausbalanciert, um sicherzustellen, dass Probleme auf der richtigen Ebene abgefangen werden, ohne die Pipeline zu überlasten.
Schlüsselelemente wie Codeabdeckung, Mutationstests und Datenmanagement verbessern die CI/CD-Tests weiter. Die Codeabdeckung hilft dabei, sicherzustellen, dass wichtige Bereiche getestet werden, während Mutationstests Schwachstellen aufdecken, indem sie prüfen, ob Tests absichtliche Fehler abfangen. Die Verwaltung von Testdaten durch Mocks oder Snapshots erhöht die Zuverlässigkeit und Wiederholbarkeit und verbessert so die Gesamtqualität der Software. Durch die parallele Ausführung von Tests, die selektive Ausführung betroffener Tests und die Isolierung von Umgebungen können Testzeit und Stabilität optimiert werden.
Optimierungen
Die Optimierung von CI/CD-Pipelines ist von entscheidender Bedeutung, um die Wartezeit für Entwickler zu minimieren und somit Änderungen schneller bereitzustellen. Die Optimierung der Pipelinezeit ist auch für die Kostenkontrolle von entscheidender Bedeutung, da die meisten Plattformen auf der Grundlage der Nutzungszeit und der verbrauchten Ressourcen abrechnen. Hier sind drei Beispiele, wie Sie Ihre Pipeline optimieren können:
Weitere Optimierungen umfassen die Optimierung von Docker-Images und die effiziente Verwaltung von Abhängigkeiten, sowohl innerhalb des CI-Jobs als auch der für den Build verwendeten Abhängigkeiten.
Sicherheit
CI/CD-Prozesse stellen besondere Sicherheitsanforderungen, wenn Sie sicherstellen wollen, dass die Pipeline und die Anwendungen vor Schwachstellen geschützt bleiben. Dazu gehört ein vielseitiger Ansatz zur Identifizierung von Schwachstellen in verschiedenen Entwicklungs- und Bereitstellungsphasen. Statische Anwendungssicherheitstests (SAST) scannen Quellcode oder Binärdateien, um Sicherheitsschwachstellen bereits in der Entwicklungsphase zu identifizieren. Dynamische Anwendungssicherheitstests (DAST) analysieren laufende Anwendungen, um Probleme wie Injektionsangriffe und Konfigurationsfehler zu erkennen. Software Composition Analysis (SCA) untersucht Abhängigkeiten von Drittanbietern und Bibliotheken auf bekannte Schwachstellen und Lizenzkonformität. Diese Tools arbeiten zusammen, um Anwendungen während des gesamten Entwicklungs- und Bereitstellungslebenszyklus zu sichern.
In der obigen Beispielpipeline werden statische Sicherheitstools im Schritt der Codequalitätsprüfung verwendet, um den Code auf Schwachstellen zu überprüfen. Um dynamische Sicherheitstests in einer laufenden Anwendung zu implementieren, können Sie einen zusätzlichen Job einrichten, der darauf wartet, dass der Build generiert wird, ihn in eine Vorschauumgebung schiebt (möglicherweise eine auf Upsun gehostete) und dann ein DAST-Tool (wie OWASP Zap) ausführt, um Sicherheitsprüfungen daran durchzuführen.
Sensible Daten, wie z. B. API-Schlüssel, sollten sicher gespeichert und in Pipelines eingefügt werden. Sie können die integrierte Geheimnisverwaltung Ihrer CI/CD-Plattform nutzen, um die gespeicherten Daten zu verschlüsseln und sie sicher in den Pipeline-Code zu injizieren. Wenn Sie erweiterte Anforderungen haben, wie z. B. dynamische Schlüsselgenerierung oder ein flexibles Berechtigungssystem, sollten Sie externe Dienste wie HashiCorp Vault oder AWS Secrets Manager verwenden.
Wenn Ihre Pipeline Artefakte wie Builds oder Testergebnisse veröffentlicht, ist es wichtig, diese vor unbefugtem Zugriff zu schützen, damit niemand auf private Informationen zugreifen kann, die von Ihrer Pipeline erzeugt wurden. Sie können auch einen Schritt zur Schwachstellenüberprüfung von Artefakten hinzufügen, um sicherzustellen, dass keine sensiblen Daten versehentlich injiziert wurden und dass sie keinen potenziell schädlichen Code enthalten.
In diesem Artikel wurden die Kernkonzepte von CI/CD, bewährte Praktiken für die Implementierung und fortgeschrittene Techniken, die Ihren Freigabeprozess verändern können, erläutert. Zu den wichtigsten Vorteilen von CI/CD gehören eine schnellere Markteinführung, höhere Zuverlässigkeit, weniger manuelle Fehler und die Möglichkeit, Entwicklungsabläufe für komplexe Projekte zu skalieren.
Doch hier liegt die Herausforderung: Selbst bei soliden CI/CD-Pipelines bleibt das Testen in produktionsähnlichen Umgebungen ein Engpass. Die meisten Teams kämpfen mit Umgebungsinkonsistenzen, begrenzten Staging-Ressourcen und der Unfähigkeit, mit echten Daten sicher zu testen.
An dieser Stelle verbessert Upsun Ihre bestehenden CI/CD-Workflows. Anstatt Ihre CI/CD-Plattform zu ersetzen, lässt sich Upsun nahtlos in GitHub Actions, GitLab CI, Jenkins und andere Tools integrieren, um die Herausforderungen bei der Bereitstellung und beim Testen zu lösen, die Pipelines allein nicht bewältigen können.
Anstatt eine komplexe Bereitstellungsinfrastruktur zu verwalten, kann sich Ihre CI/CD-Pipeline auf das konzentrieren, was sie am besten kann: das Erstellen und Testen von Code, während Upsun die Bereitstellung, die Bereitstellung der Umgebung und das Hosting in Produktionsqualität übernimmt.
Sind Sie bereit, Ihre CI/CD-Pipeline zu verbessern? Starten Sie Ihre kostenlose Upsun-Testversion und erleben Sie nahtlose Bereitstellungen mit produktionsähnlichen Testumgebungen, die sich in Ihre bestehenden Arbeitsabläufe integrieren lassen.