Anzeige
Anzeige
How-To

Besser entwickeln mit Devops-Praktiken: Continuous Delivery mit Kubernetes

In der Software-Industrie sind die Reaktionsfähigkeit auf neue Markt­anforderungen und kurze Produkteinführungszeiten entscheidende ­Wett­­­­b­ewerbs­faktoren. Viele Entwicklungs­teams führen daher Devops-Praktiken wie etwa ­Continuous Delivery ein und nutzen aktuelle Technologien wie Kubernetes als unterstützende ­Werkzeuge.

Von Martin Helmich
6 Min.
Artikel merken
Anzeige
Anzeige

(Grafik: Irina Strelnikova/ Shutterstock)

Der Begriff Continuous Delivery beschreibt den Wechsel von ­konstanten Release-Zyklen („neue Versionen werden immer zum Quartalsende veröffentlicht“) hin zu einem kontinuierlichen Ausrollen neuer Versionen einer Software. Damit Continuous Delivery in der Praxis funktioniert, müssen mehrere Voraus­setzungen erfüllt sein: Zum einen benötigt das Entwicklungsteam einen gewissen Spielraum, in dem es selbstständig und eigenverantwortlich agieren kann; Abhängigkeiten von anderen Teams oder Abteilungen sollten möglichst vermieden werden. Viele Teams greifen zu einer Devops-­Organisationsstruktur, in der die (ansonsten oft klaren) Grenzen zwischen Entwicklung (Development) und Betrieb (Operations) verschwimmen – etwa in Form von Entwicklern, die gleichzeitig auch für den operativen Betrieb ihrer Applikationen verantwortlich sind.

Anzeige
Anzeige

Zum anderen benötigt es einen schnellen, wiederholbaren und gut automatisierbaren Prozess zur Auslieferung und zum Betrieb der Software. Diese Anforderungen werden von aktuellen Technologien wie Docker und Kubernetes gut bedient, die Devops-Teams passende (und gut automatisierbare) Werkzeuge zum Bauen, Ausliefern und Betreiben von Applikationen an die Hand geben. Wie das mit Kubernetes gelingen kann, zeigen wir euch im Folgenden.

Deployment nach Kubernetes

Am Anfang jeden Deployments steht zunächst das Erstellen eines Container-Images, das beispielsweise mithilfe eines ­Dockerfiles und dem Befehl docker build erstellt werden kann (im Folgenden nehmen wir das Image your-app:v1.2.3 als Beispiel an).

Anzeige
Anzeige

Zum Starten einer Applikation auf Kubernetes kann am besten ein Deployment-Objekt benutzt werden. Dieses wird in Form einer YAML-Datei definiert, die wie folgt aussehen könnte:

Anzeige
Anzeige
apiVersion: apps/v1
kind: Deployment
metadata:
  name: your-application
spec:
  replicas: 4
  template:
    containers:
    - name: app
      image: "your-app:v1.2.3"
      ports:
      - containerPort: 8080
        name: http

Das Deployment kann mit dem Befehl kubectl apply erstellt werden. In diesem Fall startet Kubernetes vier „Replicas“ des angegebenen (und zuvor gebauten) Container-Images:

> kubectl apply -f your-deployment.yaml

Die gestarteten Instanzen (Pods) können im Anschluss mit dem Befehl kubectl get pods abgefragt werden:

Anzeige
Anzeige
> kubectl get pods
NAME                    READY  STATUS   RESTARTS  AGE
my-app-351368469-brjcd  1/1    Running  0         1m
my-app-351368469-nrzxh  1/1    Running  0         1m
my-app-351368469-owkfz  1/1    Running  0         1m
my-app-351368469-bhaz6  1/1    Running  0         1m

Zukünftige Versionen der Software können nun als jeweils neues Image veröffentlicht werden. Um eine neue Version zu releasen, kann das Deployment über den folgenden Befehl bearbeitet werden:

> kubectl set image deployment/your-application app=your-app:v1.2.4
deployment.apps/your-application image updated

