Tekton Triggers in der Praxis

Keine Kommentare

Tekton Triggers in der Praxis

Dieser Artikel ist Teil einer Reihe, die sich mit Tekton CI/CD und dem praktischen Einsatz beschäftigt.

Im ersten Artikel haben wir die Installation vorgenommen und die erste Pipeline erstellt. Im zweiten Artikel haben wir die Vorteile von Tekton durch den geschickten Einsatz der wiederverwendbaren Komponenten erleben können. Dieser Artikel beschäftigt sich mit der Einbettung von Tekton in einen Projektkontext. Das Ziel für diesen Artikel ist erstmal die Grundlagen dafür zu schaffen. Wir werden mit Tekton Triggers ein WebHook Interface öffnen und ein Gitlab-WebHook-JSON-Objekt schicken, das einen Build in der Tekton-Installation startet.

Möglicher Einsatz

Was meine ich an der Stelle mit einem „Projektkontext“? Bisher haben wir Tekton in einem isolierten Setup laufen lassen, was in der Praxis nicht hilfreich ist, denn damit geht die Sichtbarkeit auf die eigene Arbeit schnell verloren. Die Gesamtsicht ist über mindestens zwei Systeme verteilt, welche untereinander nicht verknüpft sind. Schlimmer sogar, die Tekton muss bisher manuell gestartet werden.

Warum nicht einfach das Integrierte nutzen?

Der Trend bei den großen Plattformen wie GitHub oder Gitlab ist die Integration der Entwicklungstools. Angefangen vom Git Repository über eine Pipeline-Lösung wie GitHub Actions, über das Container Repository bis hin zur Integration der Organisationstools. Der dahinterstehende Grund dabei ist die Transparenz zu erhöhen.

Dem entgegen steht die Nutzung von Tekton für den Aspekt der CI/CD-Ausführung. Sinn ergibt das, wenn der Wunsch der Compliance, Wiederverwendbarkeit und vermeintlicher Zukunftsfähigkeit steigt. Die richtungsweisende Vision ist die API-Kompatibilität in die Breite zu tragen und ein nachhaltiges Öko-System aufzubauen. Dies ist natürlich erstmal der Beginn einer Reise und es bleibt abzuwarten, ob dies realistisch ist. Bei Entscheidungen die das CI/CD-System betreffen ist die Zukunftsfähigkeit aus meiner Sicht ein interessantes Kriterium.

Schreibt gerne eure Meinung in die Kommentare oder gebt gerne per Twitter Feedback.

Triggers Installation

Tekton Triggers sind eine weitere Komponente, die im Cluster installiert sein muss. Hierzu können wir der Installationsanleitung im GitHub – Projekt folgend die notwendigen Manifeste einspielen. Im Kapitel „Setting Up Tekton Triggers“ findet man die beiden Dateien, welche über das Tool der Wahl eingespielt werden können.

Die Datei mit dem Namen release.yaml beinhaltet die gesamte Triggers-Basisinstallation und die interceptors.yaml-Datei bringt Interceptoren für die einfache Anbindung von Systemen wie gitlab, github oder bitbucket mit. Diese sollten ebenfalls installiert werden, denn wir werden einen installierten ClusterInterceptor später noch benutzen. Im nächsten Abschnitt beschreibe ich, welchen Zweck diese haben.

An dieser Stelle der kurze Hinweis, dass die Tekton-Installation inklusive der Tekton Triggers in meinem GitHub Projekt fertig aufgebaut ist. Einfach klonen und testen. Alles Wichtige ist in der README.md oder auch in der github Action zu finden, die den Code bei jedem Push testet. Mehr zu diesem Projekt ist im Softwerker Vol. 19 zu finden, denn dort beschreibe ich das gesamte Projekt in der Tiefe und zeige die Zusammenhänge auf.

Triggers-API-Objekte

Die Triggers API sieht auf den ersten Blick sehr kompliziert aus, jedenfalls ist es mir so gegangen. Am besten wir gehen Schritt für Schritt durch und verstehen, wofür das jeweilige Objekt genutzt wird. Hier meine kurze Remarkable-Notiz die mir bei der Orientierung sehr geholfen hat:

EventListener

Unser Ziel ist einen WebHook von außen zu empfangen. Auf Seite von Kubernetes bedeutet dies, dass ein Service einen TCP-Port zur Verfügung stellt, der dafür genutzt werden kann. Als Anker wird der EventListener genutzt und mit den weiteren Objekten verknüpft. Neben dem zu verwendenden ServiceAccount werden an dieser Stelle die Trigger angehängt. Hinter einem EventListener können beliebig viele Trigger auf unterschiedliche Anfragen lauschen.

Durch Erstellung des EventListeners wird automatisch der beschriebene Service erstellt. Nur kurz zur Einordnung: Dieser Service ist nur im Cluster verfügbar und kann je nach Use Case z. B. durch ein Ingress für andere Applikationen außerhalb des Clusters sichtbar gemacht werden.

Trigger

Die Aufgabe des Triggers ist darauf aufbauend die Anfragen zuzuordnen und durch die Verwendung von Interceptoren, TriggerBindings und TriggerTemplates zu verarbeiten. Der Trigger hat einen Namen und alles weitere wird in den genutzten Objekten verwendet.

Interceptor

WebHooks werden häufig durch bestimmte Systeme aufgerufen. Im Falle von Tekton sind dies Git Repositories wie z. B. Gitlab oder Github. Die Formate des Aufrufs und die genutzten Sicherheitsmechanismen unterscheiden sich zwischen den Systemen.

Ein WebHook von Github wird z. B. mit einem HMAC des Payloads und mithilfe eines geheimen Strings abgesichert, wohingegen durch Gitlab ein X-Gitlab-Token HTTP Header mit einem Secret hinzugefügt wird.

Wir können den passenden Interceptor nutzen, das notwendige Secret und den Event-Type definieren.

TriggerBinding

Mit diesem Binding greifen wir auf den JSON Body der Anfrage zu und extrahieren die notwendigen Informationen, wie z. B. die URL des git repositories und den Branch-Namen.

Die extrahierten Werte sind dann als Parameter verwendbar und können im letzten Objekt verwendet werden.

TriggerTemplate

An dieser Stelle wird jetzt der eigentlich Aufruf vorgenommen, und zwar werden hier die extrahierten Parameter referenziert und einem Template, z. B. einem PipelineRun, zur Verfügung gestellt. Der PipelineRun wird bei einem WebHook-Aufruf gestartet und das Wissen aus den ersten Artikeln greift hier wieder.

Praktische Umsetzung im Sample Projekt

Hier das komplette Beispiel aus dem Demo-Projekt, welches die angesprochenen Objekte nutzt:

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: gitlab-listener
spec:
  serviceAccountName: tekton-triggers-gitlab-sa
  triggers:
    - name: gitlab-push-events-trigger
      interceptors:
        - name: "verify-gitlab-payload"
          ref:
            name: "gitlab"
            kind: ClusterInterceptor
          params:
            - name: secretRef
              value:
                secretName: "gitlab-secret"
                secretKey: "secretToken"
            - name: eventTypes
              value:
                - "Push Hook"
      bindings:
        - name: git-revision
          value: $(body.checkout_sha)
        - name: git-repository-url
          value: $(body.repository.git_http_url)
      template:
        spec:
          params:
            - name: git-revision
            - name: git-repository-url
          resourcetemplates:
            - apiVersion: tekton.dev/v1beta1
              kind: PipelineRun
              metadata:
                generateName: show-parameter-triggered-pipeline-
              spec:
                pipelineRef:
                  name: show-parameter-pipeline
                params:
                  - name: image
                    value: test-image-build-by-buildpack-and-triggered:latest
                  - name: git-repository-url
                    value: $(tt.params.git-repository-url)
                  - name: git-revision
                    value: $(tt.params.git-revision)

In dem Beispiel-Projekt wird der Aufruf durch eine Gitlab-Instanz durch einen curl simuliert. Der Aufruf enthält, wie bei den Interceptoren beschrieben, das notwendige Secret und die eigentlichen Daten des Aufrufs.

curl -v \
-H 'X-GitLab-Token: 1234567' \
-H 'X-Gitlab-Event: Push Hook' \
-H 'Content-Type: application/json' \
--data-binary "@gitlab-push-event.json" \
http://localhost:8081

In diesem kurzen Ausschnitt möchte ich beschreiben, wie eine Zuordnung zum Aufruf stattfinden kann, denn auf der einen Seite ist dieser Aufruf ein Fire-and-Forget-Lösung, doch auf der anderen Seite kann es notwendig sein, im Rahmen einer Fehlersuche die Verarbeitung nachzuvollziehen. Möglich ist dies, weil Tekton Triggers ein JSON-Objekt zurückliefert, welches eine Event-ID definiert. Diese Event-ID wird als Label an den PipelineRun weitergegeben, der dann darüber identifiziert werden kann. Im folgenden Snippet ist dies in der Praxis dargestellt und komplett hier zu finden.

    EVENT_ID=$(./trigger-tekton.sh | jq -r '.eventID')
    echo "EVENT-ID found in the response of the web-hook call${EVENT_ID}"
    # Wait for the triggered PipelineRun to complete
    kubectl -n tekton-pipelines wait --for=condition=SUCCEEDED=True --timeout=60s pipelineruns.tekton.dev -l triggers.tekton.dev/triggers-eventid==$EVENT_ID

Zusammenfassung und Ausblick

Dieser Artikel zeigt anhand eines praktischen Beispiels, wie Tekton in eine vorhandene Umgebung eingebunden und genutzt werden kann. An dieser Stelle haben wir ein CI-System aufgebaut, das automatisch Pipelines startet wenn ein Push stattgefunden hat.

Wie geht die Serie weiter? Wie angekündigt wird ein Post folgen, der die Integration mit Gitlab praktisch darstellt – und zwar auf Basis eines AWS EKS Clusters. Was danach kommt ist noch offen: Möglich wäre es z. B., einen eigenen Task zu entwickeln und zur Verfügung zu stellen oder auch in die Richtung der Supply Chain Security abzubiegen.

Wenn ihr Fragen oder Anmerkungen zu dem Post habt, freue ich mich über Rückmeldungen von euch hier auf dem Blog, per E-Mail oder gerne auf Twitter.

Marco entwickelt Software aus Leidenschaft. Gerne arbeitet er im Team an der Lösung komplexer Probleme.
In der Vergangenheit hat er dabei erfolgreich Legacy-Applikationen modernisiert, um diese auf geänderte Herausforderungen vorzubereiten. Alle Beteiligten auf diesem Weg mitzunehmen und für neue Technologien zu begeistern – das ist für ihn selbstverständlich.

Über 1.000 Abonnenten sind up to date!

Die neuesten Tipps, Tricks, Tools und Technologien.
Jede Woche direkt in deine Inbox.

Kostenfrei anmelden und immer auf dem neuesten Stand bleiben!
(Keine Sorge, du kannst dich jederzeit abmelden.)

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht.