Skip to content
Vladimir Chavkov
Go back

OpenShift Pipelines: Complete Tekton CI/CD Guide

Edit page

OpenShift Pipelines: Complete Tekton CI/CD Guide

OpenShift Pipelines is a cloud-native, continuous integration and delivery (CI/CD) solution based on Kubernetes resources and Tekton. This comprehensive guide covers pipeline creation, task development, and production CI/CD patterns for OpenShift.

What is OpenShift Pipelines?

OpenShift Pipelines provides:

Key Features

  1. Kubernetes Native: Pipelines as Custom Resources
  2. Reusable Components: Tasks and pipelines as building blocks
  3. Serverless: No dedicated CI/CD server required
  4. Parallel Execution: Run tasks in parallel
  5. Extensibility: Custom tasks and resources
  6. Event-Driven: Webhook and event triggers
  7. Multi-Platform: Build for any platform
  8. GitOps Ready: Integration with ArgoCD and Flux

Architecture

┌─────────────────────────────────────────────────────────┐
│ Tekton Components │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Pipeline │ │ Task │ │ Trigger │ │
│ │ (CRD) │ │ (CRD) │ │ (CRD) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ PipelineRun │ │ TaskRun │ │
│ │ (Runtime) │ │ (Runtime) │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ Kubernetes/OpenShift │
│ │
│ Each TaskRun creates a Pod with containers for steps │
└─────────────────────────────────────────────────────────┘

Installation

Install Operator

Terminal window
# Via OpenShift Console:
# Operators → OperatorHub → Search "OpenShift Pipelines"
# → Install → Subscribe
# Or via CLI
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
# Verify installation
oc get pods -n openshift-pipelines
tkn version

Install tkn CLI

Terminal window
# macOS
brew install tektoncd-cli
# Linux
wget https://github.com/tektoncd/cli/releases/download/v0.33.0/tkn_0.33.0_Linux_x86_64.tar.gz
tar xvzf tkn_0.33.0_Linux_x86_64.tar.gz
sudo mv tkn /usr/local/bin/
# Windows
choco install tektoncd-cli
# Verify
tkn version

Core Concepts

Task

task-build.yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: build-image
spec:
params:
- name: IMAGE
type: string
description: Image name with tag
- name: CONTEXT
type: string
default: "."
description: Build context directory
workspaces:
- name: source
description: Source code workspace
steps:
- name: build-and-push
image: gcr.io/kaniko-project/executor:latest
command:
- /kaniko/executor
args:
- --context=$(workspaces.source.path)/$(params.CONTEXT)
- --dockerfile=$(workspaces.source.path)/$(params.CONTEXT)/Dockerfile
- --destination=$(params.IMAGE)
- --cache=true
volumeMounts:
- name: docker-config
mountPath: /kaniko/.docker
volumes:
- name: docker-config
secret:
secretName: docker-config

ClusterTask

clustertask-git-clone.yaml
apiVersion: tekton.dev/v1beta1
kind: ClusterTask
metadata:
name: git-clone
spec:
params:
- name: url
type: string
description: Repository URL
- name: revision
type: string
default: main
description: Git revision
- name: subdirectory
type: string
default: ""
description: Subdirectory inside workspace
workspaces:
- name: output
description: Clone destination
steps:
- name: clone
image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:latest
script: |
#!/bin/sh
set -eu
git clone $(params.url) $(workspaces.output.path)/$(params.subdirectory)
cd $(workspaces.output.path)/$(params.subdirectory)
git checkout $(params.revision)

Pipeline

pipeline-build-deploy.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: build-and-deploy
spec:
params:
- name: APP_NAME
type: string
- name: GIT_REPO
type: string
- name: GIT_REVISION
type: string
default: main
- name: IMAGE
type: string
- name: DEPLOYMENT_NAME
type: string
workspaces:
- name: shared-workspace
- name: maven-settings
tasks:
# Task 1: Clone repository
- name: fetch-repository
taskRef:
name: git-clone
kind: ClusterTask
workspaces:
- name: output
workspace: shared-workspace
params:
- name: url
value: $(params.GIT_REPO)
- name: revision
value: $(params.GIT_REVISION)
# Task 2: Run tests
- name: run-tests
taskRef:
name: maven
kind: ClusterTask
runAfter:
- fetch-repository
workspaces:
- name: source
workspace: shared-workspace
- name: maven-settings
workspace: maven-settings
params:
- name: GOALS
value:
- clean
- test
# Task 3: Build image
- name: build-image
taskRef:
name: build-image
runAfter:
- run-tests
workspaces:
- name: source
workspace: shared-workspace
params:
- name: IMAGE
value: $(params.IMAGE)
# Task 4: Deploy
- name: deploy
taskRef:
name: openshift-client
kind: ClusterTask
runAfter:
- build-image
params:
- name: SCRIPT
value: |
oc set image deployment/$(params.DEPLOYMENT_NAME) \
$(params.APP_NAME)=$(params.IMAGE)
oc rollout status deployment/$(params.DEPLOYMENT_NAME)