Kubernetes führt in diesem Fall ein Rolling Update der ­Applikation aus. Das bedeutet, dass die Container mit der ­vorherigen Version des Images einer nach dem anderen heruntergefahren werden. Für jeden gestoppten Container der Vorversion wird ein ­neuer Container mit der neuen Version gestartet. Auf diese Weise werden alle laufenden Instanzen der Applikation nach und nach ausgetauscht. Die Applikation als Ganzes bleibt dabei erreichbar. Allerdings muss berücksichtigt werden, dass für einen kurzen Zeitraum zwei Versionen parallel laufen. Sollte die neue Version der Software nicht so laufen wie gewünscht, kann das Ganze über den kubectl rollout undo-Befehl wieder rückgängig gemacht werden:

> kubectl rollout undo deployment/your-application

Der Helm-Paketmanager

Die Methode, Deployments über den kubectl set image-Befehl zu aktualisieren, funktioniert in vielen einfachen Fällen, stößt ­jedoch schnell an ihre Grenzen. Häufig besteht eine auf ­Kubernetes betriebene Applikation nicht nur aus einem Deployment-Objekt, sondern aus zahlreichen weiteren Objekten (beispielsweise aus Service- und Ingress-Objekten, die definieren, wie eingehender Traffic die Applikation erreicht oder Configmap- und Secret-Ressourcen, die Konfigurationsdaten für die Applikation beinhalten). Änderungen an solchen Ressourcen können in einer Deployment-­Pipeline über den obigen kubectl set image-Befehl nicht abgebildet werden.

Anzeige
Anzeige

Hier kommt jetzt Helm ins Spiel: Konzipiert als Paket­manager für ­Kubernetes, verwaltet Helm Definitionen für komplexe Kubernetes-­Deployments, die aus zahlreichen verschiedenen Objekten bestehen können. Bei Helm heißen diese Definitionen Charts. Ein Helm-Chart kann zahlreiche verschiedene ­Kubernetes-Objekte definieren (beispielsweise ein Deployment und dazugehörige Services, Ingress-­Definitionen und auch andere).

Die Skizze zeigt eine typische ­Deployment-Pipeline für ein ­Go-Projekt. Der Vorteil: Die hochperformante Auslieferung bei gleichzeitig ständiger Beobachtung aller Applikationsbestandteile. (Grafik: t3n)

Die Skizze zeigt eine typische ­Deployment-Pipeline für ein ­Go-Projekt. Der Vorteil: Die hochperformante Auslieferung bei gleichzeitig ständiger Beobachtung aller Applikationsbestandteile. (Grafik: t3n)

Helm besteht aus einem Client, der auf eurem lokalen Rechner (oder eurer CI-Umgebung) laufen muss, sowie einem Server (genannt Tiller), der innerhalb des Kubernetes-Clusters laufen muss. Charts können aus einem (oder mehreren) zentralen Repositories oder aus dem lokalen Dateisystem geladen werden. Der Helm-Server kann in einem bestehenden Kubernetes-Cluster über den Befehl helm init ­installiert werden.

Helm-Charts erstellen

Für das kontinuierliche Deployment eigener Applikationen ist es ratsam, das Helm-Chart einer Applikation zusammen mit der ­Applikation selbst in demselben Git-Repository zu verwalten. Mit folgendem Befehl kann ein neues Helm-Chart erstellt werden:

Anzeige
Anzeige
> helm create charts/my-app
Creating charts/my-app

Jedes Helm-Chart besteht aus einem Satz an Templates, dabei handelt es sich um Vorlagen für Kubernetes-Objekte, die später bei der Installation eines Charts von Helm erstellt werden. Jedes Template enthält Platzhalter für bestimmte Werte. Das Template für ein Deployment könnte beispielsweise folgendermaßen aussehen:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ template "my-app.fullname" . }}
  labels:
    app: {{ template "my-app.name" . }}
    chart: {{ template "my-app.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ template "my-app.name" . }}
      release: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ template "my-app.name" . }}
        release: {{ .Release.Name }}
      spec:
        containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          ports:
            - name: http
              containerPort: 8080

Bei der verwendeten Template-Sprache handelt es sich um die Standard-Template-Sprache von Go, die in der offiziellen Dokumentation „go-template“ näher beschrieben ist.
Zusätzlich zu den Templates enthält jedes Helm-Chart eine yalues.yml-Datei. Diese enthält Werte, die dann anschließend in den Templates genutzt werden können (beispielsweise oben in Form der .Values.replicaCount-Variable). Ein bestehendes Helm-Chart kann anschließend mit dem Befehl helm install in einem Kubernetes-Cluster installiert ­werden:

> helm install --set image.tag=v1.2.3 --name my-app ./charts/my-app

Über das --set-Argument können bei der Installation einzelne Werte aus der values.yml überschrieben werden. Indem der image.tag-Wert überschrieben wird, kann beispielsweise eine ganz bestimmte Version einer Applikation installiert werden.

Anzeige
Anzeige

Ist ein Chart bereits installiert, kann die bestehende Installation über den helm upgrade-Befehl aktualisiert werden. Dieser Befehl kann auch beispielsweise genutzt werden, um bestimmte Werte zu aktualisieren:

> helm upgrade --install --set image.tag=v1.2.4 my-app ./charts/my-app

Hier wurde beispielsweise die Version des Container-Images geändert. Der helm upgrade-Befehl würde nun dafür sorgen, dass sämtliche im Chart definierten Ressourcen auf den gewünschten Stand aktualisiert werden. Das Deployment würde zudem auf die Image-Version v1.2.4 aktualisiert und ­Kubernetes würde (ähnlich wie beim kubectl set image-Befehl) ein Rolling Update des Deployments starten.

Das --install-Argument in dem obigen Befehl sorgt übrigens dafür, dass das Chart installiert wird, falls dies noch nicht der Fall ist. Dadurch kann man sich auch den initialen helm install-Befehl bequemerweise sparen. Und natürlich gibt es auch einen helm rollback-Befehl, mit dem im Fehlerfall schnell zum vorherigen Release zurückgewechselt werden kann.

Anzeige
Anzeige

Integration mit einem CI-Tool nach Wahl

Mithilfe von Helm reicht mit helm upgrade nun ein einziger ­Befehl, um eine auf Kubernetes betriebene Applikation auf den im Quelltext-Repository definierten Stand zu bringen. Um diesen Prozess völlig zu automatisieren, bietet sich nun eine Integration in die üblichen Continuous-Integration-Lösungen an, sodass beispielsweise beim Erstellen eines neuen Git-Tags auch gleich das dazugehörige Deployment aktualisiert wird.

CI-Lösungen gibt es viele, stellvertretend soll an dieser ­Stelle die Gitlab CI als Beispiel dienen. Ein Job, der eine Applikation per Helm-Chart installiert, könnte in Gitlab CI wie folgt aussehen:

dockerbuild:
  stage: build
  image: docker
  script:
  - "docker build -t my-app:${CI_COMMIT_TAG} ."
  - "docker push my-app:${CI_COMMIT_TAG}"
  only: [tags]
deploy:
  stage: deploy
  image: quay.io/martinhelmich/k8s-deployer:v1.1.0
  environment: development
  script:
  - >
    helm upgrade --install
      --set image.tag=${CI_COMMIT_TAG}
      ${CI_PROJECT_NAME} ./charts/my-app
only: [tags]

Wichtig ist hier insbesondere die Variable ${CI_COMMIT_TAG}: Wird ein Git-Tag in das Repository gepushed (­beispielsweise v1.2.5), enthält diese Variable den Namen des Tags. Im ­dockerbuild-Job wird dabei zunächst ein Docker-Image ­dieses Namens gebaut. Anschließend wird das gebaute Image im ­deploy-Build über den schon vorgestellten helm upgrade-­Befehl installiert.

Anzeige
Anzeige

Der Vorteil dieses Ansatzes ist, dass jedes Helm-Chart mehrfach in einem Cluster installiert werden kann. Das ist ­insbesondere in Entwicklungsumgebungen nützlich. Hier kann ­beispielsweise jeder Git-Branch (beispielsweise für Pull Requests) einzeln deployed werden:

