05. September 2017

Continuous Integration für Kubernetes mit Jenkins

Continuous Integration für Kubernetes mit Jenkins (Bild: pixabay.com/StockSnap)

Bei der Entwicklung und dem Betrieb von Software mit modernen Microservices sind Continuous Integration (CI) und Continuous Delivery (CD) nicht mehr weg zu denken. Dazu gehört auch die Philosophie, jeden Build der Software gründlich zu testen und aktuell zu halten. Dieser Beitrag befasst sich mit den Herausforderungen bei CI/CD mit Jenkins von Kubernetes-basierten Software Produkten.

Jenkins – von Code zu Container

Das frei verfügbare Produkt Jenkins ist eine Software für das Bauen und Deployen von Applikationen. Es wird weitgehend als CI/CD Software benutzt, da es sehr einfach mit verschiedenen Plugins erweiterbar ist; außerdem ist es einfach zu installieren und lässt sich sehr leicht bedienen.

Über ein Web Interface lassen sich vordefinierte Software Deployments anstoßen, die auch automatisiert in eine Betriebsumgebung (wie Kubernetes) geschickt werden können. Der Deployment-Ablauf beginnt für Jenkins meistens mit einem externen Ereignis. Dies kann zum Beispiel ein Commit in ein Git Repository sein. Jenkins lädt den Software Code aus Git und baut daraus eine Applikation mit allen notwendigen Abhängigkeiten, die anschließend von Jenkins in ein Docker Image verpackt wird. Dieses Docker Image wird danach in ein Docker Repository hochgeladen, damit es für Applikationsserver verfügbar ist. Mit Jenkins haben wir uns in diesem Blog-Beitrag bereits ausführlich auseinandergesetzt.

Essenzielle Vorarbeiten – ohne sie läuft gar nichts

Der Vorteil einer Applikation in einem (Docker) Container ist die Einsetzbarkeit in verschiedenen Umgebungen. Ein Container kann sowohl in einer Testumgebung als auch (nach gründlichen Tests) in einer produktiven Umgebung gestartet werden, da alle Abhängigkeiten bereits im Container enthalten sind. Trotzdem muss man Vorarbeit leisten und folgende Punkte definieren, die für den produktiven Betrieb eines Containers lebenswichtig sind:

– Schnittstellen der Applikation

Datenbanken oder andere externe Systeme sind in jeder Situation anders erreichbar. Kubernetes bietet die Möglichkeit, Dienste über „Services“ anzusprechen. Ein Service kann aber nicht nur Applikationen in Kubernetes erreichbar machen, sondern ist auch auf externe Systeme einstellbar. Damit kann eine Applikation zum Beispiel eine Datenbank immer über einen Servicenamen ansprechen, der auf eine eingestellte IP des Systems weiterleitet. Diese explizite Definition der Schnittstellen erlaubt auch den Austausch von externen Servern oder das Clustern von Diensten, da Services auch auf mehrere IPs verteilt zeigen können.

– Umgebungsabhängige Parameter

Jede Applikation benötigt eine Konfiguration, damit die Software einwandfrei laufen kann. In dieser Konfiguration sind statische Parameter, z.B. für Mailversand, Memory Management und Einstellungen für den Parallelbetrieb mehrerer Container, enthalten. Dazu werden in Kubernetes „ConfigMaps“, statische Konfigurationsdateien, die einem Container beim Start übergeben werden, definiert. Diese Dateien können in allen Umgebungen gleich benannt werden und für jede Umgebung spezifische Parameter enthalten. So startet ein Container immer genau richtig in der gewünschten Umgebung.

– Health Checks für Lifecycle Management

Kubernetes übernimmt zwar den Betrieb und sorgt für hohe Verfügbarkeit einer Applikation. Der genaue Start des Containers ist allerdings für Kubernetes nicht sichtbar. Es ist deshalb unbedingt notwendig, einen „Health Check“ in die Applikation einzubauen. Dieser extern erreichbare Check muss von Anfang an vorgesehen sein, und alle wichtigen Parameter der Applikation zu einem Schlagwort (OK oder FATAL) zusammenfassen. Der Check wird in Kubernetes konfiguriert und benutzt, um sicherzustellen, dass die Applikation gebrauchsfertig ist.

Non-disruptives Deployment – der continuous Teil der Integration

Nachdem die Applikation richtig verpackt wurde und auf den Betrieb in allen Umgebungen vorbereitet ist, folgt nun die Herausforderung des Deployments. In hochverfügbaren Kubernetes Software-Umgebungen liegt der Fokus immer auf der Erreichbarkeit der Applikation. Das Bereitstellen einer neuen Version sollte also auf keinen Fall diese Erreichbarkeit in irgendeiner Form beeinträchtigen.

Das Konzept des „Rolling Update“ in Kubernetes bietet die Möglichkeit neue Versionen der Software kurzfristig neben der bestehenden Version zu starten. Die neue Version wird nach und nach mit in die Lastverteilung einbezogen, gleichzeitig wird die bestehende Version langsam abgeschaltet.

Obwohl sich dieses Konzept grundsolide anhört, muss die Applikation darauf vorbereitet sein. Dabei kommt der bereits genannte Health Check ins Spiel. Kubernetes prüft mit dem Health Check, ob die Applikation im Container gestartet ist und nimmt diese erst dann in die Lastverteilung auf. Des Weiteren werden erst nach erfolgreichem Check der neuen Version Container der bestehenden Version abgeschaltet. Ein wichtiger Prozess, der ein non-disruptives Deployment erfolgreich ablaufen lässt.

Jenkins spielt bei diesem Prozess nur die Rolle des Auftraggebers. Nachdem eine Software erfolgreich mit Jenkins gebaut und hochgeladen wurde, gibt Jenkins den Befehl des Rolling Updates in Kubernetes. Der Prozess wird von Jenkins mit überwacht, Jenkins hat aber keinen Einfluss auf den Ablauf des Rolling Updates. Wegen dieser Aufgabenverteilung ist ein funktionsfähiger Health Check auf Applikationsebene so wichtig –Jenkins kann während des Deployments nicht selbstständig prüfen, ob die Applikation bereits gestartet ist.

Zusammenfassung – Die komplette Pipeline

Wenn alle Randbedingungen erfüllt sind, lässt sich Software mit dieser CI/CD Pipeline über Jenkins in Kubernetes reibungslos ausrollen. Dabei sorgt Jenkins nach einem Git Commit für eine Applikation mit allen Abhängigkeiten in einem Docker Container und gibt Kubernetes die Aufgabe zum Deployment. Mit vordefinierten ConfigMaps, externen Diensten über Services und den Health Checks innerhalb der Applikation wird eine neue Softwareversion ohne Einschränkung der Erreichbarkeit zur Verfügung gestellt.

Damit ist das Bereitstellen neuer Software nicht nur höchst effizient, sondern auch sehr robust. Im Gegensatz zum manuellen Deployen ist man bei dieser CI/CD Pipeline unabhängig von Dokumentation oder Know-how einzelner Personen. Jeder Schritt ist automatisiert und universell einsetzbar. Dies kann die Fehlerquote beim Ausrollen neuer Software deutlich senken.

(Alexander Hetmann)

Keine Kommentare


Dein Kommentar:

* Pflichtfelder

Time limit is exhausted. Please reload CAPTCHA.