← Übersicht  ·  Skripte & Dateien  ·  cloud-host · OpenShift · CI/CD

Tekton Pipelines in OpenShift

Die Zeichnungen dazu stehen hier bei den jeweiligen Schritten. Die Bibliothek baut mit Jenkins außerhalb des Clusters (build-kette-openshift.html). Diese Anleitung probiert die Alternative aus, die der Atlas als „der OpenShift-Weg“ beschreibt: den OpenShift-Pipelines-Operator installieren, einen echten Task mit mehreren Steps schreiben, ihn über eine Pipeline und einen Workspace verketten, einen PipelineRun live beobachten – alles flüchtig, kein Server-Pod bleibt stehen. EX280-relevant.

Stand: 4. September 2026 OKD 4.x / OCP 4.x ns library

Voraussetzung: oc login als cluster-admin für Schritt 2 (Operator-Installation), danach reicht der Zugang zum Namespace library. Baut auf operator-installieren-olm.html auf – dort steht das allgemeine OLM-Verfahren.

1 Wer baut, verbraucht CPU

Baust du im Cluster, kostet jeder Build CPU und RAM, die den Diensten fehlen.

Baust du im Cluster, kostet jeder Build CPU und RAM, die deinen Diensten fehlen. Jenkins im Cluster (Master-Pod plus Agent-Pods je Build) ist der teure Weg. Der OpenShift-Weg: entweder Tekton (flüchtige Build-Pods, E2) oder CI außerhalb, die nur noch über ein ServiceAccount-Token deployt. Die Bibliothek baut außerhalb.

Wer baut, verbraucht CPU. Die Frage ist nur: im Cluster oder außerhalb? A · Jenkins im Cluster ein Master-Pod (die alte OpenShift-Jenkins-Vorlage) plus Agent-Pods je Build (Kubernetes-Plugin) jeder Build zieht Maven, kompiliert, testet – im Cluster konkurriert mit den Diensten um CPU und RAM braucht ein PVC für $JENKINS_HOME auf SNO oder dem kleinen Bibliothek-Cluster: keine gute Idee Vorteil: alles an einem Ort, ein OAuth-Login (A4) die Vorlage wird nicht mehr gepflegt – Neuanlage vermeiden B · der OpenShift-Weg Tekton (E2): Build-Pods, aber zweckgebaut und flüchtig kein Master, kein PVC – ein PipelineRun pro Lauf oder CI außerhalb: GitHub Actions, GitLab CI, Jenkins extern baut außerhalb, deployt nur über ein SA-Token in den Cluster der Cluster trägt nur die Last der Dienste, nicht der Builds Nachteil: zwei Systeme, das Token muss verwaltet werden Argo CD (E3) macht daraus reinen Pull statt Push Faustregel: baue dort, wo CPU billig ist – deploye dort, wo die App läuft Abwägung Control Plane: A belastet sie stark, B kaum Secrets: A hat alles intern, B muss ein Deploy-Token und Registry-Zugang nach außen geben Portabilität: B läuft gegen jeden Cluster gleich, A ist an diesen einen Cluster gebunden Wartung: A ein weiterer Dienst im Cluster, B ein CI-System Audit: B loggt jeden Deploy als der pipeline-SA (A6) EX280 kennt beide – der Trend geht klar zu B Bibliothek / cloud-host – der konkrete Weg Jenkins läuft außerhalb in einem lokalen docker-compose (der Hetzner-Server war weg, Jenkins kam vom Snapshot ins Shared-Infra-Compose) 1 Jenkins baut je Dienst ein Image und pusht nach ghcr.io oc login <api> --token=$PIPELINE_TOKEN 2 Jenkins ruft je Dienst helm upgrade --install catalog ./chart -n library --atomic 3 authentifiziert als system:serviceaccount:library:pipeline – gebunden an admin + system:image-builder + registry-editor (A5) der Cluster sieht nur helm upgrade-Aufrufe – keine Build-Pods, kein Jenkins-Pod, kein PVC der nächste Schritt wäre Tekton im Cluster (E2) oder Argo CD als Pull-Modell (E3) – beide ersetzen den Push von außen oder Merksatz: im Cluster bauen = Build-Last auf der Control Plane. Außerhalb bauen und nur deployen = der Cluster trägt nur die Dienste. ein Deploy von außen braucht genau eins: ein pipeline-SA-Token mit gerade den nötigen Rollen (A5) – nicht cluster-admin OCP-Unterschied: die alte Jenkins-Vorlage ist OpenShift-eigen (Templates, OAuth-Login, S2I-Jenkinsfile). Tekton kommt als OpenShift-Pipelines-Operator, ist aber Standard-Kubernetes-Tekton.
Wer baut, verbraucht CPU. Jenkins im Cluster heißt: ein Master-Pod plus Agent-Pods je Build, die mit deinen Diensten um CPU und RAM konkurrieren, plus ein PVC für $JENKINS_HOME. Der OpenShift-Weg ist Tekton (flüchtige Build-Pods) oder CI außerhalb, die nur noch über ein ServiceAccount-Token in den Cluster deployt. Die Bibliothek baut außerhalb: Jenkins (lokales compose) pusht nach ghcr.io und ruft helm upgrade --install je Dienst als system:serviceaccount:library:pipeline – der Cluster sieht keine Build-Last.
  • Jenkins im Cluster: ein Master-Pod plus Agent-Pods je Build (Kubernetes-Plugin) – jeder Build kostet Cluster-CPU, konkurriert mit den Diensten, braucht ein PVC für $JENKINS_HOME
  • die alte OpenShift-Jenkins-Vorlage (Templates, OAuth-Login, S2I-Jenkinsfile) wird nicht mehr gepflegt – keine Neuanlage
  • der OpenShift-Weg, Variante Tekton (E2): Build-Pods, aber zweckgebaut und flüchtig – kein Master, kein PVC, ein PipelineRun je Lauf
  • der OpenShift-Weg, Variante CI außerhalb: GitHub Actions / GitLab CI / externer Jenkins baut außerhalb und deployt nur über ein SA-Token in den Cluster
  • Faustregel: baue dort, wo CPU billig ist – deploye dort, wo die App läuft
  • Bibliothek: Jenkins läuft außerhalb in einem lokalen docker-compose, baut je Dienst ein Image und pusht nach ghcr.io
  • dann ruft Jenkins je Dienst helm upgrade --install catalog ./chart -n library --atomic
  • authentifiziert als system:serviceaccount:library:pipeline, gebunden an admin, system:image-builder und registry-editor in library (A5)
  • der Cluster sieht nur helm upgrade-Aufrufe – keine Build-Pods, kein Jenkins-Pod, kein PVC
  • Abwägung Control Plane: Jenkins-im-Cluster belastet sie stark, extern-bauen kaum
  • Abwägung Secrets: intern hat Jenkins alles, extern muss man ein Deploy-Token und Registry-Zugang nach außen geben
  • Abwägung Portabilität: externe CI läuft gegen jeden Cluster gleich, Jenkins-im-Cluster ist an diesen einen gebunden
  • ein Deploy von außen braucht genau ein Token mit gerade den nötigen Rollen – nicht cluster-admin
  • OCP-Unterschied: die Jenkins-Vorlage ist OpenShift-eigen – Tekton kommt als OpenShift-Pipelines-Operator, ist aber Standard-Kubernetes-Tekton
Modellwas läuftLast auf der Control Plane
Jenkins im Clusterein Master-Pod (dauerhaft) + Agent-Pods je Build, PVC für $JENKINS_HOMEhoch, konkurriert mit den Diensten
Tekton (dieser Guide)ein Pod je TaskRun, danach weg – kein Master, kein PVC für einen Servernur während des Laufs
CI außerhalb (die Bibliothek)baut komplett extern, deployt nur über ein SA-Tokenpraktisch keine

Faustregel aus dem Atlas: baue dort, wo CPU billig ist, deploye dort, wo die App läuft. Tekton ist der Mittelweg – Build-Last im Cluster, aber flüchtig statt dauerhaft. Die alte OpenShift-Jenkins-Vorlage (Templates, OAuth-Login, S2I-Jenkinsfile) wird nicht mehr gepflegt, keine Neuanlage.

2 Den Pipelines-Operator installieren

Tekton kommt als OpenShift-Pipelines-Operator – Standard-Tekton darunter, plus Konsolen-Integration.

Laptop · Bash
oc get csv -A | grep -i pipelines   # schon installiert?

cat <<'EOF' | oc apply -f -
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: openshift-pipelines-operator
  namespace: openshift-operators
spec:
  channel: latest
  name: openshift-pipelines-operator-rh
  source: redhat-operators
  sourceNamespace: openshift-marketplace
EOF

oc get csv -n openshift-operators -w   # bis Phase Succeeded

Der Operator bringt die CRDs Task, Pipeline, TaskRun, PipelineRun mit, und den pipeline-ServiceAccount, der in jedem Namespace automatisch entsteht, sobald der erste Tekton-Lauf dort startet.

3 Einen Task schreiben und laufen lassen

Ein Task ist eine geordnete Liste von steps – jeder Step ein Container.

Tekton ist CI als Kubernetes-Objekte. Ein Task ist eine Reihe von steps, jeder Step ein Container. Eine Pipeline reiht Tasks. Ein PipelineRun ist ein Lauf und erzeugt Pods. Daten zwischen Tasks fließen über Workspaces. Alles flüchtig – kein Master, kein PVC für einen Server.

TaskPipelinePipelineRun – jeder Step ein Container, jeder Lauf ein Satz Pods. Task eine geordnete Liste von steps jeder Step = ein Container (Image + Kommando) step: git-clone step: mvn package step: buildah bud + push Steps teilen sich einen Pod, laufen nacheinander wiederverwendbar aus dem Tekton Hub / als ClusterTask Pipeline eine geordnete oder DAG-Anordnung von Tasks clone → test → build → deploy runAfter ordnet, sonst laufen Tasks parallel params rein, results raus – so gibt ein Task den Image-Digest an den nächsten weiter finally-Tasks laufen immer (Aufräumen, Melden) die Pipeline selbst startet nichts – sie ist die Vorlage when-Ausdrücke: Tasks bedingt überspringen PipelineRun eine Ausführung der Pipeline erzeugt je Task einen TaskRun → je TaskRun einen Pod bindet konkrete params und workspaces läuft als der pipeline-SA (A6) – dessen RBAC begrenzt ihn nach dem Lauf werden Pods bereinigt – per Cleanup/Retention Status + Logs: tkn pr logs -f, die Konsole (Pipelines-Tab) bleibt als Objekt für die Historie (bis aufgeräumt) weiterhin Cluster-CPU – aber nur während des Laufs Workspace geteilter Speicher zwischen Tasks ein PVC (bleibt), emptyDir (nur der Run) oder eine ConfigMap / ein Secret so kommt der geklonte Code von clone zu build der Maven-Cache als PVC-Workspace → schnellere Builds volumeClaimTemplate: ein frisches PVC je Run ohne Workspace kann ein Task nichts an den nächsten geben Secret-Workspace: die Registry-Credentials für den Push Triggers – ein Git-Webhook wird zum PipelineRun EventListener – ein Pod mit einer Route, nimmt den Webhook an TriggerBinding – zieht Werte aus dem Payload (Branch, Commit, Repo) TriggerTemplate – die Vorlage für den PipelineRun, die entsteht Interceptors prüfen die Webhook-Signatur (GitHub, GitLab) und filtern (nur main) Alternative: tkn pipeline start von Hand, oder ein Cron-PipelineRun Pipelines as Code (PAC): der .tekton/-Ordner im Repo definiert alles Werkzeuge & Bibliothek tkn-CLI: tkn pipeline start, tkn pr ls, tkn pr logs -f der OpenShift-Pipelines-Operator bringt Tekton + die Konsolen-Ansicht Bibliothek: git-clone → mvn test → buildah → helm upgrade je Dienst das wäre der Weg weg von Jenkins (E1) und rein in den Cluster Deploy per Argo CD (E3) statt helm upgrade macht die Pipeline noch schlanker Konsole zeigt den DAG live, grün/rot je Task Merksatz: Task = Steps (Container), Pipeline = Tasks (Reihenfolge), PipelineRun = ein Lauf (Pods), Workspace = wie Daten zwischen Tasks fließen alles laufbezogen – Pods werden per Cleanup/Retention bereinigt, kein dauerhafter Server-Prozess wie bei Jenkins (E1) OCP-Unterschied: der Operator heißt OpenShift Pipelines und bringt die Konsolen-Integration und ein paar Extra-ClusterTasks – darunter ist Standard-Tekton.
CI als Kubernetes-Objekte. Ein Task ist eine Reihe von steps, jeder ein Container. Eine Pipeline ordnet Tasks (Reihenfolge oder DAG). Ein PipelineRun ist ein Lauf und erzeugt je Task einen Pod – diese laufbezogenen Pods und Objekte werden nach dem Lauf durch konfigurierte Cleanup-/Retention-Regeln bereinigt; kein Master, kein PVC für einen Server. Daten zwischen Tasks fließen über Workspaces (ein PVC, emptyDir, ein Secret). Ein EventListener mit TriggerBinding und TriggerTemplate macht aus einem Git-Webhook einen PipelineRun.
  • ein Task ist eine geordnete Liste von stepsjeder Step ist ein Container (Image + Kommando), die Steps teilen sich einen Pod
  • eine Pipeline ist eine geordnete oder DAG-Anordnung von TasksrunAfter ordnet, sonst laufen sie parallel, finally-Tasks laufen immer
  • params gehen rein, results kommen raus – so gibt ein Task den Image-Digest an den nächsten weiter
  • ein PipelineRun ist eine Ausführung – er erzeugt je Task einen TaskRun und je TaskRun einen Pod
  • der PipelineRun läuft als der pipeline-SA (A6) – dessen RBAC begrenzt, was die Pipeline anfassen darf
  • Cleanup/Retention bereinigt die laufbezogenen Pods und TaskRuns nach dem Lauf – kein dauerhafter Server-Prozess wie bei Jenkins (E1), Cluster-CPU fällt nach dem Lauf wieder ab
  • ein Workspace ist geteilter Speicher zwischen Tasks: ein PVC (bleibt), emptyDir (nur der Run), oder eine ConfigMap / ein Secret
  • so kommt der geklonte Code von clone zu build, und der Maven-Cache als PVC-Workspace macht Builds schneller
  • Triggers: ein EventListener (Pod + Route) nimmt den Webhook an, TriggerBinding zieht Werte aus dem Payload, TriggerTemplate ist die PipelineRun-Vorlage
  • Interceptors prüfen die Webhook-Signatur und filtern (nur main) – Alternative: tkn pipeline start oder ein Cron-PipelineRun
  • wiederverwendbare Tasks aus dem Tekton Hub oder als ClusterTask: git-clone, buildah, s2i
  • Werkzeuge: die tkn-CLI (tkn pr logs -f), der OpenShift-Pipelines-Operator mit Konsolen-Ansicht (DAG live, grün/rot je Task)
  • Bibliothek: git-clone → mvn test → buildah → helm upgrade je Dienst wäre der Weg weg von Jenkins (E1) und rein in den Cluster
  • OCP-Unterschied: der Operator heißt OpenShift Pipelines und bringt Konsolen-Integration und Extra-ClusterTasks – darunter ist Standard-Tekton
Laptop · Bash
cat <<'EOF' | oc apply -f -
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: demo-check
  namespace: library
spec:
  params:
    - name: nachricht
      type: string
      default: "Tekton laeuft"
  steps:
    - name: begruessen
      image: registry.access.redhat.com/ubi9/ubi-minimal:latest
      script: |
        #!/bin/sh
        echo "$(params.nachricht)"
    - name: umgebung-zeigen
      image: registry.access.redhat.com/ubi9/ubi-minimal:latest
      script: |
        #!/bin/sh
        echo "laeuft als: $(whoami 2>/dev/null || id -u)"
        cat /etc/os-release | head -3
EOF

cat <<'EOF' | oc apply -f -
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  name: demo-check-run-1
  namespace: library
spec:
  taskRef:
    name: demo-check
  params:
    - name: nachricht
      value: "Hallo aus dem ersten TaskRun"
EOF

tkn taskrun logs demo-check-run-1 -n library -f
# ohne tkn-CLI: oc logs -f -l tekton.dev/taskRun=demo-check-run-1 -n library --all-containers

Die zwei Steps teilen sich einen Pod, laufen aber nacheinander – im Pod stehen sie als step-begruessen und step-umgebung-zeigen. Nach dem Lauf bleibt der TaskRun als Objekt für die Historie, der Pod selbst verschwindet nach kurzer Zeit (Completion-TTL).

4 Zwei Tasks zu einer Pipeline verketten

Eine Pipeline ordnet Tasks, ein Workspace gibt ihnen geteilten Speicher – genau das Muster, das git-clone → build in der echten Build-Kette nutzt.

Laptop · Bash
cat <<'EOF' | oc apply -f -
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: demo-schreiben
  namespace: library
spec:
  workspaces:
    - name: teilen
  steps:
    - name: datei-schreiben
      image: registry.access.redhat.com/ubi9/ubi-minimal:latest
      script: |
        #!/bin/sh
        echo "erzeugt um $(date -Iseconds)" > $(workspaces.teilen.path)/marker.txt
---
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: demo-lesen
  namespace: library
spec:
  workspaces:
    - name: teilen
  steps:
    - name: datei-lesen
      image: registry.access.redhat.com/ubi9/ubi-minimal:latest
      script: |
        #!/bin/sh
        echo "gefunden:"
        cat $(workspaces.teilen.path)/marker.txt
EOF

cat <<'EOF' | oc apply -f -
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: demo-pipeline
  namespace: library
spec:
  workspaces:
    - name: geteilt
  tasks:
    - name: schreiben
      taskRef: { name: demo-schreiben }
      workspaces:
        - { name: teilen, workspace: geteilt }
    - name: lesen
      taskRef: { name: demo-lesen }
      runAfter: ["schreiben"]
      workspaces:
        - { name: teilen, workspace: geteilt }
EOF

runAfter erzwingt die Reihenfolge – ohne die Zeile würden schreiben und lesen parallel starten, und lesen fände die Datei noch nicht.

5 Den PipelineRun live beobachten

Ein PipelineRun ist ein Lauf – er erzeugt je Task einen TaskRun, je TaskRun einen Pod.

Laptop · Bash
cat <<'EOF' | oc apply -f -
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: demo-pipeline-run-1
  namespace: library
spec:
  pipelineRef:
    name: demo-pipeline
  workspaces:
    - name: geteilt
      volumeClaimTemplate:
        spec:
          accessModes: ["ReadWriteOnce"]
          resources: { requests: { storage: 1Gi } }
EOF

tkn pipelinerun logs demo-pipeline-run-1 -n library -f
oc get taskrun -n library -l tekton.dev/pipelineRun=demo-pipeline-run-1
oc get pipelinerun demo-pipeline-run-1 -n library -o jsonpath='{.status.conditions[0].status} {.status.conditions[0].reason}{"\n"}'

Das volumeClaimTemplate im Workspace erzeugt ein frisches PVC nur für diesen Lauf – nach dem Löschen des PipelineRuns bleibt es stehen (Aufräumen unten). In der Konsole zeigt der Pipelines-Tab den DAG live, grün sobald ein Task fertig ist.

MerkeNach dem Lauf sind die Pods weg – kein Server-Prozess wie bei Jenkins. Die Objekte TaskRun und PipelineRun bleiben für die Historie, bis sie aufgeräumt werden.

6 Typische Fallen

Symptommeist
PipelineRun hängt in PipelinePendingder pipeline-ServiceAccount fehlt oder das PVC im Workspace kann nicht gebunden werden
lesen-Task findet die Datei nichtrunAfter fehlt – Tasks liefen parallel, nicht nacheinander
Step schlägt mit permission denied fehlSCC-Restriktion (A7) – das Skript versucht etwas, das der Pod-Security-Kontext nicht erlaubt
TaskRun bleibt ewig PendingResourceQuota im Namespace ist voll (B7) – kein Platz für einen weiteren Pod
Operator-Installation hängtCSV in openshift-operators prüfen, oft ein fehlender Katalog-Sync

7 Wie das Projekt es macht

Die Bibliothek baut nicht mit Tekton – Jenkins läuft außerhalb in einem lokalen docker-compose, pusht Images nach ghcr.io und ruft helm upgrade --install catalog ./chart -n library --atomic als system:serviceaccount:library:pipeline (build-kette-openshift.html). Der Cluster sieht dabei keine Build-Pods. Diese Anleitung zeigt das Alternativmuster, das der Atlas als nächsten Schritt nennt: dieselben Stufen git-clone → mvn test → buildah → helm upgrade als Tekton-Pipeline statt als Jenkinsfile – mit git-clone als wiederverwendbarem ClusterTask aus dem Tekton Hub anstelle von demo-schreiben.

+ Die Kurzfassung

Taskeine geordnete Liste von Steps, jeder Step ein Container, alle teilen sich einen Pod
Pipelineordnet Tasks per runAfter, sonst laufen sie parallel
PipelineRunein Lauf, erzeugt Pods, danach ist alles wieder weg – kein Server, kein Master
Workspacegeteilter Speicher zwischen Tasks – ein PVC, emptyDir oder ein Secret
⌂ Cockpit