Skip to content

Instantly share code, notes, and snippets.

@marcopaga
Created November 20, 2021 06:23
Show Gist options
  • Save marcopaga/6940fd1f84c463e77a4de36812cad523 to your computer and use it in GitHub Desktop.
Save marcopaga/6940fd1f84c463e77a4de36812cad523 to your computer and use it in GitHub Desktop.

Tekton Cloud Native CI/CD

Tekton ist laut eigener Homepage ein Framework um Cloud Native CI / CD - Systeme zu bauen und ein Ziel ist es das Tooling für CI / CD - Systeme zu standardisieren. So hat es schon Einzug in Jenkins X gehalten und ist die Basis für RedHat OpenShift Pipelines1. Das Tekton-Projekt nutzt Kubernetes als Platform und stellt im Kern die Building Blocks einer CI Pipeline in Form von CRDs dar. Eine Custom Resource Definition kurz CRD ist ein selbst erstelltes Kubernetes Objekt welches genutzt werden kann um eigene Objekte innerhalb der Kubernetes API sichtbar und nutzbar zu machen. So finden sich in Tekton Objekte wie z. B. eine Pipeline welche ebendiese abbildet und durchTasks, welche die einzelnen Prozessschritte ausführen, ausgestaltet werden können. Die gesamte Konfiguration findet dann wie von Kubernetes gewohnt über Manifeste statt. Das vorhandene Kubernetes Know-How kommt hier voll zum Zuge, denn neben der Konfiguration kann auch eine Introspektion der Prozesse über diesen Weg stattfinden. Als zentrale Anlaufstelle für durch die Community gepflegte Tasks und Pipelines wird der Tekton Hub2 angeboten. Dort zu finden sind schon viele Bausteine, um die üblichsten Schritte abzudecken. Zusätzlich zu dem öffentlichen Hub ist es sehr einfach möglich innerhalb der eigenen Organisation einmal spezifische Lösungen zu implementieren und zuverlässig zu verteilen. Neben den Manifesten liefert Tekton natürlich auch die Kubernetes Operatoren, welche die konfigurierten Arbeitsschritte ausführen. Wie bei modernen CI Systemen üblich werden die Build-Schritte innerhalb von Containern ausgeführt.

Eine beispielhafte CI Pipeline

Für das folgende Beispiel benötigen wir ein grobes Verständnis des CI Tools, daher stelle ich die Hauptbestandteile vor mit denen ein „Hello, World!“ - Beispiel aufgebaut wird.

Ein Task besteht aus einer Serie von Steps die der Reihenfolge nach ausgeführt werden. Ein Step ist ein in sich abgeschlossenes Kommando, welches im folgenden Beispiel Names hello , der Aufruf von echo "Hello World!" ist. Dies wird in einem Ubuntu Container gestartet und ausgeführt, was natürlich auch nach Gusto geändert werden kann. Im realen Einssatz finden sich an dieser Stelle Kommandos, die einen checkout vornehmen, Images bauen und vieles mehr.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: hello
spec:
  steps:
    - name: hello
      image: ubuntu
      command:
        - echo
      args:
        - "Hello, world!"

Ebenfalls ist ein goodbye Task angelegt, welcher sich durch ein echo Kommando auf der Systemconsole verabschiedet. In diesem kleinen Beispiel werden wir eine Pipeline erzeugen, welche die beiden Tasks nacheinander aufruft damit bei Betrachtung der Pipeline - Logs sowohl die Begrüßung als auch die Verabschiedung anzeigt. Sehr intuitiv – wie ich jedenfalls finde - erstellen wir ein CRD vom Typ Pipeline und definieren dort eine Liste von Tasks, welche mit Abhängigkeiten untereinander versehen werden können. In diesem einfachen Beispiel geben wir über runAfteran, dass die Verabschiedung nach der Begrüßung stattfinden soll.

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: hello-goodbye-pipeline
spec:
  tasks:
    - name: hello
      taskRef:
        name: hello
    - name: goodbye
      runAfter:
        - hello
      taskRef:
        name: goodbye

Das obig definierte Task wird über eine taskRefverlinkt, sodass die definierten Tasks darüber verknüpft werden und die Pipeline die zwei Schritte durchläuft.

Interaktion mit Tekton

Wie zu Beginn dargestellt arbeitet Tekton über die Konfiguration und Installation von CRDs. Diese API Objekte können direkt über kubectlabgerufen und manipuliert werden, worüber eine nachvollziehbare API abgebildet wird. Installierte Pipelines können problemlos abgerufen werden: # kubectl get pipelines.tekton.dev --all-namespaces -o wide NAMESPACE NAME AGE 8 tekton-pipelines hello-goodbye-pipeline 1s 9 Weiterhin ist es natürlich auch möglich eine Pipeline zu starten. In dem Repository ist ein PipelineRunzu finden den ich im folgenden einmal darstelle: apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: generateName: hello-goodbye-pipeline- spec: pipelineRef: name: hello-goodbye-pipeline Die Konfiguration stellt ein Präfix für die erstellten Runs zur Verfügung über dasgenerateNameAttribut. Ebenfalls wird eine Referenz zu der zu verwendeten Pipeline vergeben, welche wir während der Installation erzeugt haben und uns im Verlauf dieses Artikels angeschaut haben. Wie kann eine Pipeline gestartet werden? Jetzt brauchen wir doch noch ein weiteres API Objekt und zwar den PipelineRun. Dieses Objekt bringt die notwendigen Parameter - in unserem Fall noch keine - in Verbindung mit der auszuführenden Pipeline. Als Nutzer können wir durch Referenz auf den erzeugten Run den Status und auch die Log-Ausgabe abrufen. Los geht’s: kubectl create -n tekton-pipelines -f ./hello-goodbye-pipeline-run.yaml Und wie schon angedeutet rufen wir alle Ausführungen ab: kubectl get pipelineruns.tekton.dev --all-namespaces -o wide NAMESPACE NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME 8 tekton-pipelines hello-goodbye-pipeline-v5h5l True Succeeded 13s 1s Hier erkennbar sind die vorhandenen Statusfelder dieses Objekts. Für das Black-Box-Testing können wir daher auf den Statuswechsel des PipelineRuns auf Succeededwarten, um den Durchlauf einer Pipeline zu erkennen. Die Ausführung einer Pipeline kann aus verschiedensten Gründen in der Zeit variieren. Eine Möglichkeit damit umzugehen ist eine feste Zeitspanne innerhalb der Pipeline zu pausieren und nach Erreichen dieser Zeit das Ergebnis zu prüfen. In der Praxis ist dies nicht optimal, da neben zu langen Wartezeiten ebenfalls Fehlschläge der Pipeline auftreten, welche nicht notwendig sind. Das Kubernetes API Tooling bietet dafür eine elegante Lösung, welche ich gerne anhand eines Beispiels zeigen möchte. Für den oben dargestellten Fall können wir über kubectl -n tekton-pipelines wait --for=condition=SUCCEEDED=True --timeout=60s pipelineruns.tekton.dev/$PIPELINE_RUN_NAME auf das Eintreten des Zustands SUCCEEDED=True mit einem maximalen Timeout von 60 Sekunden warten. Der Timeout ist mit 1 Minute sehr groß gewählt, da dieser nur im Fehlerfall erreicht werden soll. In der Praxis wird nicht so lange gewartet. Nach Ablaufen dieses maximalen Timeouts können wir dann den Zustand der Pipeline abfragen. Die Alternative zu diesem effizienten Wait auf den Status ist ein statischer langer Sleep auf der Kommandozeile. Hierdurch werden die Tests zum einen sehr langsam und können auch oft grundlos fehlschlagen wenn die Verarbeitung aus anderen Gründen stockt.

Zusammenfassend ist es für den weiteren Verlauf wichtig zu wissen, dass der Status der Ausführung über die Kubernetes API abgerufen werden kann. Um ein stabiles Test-Setup zu erzeugen ist es wichtig mit Time-Outs auf Statusänderungen zu reagieren und Verifikationen vorzunehmen.

Neben der direkten Interaktion mit kubectl bietet Tekton ein spezialisiertes Command Line Interface (CLI) welches direkt über den aktuell genutzte Kubernetes Context mit dem Cluster interagiert. Viele Kubernetes basierten Tools bringen ein passendes CLI mit, um effizient mit der Platform zu arbeiten. tkn ist das entsprechende go Binary was problemlos auf verschiedenen Plattformen lauffähig ist. Eine Installationsanleitung ist über das GitHub Repository 3zu finden. Mit diesem CLI ist es dann einfacher möglich z. B. die Tasks und Pipelines abzurufen. Hier ein kurzes Beispiel: tkn task list --all-namespaces tkn pipeline list --all-namespaces Diese beiden Aufrufe zeigen alle vorhandenen Tasks und Pipelines in allen Namespaces an. Die Inspektion der Logs erfolgt über dieses Kommando: tkn pr logs $PIPELINE_RUN_NAME Die Ausgabe aller Tasks wird hier gesammelt und nachvollziehbar ausgegeben.

Footnotes

  1. https://cloud.redhat.com/learn/topics/ci-cd

  2. https://hub.tekton.dev/

  3. https://github.com/tektoncd/cli

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment