© Enkel/Shutterstock.com
Mit der Migration zu Kubernetes wird bei Jenkins alles anders

Jenkins-less CI/CD mit Kubernetes


Jenkins X ist das jüngste Produkt aus dem Hause CloudBees, dem Hersteller von Jenkins. Außer dem Namen bleibt nicht viel von der weitverbreiteten Continuous-Anything-Plattform, die weitere Verwendung des Namens Jenkins ist sowohl Heilsversprechen als auch Menetekel. Zum einen versucht man wohl, die Jünger des altbekannten Butlers mitzunehmen, zum anderen schreckt man leider auch neue potenzielle Nutzer ab.

Mit Jenkins verband viele seiner Fans und Kritiker eine Hassliebe: Das Ökosystem rund um den klassischen Jenkins ist mit seinen über 1 000 Plug-ins sehr leistungsfähig und vielseitig, aber leider auch kompliziert und fehleranfällig. Wird sich das mit Jenkins X ändern? Viele Nutzer suchen (vermeintlich) einfache Build Engines, wie sie z. B. durch das inzwischen eingestellte Travis CI auf Basis einer YAML-Konfigurationsdatei vorlagen. Aber was ist mit komplexeren Build- oder Deployment-Szenarien? Lassen die sich damit realisieren? Sind sie überhaupt noch nötig? Jenkins X versucht, neue Wege zu gehen, aber gleichzeitig konzeptionell an die vielen Jahre Erfahrung der Jenkins-Entwicklung und die daraus gewachsene Gemeinde der Nutzer anzuknüpfen.

Die gute Nachricht: Jenkins X realisiert wie der Vorgänger im weitesten Sinne auch wieder eine Continuous-Integration/Delivery-Plattform – allerdings technisch komplett anders als der Vorgänger. Außerdem ist Jenkins X auch wieder ein Open-Source-Projekt [1] und es gibt kommerziellen Support von CloudBees [2].

So gut wie alles ist technisch neu, wobei die wichtigste Änderung die Ausführungsplattform betrifft. Jenkins X funktioniert ausschließlich auf Kubernetes und Derivaten wie OpenShift. Es kann sich potenziell um ein sehr kleines Kubernetes mit nur einem Knoten handeln, aber die Verwendung von Kubernetes ist unabdingbare Voraussetzung, da Jenkins X in vielen Komponenten eine Erweiterung von Kubernetes ist. Es implementiert viele seiner Funktionen als sogenannte Custom Resource Definitions und erweitert damit das Kubernetes API (Kasten: „Jenkins-X-Background: Kubernetes und Helm“).

Jenkins-X-Background: Kubernetes und Helm

Jenkins X läuft ausschließlich auf Kubernetes und nutzt für viele Dinge den Kubernetes-Package-Manager Helm. Beide Technologien können wir hier nur kurz und relativ allgemein anreißen.

Kubernetes

Kubernetes ist eine Abstraktion über verschiedene Cloud-Provider. Es basiert auf der Docker-Technologie und ermöglicht die Orchestrierung von Anwendungscontainern (Feinheiten wie die Verwendung von anderen leichtgewichtigen Containertechnologien ignorieren wir der Einfachheit halber). Jede Anwendung besteht in Kubernetes aus einem oder mehreren (Docker-)Container(n), den sogenannten Pods. Kubernetes kann so konfiguriert werden, dass mehrere Instanzen der Anwendung gestartet werden, auch dynamisch z. B. je nach Last oder Verfügbarkeitsanforderungen. Die Schnittstelle einer Anwendung wird in Kubernetes als Service bezeichnet. Die Anwendungen/Services können sich untereinander aufrufen und sind auch von außerhalb eines Kubernetes-Containers aufrufbar.

Ein Kubernetes-System (eine Instanz) wird auch als Kubernetes-Cluster bezeichnet. Der Cluster besteht in der Regel aus mehreren realen oder virtuellen Maschinen des zugrunde liegenden Cloud-Providers und Kubernetes verteilt (orchestriert) die Anwendungen darauf. Dabei berücksichtigt Kubernetes die Auslastung (Speicher, CPU, Netz, I/O) der einzelnen Knoten des sie verbindenden Netzwerks und der verfügbaren Speichermedien.

Alle Kubernetes-Implementierungen der verschiedenen Cloud-Anbieter bieten (je nach Kubernetes-Version) neben ihren spezifischen Diensten eine einheitliche Laufzeitschnittstelle (Docker) und allgemeine Kubernetes-Dienste an, z. B. den Kubernetes-API-Server. Der API-Server implementiert eine REST-Schnittstelle, über die ein Cluster verwaltet wird. Alle Ressourcen (Anwendungen, Pods, Deployments und viele weitere) sind über das API konfigurierbar. Das Kubernetes API ist durch Custom Resource Definitions (CRDs) und Kubernetes-Operatoren erweiterbar, das sind spezielle Kubernetes Services, die im Cluster deployt werden (Listing 1). Jenkins-X erweitert Kubernetes um eine Reihe von Operatoren, z. B. für Webhooks.

Als Benutzer spricht man den API-Server per Kommandozeilentool (kubectl) an, das in vielen Punkten an die REST-Schnittstelle des API-Servers angelehnt ist. Die Konfiguration von Kubernetes erfolgt über JSON- oder YAML-Dateien (sog. Manifeste), die als REST-Ressource über den API-Server geladen oder abgefragt werden.

Kubernetes verwaltet seine Ressourcen (Anwendungen etc.) in Namespaces, z. B. für unterschiedliche Umgebungen oder Teams.

Helm

Ein Kubernetes-Manifest enthält viele konkrete Parameter, z. B. den gewünschten Speicher einer Anwendung. Diese Parameter können und werden sich je nach Umgebung (Entwicklung, Test, Produktion) unterscheiden. Das Projekt Helm ermöglicht eine verallgemeinerte Beschreibung zusammenhängender Kubernetes-Manifeste unter Verwendung einer Template-Engine. Mit Hilfe der Template-Engine (Go-Templates) lassen sich die variablen Anteile der Manifeste z. B. je nach Umgebung auslagern. Die Manifeste (für Deployment, Konfiguration, Service-Definition etc.) werden zu einem sog. Helm Chart zusammengefasst. Der Chart lässt sich in einem Repository ablegen und durch das Kommandozeilentool helm deployen, wieder vom Cluster löschen oder anpassen. Wir sprechen hier von einem Anwendungs-Helm-Chart.

Listing 2 zeigt das Fragment aus Listing 1 als Helm Chart. Bestimmte Anteile wurden hier durch Variablen ersetzt: der Name der Anwendung, die Anzahl der Replikate und die Koordinaten des Docker Image. Helm ersetzt bei der Ausführung (Deployment) die Platzhalter durch konkrete Werte, sodass effektiv wieder ein Manifest wie oben entsteht. Die Parametrisierung von Helm kann z. B. umgebungsspezifisch erfolgen oder in Abhängigkeit zu anderen Anwendungen und deren Konfigurationen.

Außerdem können Anwendungen voneinander abhängig sein, z. B. ein Frontend Service einer Anwendung von einem oder mehreren Backend Services. Helm Charts können auf diese Abhängigkeiten verweisen und Helm würde beim Deployment auch die abhängigen Anwendungen mitdeployen (sofern sie im Namespace noch nicht vorhanden sind). Helm bezeichnet sich selbst daher auch als Package-Manager für Kubernetes, vergleichbar mit Homebrew bei macOS oder Linux-Package-Managern wie Yum.

Jenkins X nutzt diesen Mechanismus aus und fasst die Anwendungen einer Umgebung in einem Helm Chart zusammen.

Listing 1: Beispielmanifest zum Deployment eines Service (Auszug)

apiVersion: apps/v1 kind: Deployment metadata: name: jx-demo-jm spec: replicas: 1 template: spec: containers: - image: gcr.io/jxtest-199909/demo-jm:0.0.1

Listing 2: Beispieltemplate zum Deployment eines Service (Auszug)

apiVersion: apps/v1 kind: Deployment metadata: name: {{ template "fullname" . }} spec: replicas: {{ .Values.replicaCount }} template: spec: containers: - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" ...

J...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang