Tekton-Ressourcen mit ytt-Templates generieren

René Wilby | 11.04.2024 Min. Lesezeit

CI/CD mit Tekton

Tekton ist ein Open-Source-Framework zur Erstellung von CI/CD-Systemen. Mit Hilfe von Tekton können Entwickler:innen ihre Anwendungen kontinuierlich bauen, testen und deployen. Tekton kann als CI/CD-System in Kubernetes-Umgebungen zum Einsatz kommen. Auch in OpenShift kommt Tekton in Form des OpenShift Pipeline Operators zum Einsatz.

Tekton-Ressourcen

Tekton stellt verschiedene Ressourcen, wie bspw. Pipelines, Tasks, Trigger und EventListener zur Verfügung. Das Zusammenspiel dieser Ressourcen und ihre Konfiguration erfolgt über Custom Resource Definitions (CRD) für Kubernetes in Form von YAML-Dateien.

Eine minimale Tekton-Pipeline besteht i.d.R. aus einer Task-Ressource und einer Pipeline-Ressource, in der dieser Task zum Einsatz kommt. Ein einfacher Task kann dabei bspw. folgendermaßen aufgebaut sein:

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: say-hello
spec:
  params:
  - name: username
    type: string
  steps:
    - name: echo
      image: ubuntu
      script: |
        #!/bin/bash
        echo "Hello $(params.username)!"        

Eine einfache Pipeline, die diesen Task ausführt, kann folgendermaßen aussehen:

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: greeting
spec:
  params:
  - name: username
    type: string
  tasks:
    - name: say-hello
      taskRef:
        name: say-hello
      params:
      - name: username
        value: $(params.username)

Ein ausführlicher Einstieg in Tekton, seine Ressourcen und die damit verbundenen Konzepte findet man in der offiziellen Dokumentation.

Wiederverwendbarkeit von Ressourcen

Bestimmte Tekton-Ressourcen, wie bspw. Tasks sind darauf ausgelegt, dass man sie leicht wiederverwenden kann, bspw. in mehreren Pipeline-Ressourcen. Dennoch entsteht in größeren Projekten schnell eine große Anzahl von YAML-Dateien, die die Konfiguration der verschiedenen Ressourcen enthalten. Wenn zusätzlich zu Tasks und Pipelines auch Trigger und EventListener zum Einsatz kommen, verstärkt sich dieses Problem. Für jedes neue Projekt bzw. jede neue Anwendung, die in das CI/CD-System auf Basis von Tekton aufgenommen werden soll, müssen dann eine Vielzahl neuer YAML-Dateien erstellt und angepasst werden. Diese Aufgabe kann man per Copy-Paste-Modify, mit Hilfe von Merge-Strategien auf Basis von kustomize oder über einen einfachen Templating-Mechanismus realisieren.

YAML-Templating mit ytt

Meiner Erfahrung nach ähneln sich die verwendeten YAML-Dateien für bestimmte Tekton-Ressourcen innerhalb eines Teams oder Projektes inhaltlich schnell sehr stark. So bestehen Pipelines für gleichartige Anwendungen i.d.R. aus einer ähnlichen Abfolge von Tasks. Daher eignen sich diese Ressourcen sehr gut, um sie auf Basis eines Templates zu generieren. ytt ist ein einfaches Command-Line-Tool zur Generierung von YAML-Dateien auf Basis von Templates. Es unterstützt dabei u.a. die Verwendung von Platzhaltern. Die Installation von ytt ist in der Dokumentation beschrieben.

Templates für Tekton-Ressourcen

Der Einsatz von ytt in Verbindung mit Tekton soll exemplarisch anhand einer Pipeline-Ressource gezeigt werden. Die folgende Pipeline-Ressource enthält den Task git-clone.

apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: pipeline-project-a
spec:
  params:
    - name: branch
      type: string
  tasks:
    - name: git-clone
      params:
        - name: url
          value: ssh://git@scm.acme.com/project-a.git
        - name: branch
          value: $(params.branch)
      taskRef:
        kind: Task
        name: git-clone

