Optimierung von Jenkins-Pipelines durch Shared Libraries

Dieser Blog-Beitrag ist eine Fortsetzung der Fallstudie zur Optimierung der CI/CD für einen Anbieter von Infrastrukturlösungen. Wir werden das Vorgehen zur Optimierung unserer Jenkins-Pipelines mithilfe gemeinsamer Bibliotheken erläutern und Beispiele für einen einfachen Maven+Podman-Build bereitstellen.
Obwohl wir uns in diesem Beitrag auf deklarative Pipelines konzentrieren werden, sollten Sie im Hinterkopf behalten, dass sowohl deklarative als auch skriptbasierte Pipelines von gemeinsamen Bibliotheken profitieren können. Die meisten hier behandelten Konzepte werden auch auf skriptbasierte Pipelines anwendbar sein, allerdings gibt es in einigen Fällen Unterschiede.

Vorteile der Verwendung gemeinsamer Bibliotheken

Die Verwendung gemeinsamer Bibliotheken in Jenkins bringt mehrere Vorteile mit sich, ähnlich wie bei der Verwendung von Bibliotheken für andere Programmiersprachen. Hier haben wir fünf Hauptvorteile hervorgehoben:

  • Code-Wiederverwendung: Oftmals ähneln sich Pipelines, die über mehrere Jobs geschrieben sind, fast identisch, wobei der einzige wirkliche Unterschied ein paar Variablen wie Projektname oder Version sind. Mit einer gemeinsamen Bibliothek können wir denselben Code verwenden und unnötige Redundanz beseitigen.
  • Einfachere Wartung: Dies steht im Zusammenhang mit dem vorherigen Punkt, da die Zentralisierung des Codes in einer gemeinsamen Bibliothek Codeänderungen schneller und einfacher macht. Jobs ziehen regelmäßig Änderungen aus der Bibliothek, alternativ können Sie die Bibliothek so einstellen, dass sie den aktualisierten Code automatisch für jeden Build abruft und unsere Änderungen sofort überträgt.
  • Standardisierung: Gemeinsame Bibliotheken erleichtern die Durchsetzung besserer Codierungsstandards, sodass wir eine standardisierte Benutzeroberfläche für die Konfiguration von Jobs implementieren, Qualitätsprüfungen durchführen und verschiedene andere Aufgaben ohne erschwerte Konfiguration einzelner Jobs umsetzen können.
  • Sicherere Jobs: Mit einer gut durchdachten gemeinsamen Bibliothek können wir alle notwendigen Überprüfungen für Eingaben implementieren, um potenzielle Sicherheitslücken zu vermeiden, bei der Fehlerbehebung zu unterstützen oder sich von bestimmten Fehlern zu erholen.
  • Optimierter Pipeline-Code: Durch eine gemeinsame Bibliothek, die die inneren Abläufe verschiedener Funktionen in unserem Code abstrahiert, können wir eine hohe Komplexität in unseren Pipelines haben und gleichzeitig nur eine optimierte Schnittstelle für den Build-Ingenieur freigeben.

Voraussetzung

Für unsere Beispielimplementierung verwenden wir drei verschiedene Programmiersprachen (Java, Rust und Go), die auf 12 Jobs verteilt sind. Jeder Job erfordert, dass alle Schritte separat geschrieben werden; Code abrufen, Tests ausführen, erstellen usw. Die meisten dieser Schritte verwenden viel Code wieder, selbst wenn für verschiedene Sprachen erstellt wird.
Aus Gründen der Einfachheit lassen wir Parameter weg und werden nur die folgenden Phasen einbeziehen:

  • Code abrufen (git)
  • Erstellen (Maven)
  • Container erstellen (Podman)
  • Container in Registry verschieben (firmeninterne Registry)

Hier ist ein Beispiel für diese einfache Pipeline:

Beispiel einfache Pipeline

Link zum Code
Sie werden feststellen, dass alle unsere Variablen bereits in den Umgebungsblock exportiert wurden, während der größte Teil des Codes im Stages-Block sicher in eine gemeinsam genutzte Bibliothek verschoben werden kann. Von dort aus können wir es einfach aus der Pipeline aufrufen.

Umsetzung

Zunächst fügen wir unsere gemeinsame Bibliothek zu Jenkins hinzu, damit wir sie in unseren Pipelines aufrufen können. (Sie benötigen Administratorzugriff, um dies auf Ihrem Jenkins-Controller zu konfigurieren.)

  • Navigieren Sie zu Ihrem Jenkins-Dashboard und klicken Sie auf der linken Seite auf „Jenkins verwalten“, wählen Sie dann „System“ aus, oder Sie können direkt zu diesem Pfad navigieren: /manage/configure
  • Scrollen Sie nach unten zu „Globale Pipeline-Bibliotheken“ und klicken Sie auf die Schaltfläche „Hinzufügen“.
  • Füllen Sie alle erforderlichen Parameter aus. Beachten Sie bitte, dass für gemeinsame Bibliotheken die Verwendung eines SCM wie Git erforderlich ist.
    Wir empfehlen auch, „Frisches Klonsystem pro Build“ während des Tests zu aktivieren, damit Änderungen an der Bibliothek sofort in Ihren Jobs reflektiert werden.

In unserem Beispiel haben wir uns außerdem dafür entschieden, Hash Maps zu verwenden, um unsere verschiedenen Optionen zu speichern. Wenn Sie jedoch beispielsweise Umgebungsvariablen verwenden möchten, können Sie das ebenfalls tun. Beachten Sie jedoch, dass Sie dann die Eingabe für Ihre Bibliotheksmethoden ändern müssten.

Hier ist unsere Beispiel-Pipeline unter Verwendung einer gemeinsamen Bibliothek:

Beispiel-Pipeline unter Verwendung Shared Library

Link zum Code

Wir können nun einige der vorherigen Variablen entfernen, da sie nun innerhalb der gemeinsamen Bibliothek gespeichert sind. Wir haben jedoch weiterhin die Möglichkeit, sie zu überschreiben, zum Beispiel dockerBuild.registryURL. Der Block tools wurde ebenfalls entfernt, da er jetzt immer aufgerufen wird, wenn wir universalBuild() mit einem Maven-Build-Typ ausführen.
In einer umfangreicheren Implementierung könnten wir den Build-Typ aus dem Kontext erkennen oder sogar die relevante Konfigurationsdatei analysieren, um den Versionsstring zu erhalten (z. B. pom.xml für Maven). All dies kann innerhalb der Funktion universalBuild() abstrahiert werden. Wir könnten sogar die gesamte Pipeline in eine gemeinsame Bibliothek verschieben, aber das werden wir heute nicht behandeln.
Hinweis: Wenn wir deklarative Pipelines verwenden, müssen wir unsere Funktionsaufrufe in einen Skriptblock setzen.
Schauen wir uns an, was sich in universalBuild() befindet:

Beispiel - universalBuild

Link zum Code
Dies ist eine einfache Funktion, die einige Vorverarbeitungsschritte durchführt, bevor die entsprechende Build-Funktion aufgerufen wird. Schauen wir uns als nächstes die Funktion `builds.maven()` an.

Funktion builds.maven

Link zum Code
Auch dies ist eine sehr einfache Funktion, die einfach einige Standardwerte aufruft, die relevante Maven-Version lädt und schließlich mit Maven erstellt.
(Die restlichen Funktionen, wie gitLib.checkout() oder builds.docker(), sind im Repository verfügbar, das am Ende des Beitrags und unter einem der Bilder verlinkt ist.)

Fazit

Gemeinsame Bibliotheken bieten zahlreiche Vorteile, und je früher Sie sie mit Ihrem Team implementieren, desto mehr Nutzen werden Sie daraus ziehen. Mit einer skalierbaren und benutzerfreundlichen gemeinsamen Bibliothek kann sich Ihr Team auf andere Aufgaben konzentrieren als auf die ständige Wartung von Jobs und muss sich keine Sorgen machen, bestimmte Standards Ihres Unternehmens nicht zu erfüllen, da sie innerhalb der Bibliothek überprüft werden können. Zusammenfassend sind gemeinsame Bibliotheken ein sehr leistungsfähiges Werkzeug in Jenkins, das jedes mittelgroße bis große Team nutzen sollte, um Ingenieursstunden zu sparen und ihren CI/CD-Prozess zuverlässig zu gestalten!
Wenn Sie Fragen haben, zögern Sie bitte nicht, mich unter [email protected] zu kontaktieren.

Zusätzliche Ressourcen

Beispiel für eine gemeinsame Bibliothek – Repository mit dem gesamten in diesem Beitrag geteilten Code
Dokumentation zu gemeinsamen Bibliotheken – Offizielle Jenkins Shared Library-Dokumentation
CloudBeesTV – Hochwertige Jenkins-Tutorial-Videos
Online-Groovy-Sandbox – Testen Sie Teile Ihrer Skripte, bevor Sie sie in Ihre Pipeline implementieren.

Lesen Sie einen weiteren Artikel von unseren Experten:

Basis-Pipeline Für Die Entwicklung Eines SSO-Servers Mit ASP.Net Identity Und OpenIddict

 

 

Kontakt
Kontakt


    Insert math as
    Block
    Inline
    Additional settings
    Formula color
    Text color
    #333333
    Type math using LaTeX
    Preview
    \({}\)
    Nothing to preview
    Insert