PipelineRun

pipelinerun-example.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: build-deploy-run-
spec:
pipelineRef:
name: build-and-deploy
params:
- name: APP_NAME
value: myapp
- name: GIT_REPO
value: https://github.com/example/myapp
- name: GIT_REVISION
value: main
- name: IMAGE
value: image-registry.openshift-image-registry.svc:5000/myproject/myapp:latest
- name: DEPLOYMENT_NAME
value: myapp
workspaces:
- name: shared-workspace
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- name: maven-settings
emptyDir: {}
timeouts:
pipeline: 1h
tasks: 30m

Common Tasks

Maven Build

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: maven-build
spec:
params:
- name: GOALS
type: array
default:
- package
- name: MAVEN_IMAGE
type: string
default: gcr.io/cloud-builders/mvn:latest
workspaces:
- name: source
- name: maven-settings
steps:
- name: mvn
image: $(params.MAVEN_IMAGE)
workingDir: $(workspaces.source.path)
command:
- /usr/bin/mvn
args:
- -s
- $(workspaces.maven-settings.path)/settings.xml
- $(params.GOALS)
env:
- name: MAVEN_OPTS
value: "-Xmx1024m"

NPM Build

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: npm-build
spec:
params:
- name: NODE_VERSION
type: string
default: "18"
workspaces:
- name: source
steps:
- name: install
image: node:$(params.NODE_VERSION)
workingDir: $(workspaces.source.path)
script: |
#!/bin/sh
npm ci
- name: test
image: node:$(params.NODE_VERSION)
workingDir: $(workspaces.source.path)
script: |
#!/bin/sh
npm test
- name: build
image: node:$(params.NODE_VERSION)
workingDir: $(workspaces.source.path)
script: |
#!/bin/sh
npm run build

Security Scan

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: trivy-scan
spec:
params:
- name: IMAGE
type: string
steps:
- name: scan
image: aquasec/trivy:latest
command:
- trivy
args:
- image
- --severity
- HIGH,CRITICAL
- --exit-code
- "1"
- $(params.IMAGE)

Triggers

EventListener

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: github-listener
spec:
serviceAccountName: pipeline
triggers:
- name: github-push
interceptors:
- ref:
name: github
params:
- name: secretRef
value:
secretName: github-webhook-secret
secretKey: secret
- name: eventTypes
value:
- push
bindings:
- ref: github-binding
template:
ref: build-deploy-template

TriggerBinding

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: github-binding
spec:
params:
- name: gitrevision
value: $(body.head_commit.id)
- name: gitrepositoryurl
value: $(body.repository.url)
- name: gitrepositoryname
value: $(body.repository.name)

TriggerTemplate

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: build-deploy-template
spec:
params:
- name: gitrevision
- name: gitrepositoryurl
- name: gitrepositoryname
resourcetemplates:
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: $(tt.params.gitrepositoryname)-run-
spec:
pipelineRef:
name: build-and-deploy
params:
- name: GIT_REPO
value: $(tt.params.gitrepositoryurl)
- name: GIT_REVISION
value: $(tt.params.gitrevision)
- name: APP_NAME
value: $(tt.params.gitrepositoryname)
workspaces:
- name: shared-workspace
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

Configure Webhook

Terminal window
# Get EventListener URL
oc get route el-github-listener -o jsonpath='{.spec.host}'
# Configure in GitHub:
# Settings → Webhooks → Add webhook
# Payload URL: http://el-github-listener-myproject.apps.cluster.example.com
# Content type: application/json
# Secret: (from github-webhook-secret)
# Events: Just the push event

Workspaces

PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pipeline-workspace
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
# Use in PipelineRun
workspaces:
- name: shared-workspace
persistentVolumeClaim:
claimName: pipeline-workspace

VolumeClaimTemplate

# Dynamic PVC creation
workspaces:
- name: shared-workspace
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: gp3-csi

ConfigMap/Secret

workspaces:
- name: maven-settings
configMap:
name: maven-settings
- name: docker-config
secret:
secretName: docker-credentials

Complete CI/CD Pipeline

complete-pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: production-pipeline
spec:
params:
- name: APP_NAME
- name: GIT_REPO
- name: GIT_REVISION
default: main
- name: IMAGE_REGISTRY
- name: IMAGE_TAG
default: latest
workspaces:
- name: shared-workspace
- name: docker-config
tasks:
# 1. Clone source
- name: clone
taskRef:
name: git-clone
kind: ClusterTask
workspaces:
- name: output
workspace: shared-workspace
params:
- name: url
value: $(params.GIT_REPO)
- name: revision
value: $(params.GIT_REVISION)
# 2. Run unit tests
- name: test
taskRef:
name: npm-build
runAfter: [clone]
workspaces:
- name: source
workspace: shared-workspace
# 3. Code analysis
- name: sonar-scan
taskRef:
name: sonarqube-scanner
kind: ClusterTask
runAfter: [test]
workspaces:
- name: source
workspace: shared-workspace
params:
- name: SONAR_HOST_URL
value: https://sonarqube.example.com
- name: SONAR_PROJECT_KEY
value: $(params.APP_NAME)
# 4. Build container image
- name: build
taskRef:
name: buildah
kind: ClusterTask
runAfter: [sonar-scan]
workspaces:
- name: source
workspace: shared-workspace
- name: dockerconfig
workspace: docker-config
params:
- name: IMAGE
value: $(params.IMAGE_REGISTRY)/$(params.APP_NAME):$(params.IMAGE_TAG)
- name: TLSVERIFY
value: "false"
# 5. Security scan
- name: scan
taskRef:
name: trivy-scan
runAfter: [build]
params:
- name: IMAGE
value: $(params.IMAGE_REGISTRY)/$(params.APP_NAME):$(params.IMAGE_TAG)
# 6. Deploy to dev
- name: deploy-dev
taskRef:
name: openshift-client
kind: ClusterTask
runAfter: [scan]
params:
- name: SCRIPT
value: |
oc project dev
oc set image deployment/$(params.APP_NAME) \
$(params.APP_NAME)=$(params.IMAGE_REGISTRY)/$(params.APP_NAME):$(params.IMAGE_TAG)
oc rollout status deployment/$(params.APP_NAME)
# 7. Integration tests
- name: integration-test
taskRef:
name: curl
kind: ClusterTask
runAfter: [deploy-dev]
params:
- name: url
value: http://$(params.APP_NAME).dev.svc:8080/health
# 8. Deploy to staging (manual approval would go here)
- name: deploy-staging
taskRef:
name: openshift-client
kind: ClusterTask
runAfter: [integration-test]
params:
- name: SCRIPT
value: |
oc project staging
oc set image deployment/$(params.APP_NAME) \
$(params.APP_NAME)=$(params.IMAGE_REGISTRY)/$(params.APP_NAME):$(params.IMAGE_TAG)
oc rollout status deployment/$(params.APP_NAME)

CLI Operations

Terminal window
# List pipelines
tkn pipeline list
# Start pipeline
tkn pipeline start build-and-deploy \
-p APP_NAME=myapp \
-p GIT_REPO=https://github.com/example/myapp \
-w name=shared-workspace,claimName=pipeline-workspace \
--showlog
# List runs
tkn pipelinerun list
# View logs
tkn pipelinerun logs -f <pipelinerun-name>
# Describe pipeline
tkn pipeline describe build-and-deploy
# Delete pipeline run
tkn pipelinerun delete <pipelinerun-name>
# Cancel running pipeline
tkn pipelinerun cancel <pipelinerun-name>
# List tasks
tkn task list
tkn clustertask list
# Start task directly
tkn task start build-image \
-p IMAGE=myimage:latest \
-w name=source,claimName=source-pvc \
--showlog

Monitoring

Pipeline Metrics

# ServiceMonitor for Tekton
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: tekton-pipelines-controller
namespace: openshift-pipelines
spec:
endpoints:
- interval: 30s
port: metrics
selector:
matchLabels:
app: tekton-pipelines-controller

Dashboard

Terminal window
# Install Tekton Dashboard
oc apply -f https://github.com/tektoncd/dashboard/releases/latest/download/openshift-tekton-dashboard-release.yaml
# Expose dashboard
oc expose svc tekton-dashboard -n openshift-pipelines
# Get URL
oc get route tekton-dashboard -n openshift-pipelines

Best Practices

Resource Management

spec:
steps:
- name: build
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 1000m
memory: 2Gi

Timeout Configuration

# Task timeout
spec:
timeout: 30m
# Pipeline timeout
spec:
timeouts:
pipeline: 1h
tasks: 30m
finally: 15m

Results

# Task with results
spec:
results:
- name: image-digest
description: Digest of the built image
steps:
- name: build
script: |
# ... build steps ...
echo -n $DIGEST | tee $(results.image-digest.path)
# Use in next task
- name: deploy
params:
- name: IMAGE_DIGEST
value: $(tasks.build.results.image-digest)

Troubleshooting

Terminal window
# View pod logs
oc logs -f <pipelinerun-pod>
# Describe PipelineRun
tkn pipelinerun describe <name>
# Get events
oc get events --sort-by='.lastTimestamp'
# Debug failed task
oc debug pod/<taskrun-pod>
# Clean up old runs
tkn pipelinerun delete --keep 5

Conclusion

OpenShift Pipelines provides a powerful, Kubernetes-native CI/CD solution built on Tekton. Its declarative approach, reusable components, and deep OpenShift integration make it ideal for cloud-native application delivery pipelines.


Master OpenShift Pipelines with our training programs. Contact us for customized CI/CD training.


Edit page
Share this post on:

Previous Post
OpenShift Data Foundation: Complete Storage Platform Guide
Next Post
Harvester: Modern Hyperconverged Infrastructure on Kubernetes