Es ist leicht vorstellbar, dass jede Pipeline-Ressource für jede Anwendung, die in einem Git-Repository verwaltet wird, einen solchen Task hat. Der einzige Unterschied zwischen den Pipeline-Ressourcen unterschiedlicher Anwendungen ist der konkrete Pfad zum Git-Repository. Die konkrete Pipeline-Ressource kann leicht in ein Template umgewandelt werden. Dazu werden die variablen Stellen mit ytt-spezifischen Platzhalter-Kommentaren versehen und am Anfang der Datei wird eine Import-Anweisung ergänzt, die dazu führt, dass ytt die Platzhalter mit Hilfe sog. data values aus dem @ytt:data-Modul ersetzt. Eine Template-Datei pipeline-template.yaml hätte somit folgenden Inhalt:

#@ load("@ytt:data", "data")
---
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: #@ "pipeline-" + data.values.project.name
spec:
  params:
    - name: branch
      type: string
  tasks:
    - name: git-clone
      params:
        - name: url
          value: #@ "ssh://git@scm.acme.com/" + data.values.project.name + ".git"
        - name: branch
          value: $(params.branch)
      taskRef:
        kind: Task
        name: git-clone

Die verfügbaren data values werden anhand eines Schemas definiert. Die Schema-Datei schema.yaml für das vorliegende Beispiel hat folgenden Inhalt:

#@data/values-schema
---
project:
  name: "project-name"

Der Platzhalter data.values.project.name hat als Default-Wert project-name.

Tekton-Ressourcen generieren

Mit Hilfe des Templates und des Schemas können nun neue YAML-Dateien generiert werden. Die konkreten Werte für die Platzhalter können in einer eigenen Datei, wie bspw. values.yaml definiert werden:

---
project:
  name: "project-xyz"

Der Aufruf von ytt erfolgt anschließend über die Kommandozeile:

ytt --file schema.yaml --file pipeline-template.yaml --data-values-file values.yaml --output-files ./generated --file-mark "pipeline-template.yaml:path=pipeline/pipeline-xyz.yaml"

Das Ergebnis dieses Aufrufs ist eine konkrete Pipeline-Ressource für project-xyz im Verzeichnis ./generated/pipeline mit dem Dateinamen pipeline-xyz.yaml.

Zusammenspiel mit kustomize

Wenn kustomize in Verbindung mit Kubernetes zum Einsatz kommt, müssen die erzeugen Dateien in entsprechende kustomization.yaml Dateien eingetragen werden. Dies kann mit Hilfe von yq automatisiert werden. yq ist ebenfalls ein Command-Line-Tool und kann verwendet werden, um YAML-Dateien zu manipulieren. Eine neu erzeugte Datei pipeline-xyz.yaml kann mit folgendem Aufruf in die resources-Liste einer kustomization.yaml aufgenommen werden.

yq --inplace '.resources += "pipeline-xyz.yaml"' ./kustomization.yaml

Sowohl ytt als auch yq können sehr einfach ein einem Bash-Skript kombiniert werden, so dass unkompliziert Skripte erstellt werden können, die diese Art von wiederkehrende Aufgaben automatisieren können und dabei helfen Fehler zu vermeiden, wie sie bspw. beim Copy-Paste-Modify-Ansatz schnell auftreten können.

Fazit

Mit Hilfe von Tekton können CI/CD-Systeme in Kubernetes- bzw. OpenShift-Umgebungen erstellt werden. Die verfügbaren CRDs ermöglichen u.a. die Implementierung flexibler Pipelines. Die Konfiguration über YAML-Dateien ist im Kubernetes-Umfeld bekannt, führt aber bei vielen Anwendungen und vielen Pipelines schnell zu einer Vielzahl an Dateien. Der initiale manuelle Aufwand, um bspw. eine Pipeline für eine neue Anwendung zu erstellen, kann über den gezeigten Templating-Mechanismus mit yyt verringert werden. Kommen weitere Tekton-Komponenten, wie Trigger oder EventListener zum Einsatz steigt die Anzahl der YAML-Dateien und der Einsatz von Templates lohnt sich um so mehr.