deploy:
  stage: deploy
  image: quay.io/martinhelmich/k8s-deployer:v1.0.0
  environment:
    name: review/$CI_COMMIT_REF_NAME
    url: https://$CI_ENVIRONMENT_SLUG.your-app.example
  script:
  - >
    helm upgrade --install
     --set image.tag=${CI_COMMIT_TAG}
     ${CI_PROJECT_NAME}-${CI_ENVIRONMENT_SLUG} .
     /charts/my-app

Das Beispiel nutzt die Review-Apps-Funktionalität von Gitlab, um für jeden Pull Request einer Applikation ein eigenes Release des hinterlegten Helm-Charts zu erstellen.

Fazit

Die gezeigte Kombination aus Tools ermöglicht die ­Konstruktion recht komplexer und durchaus praxistauglicher Deployment-­Pipelines. Natürlich ist hier noch längst nicht Schluss. Beispielsweise lassen sich mit Kubernetes und Helm auch komplexere Deployments wie beispielsweise ein Blue/Green-Deployment umsetzen. Weitere Möglichkeiten eröffnen sich durch den Einsatz von ­Service Meshes wie beispielsweise Istio. Diese unterstützen ­unter anderem Canary Releases, bei denen zunächst nur ein geringer Teil des Traffics an ein neues Release der Anwendung geleitet wird. Generell ermöglichen solche Meshes auch eine hohe ­Observability, sodass Fehler, die sich durch ein neues Release eingeschlichen haben, schnell gefunden werden können.

Mehr zu diesem Thema
Fast fertig!

Bitte klicke auf den Link in der Bestätigungsmail, um deine Anmeldung abzuschließen.

Du willst noch weitere Infos zum Newsletter? Jetzt mehr erfahren

Anzeige
Anzeige
Schreib den ersten Kommentar!
Bitte beachte unsere Community-Richtlinien

Wir freuen uns über kontroverse Diskussionen, die gerne auch mal hitzig geführt werden dürfen. Beleidigende, grob anstößige, rassistische und strafrechtlich relevante Äußerungen und Beiträge tolerieren wir nicht. Bitte achte darauf, dass du keine Texte veröffentlichst, für die du keine ausdrückliche Erlaubnis des Urhebers hast. Ebenfalls nicht erlaubt ist der Missbrauch der Webangebote unter t3n.de als Werbeplattform. Die Nennung von Produktnamen, Herstellern, Dienstleistern und Websites ist nur dann zulässig, wenn damit nicht vorrangig der Zweck der Werbung verfolgt wird. Wir behalten uns vor, Beiträge, die diese Regeln verletzen, zu löschen und Accounts zeitweilig oder auf Dauer zu sperren.

Trotz all dieser notwendigen Regeln: Diskutiere kontrovers, sage anderen deine Meinung, trage mit weiterführenden Informationen zum Wissensaustausch bei, aber bleibe dabei fair und respektiere die Meinung anderer. Wir wünschen Dir viel Spaß mit den Webangeboten von t3n und freuen uns auf spannende Beiträge.

Dein t3n-Team

Melde dich mit deinem t3n Account an oder fülle die unteren Felder aus.

Bitte schalte deinen Adblocker für t3n.de aus!
Hallo und herzlich willkommen bei t3n!

Bitte schalte deinen Adblocker für t3n.de aus, um diesen Artikel zu lesen.

Wir sind ein unabhängiger Publisher mit einem Team von mehr als 75 fantastischen Menschen, aber ohne riesigen Konzern im Rücken. Banner und ähnliche Werbemittel sind für unsere Finanzierung sehr wichtig.

Schon jetzt und im Namen der gesamten t3n-Crew: vielen Dank für deine Unterstützung! 🙌

Deine t3n-Crew

Anleitung zur Deaktivierung
Artikel merken

Bitte melde dich an, um diesen Artikel in deiner persönlichen Merkliste auf t3n zu speichern.

Jetzt registrieren und merken

Du hast schon einen t3n-Account? Hier anmelden

oder
Auf Mastodon teilen

Gib die URL deiner Mastodon-Instanz ein, um den Artikel zu teilen.

Anzeige
Anzeige