Introduction to Tekton CI/CD Pipelines
Tekton is a powerful, open-source, Kubernetes-native framework for building continuous integration and continuous delivery (CI/CD) systems. Originally developed as part of the Knative project and now governed by the Continuous Delivery Foundation (CDF), Tekton provides a set of building blocks that allow developers to construct sophisticated pipelines for building, testing, and deploying applications across cloud environments.
Unlike traditional CI/CD tools that run as standalone applications, Tekton leverages the full power of Kubernetes. Every step in a Tekton pipeline runs as a container within a Kubernetes pod, which means your pipelines inherit the scalability, isolation, and resource management capabilities of Kubernetes itself.
Why Tekton Matters
The modern software delivery landscape demands flexibility, scalability, and vendor neutrality. Tekton addresses these needs through several key advantages:
- Kubernetes-native: Tekton installs as a Kubernetes extension and uses Kubernetes Custom Resource Definitions (CRDs) to define pipeline components, making it a natural fit for cloud-native workflows.
- Decoupled and reusable: Tasks and pipelines are defined independently, allowing teams to compose reusable building blocks across projects.
- Vendor-neutral: Tekton works with any Kubernetes cluster and integrates with most CI/CD tooling ecosystems.
- Serverless execution: Pipeline runs spin up pods on demand and tear them down when complete, optimizing resource usage.
- Extensible catalog: The Tekton Hub provides a community-driven catalog of pre-built tasks and pipelines.
Core Concepts and Architecture
Before diving into implementation, it is essential to understand the foundational building blocks of Tekton. Each component is represented as a Kubernetes CRD, which means you manage them using kubectl just like any other Kubernetes resource.
Steps, Tasks, and Pipelines
Tekton organizes work into a clear hierarchy:
- Step: The smallest unit of work, represented by a single container that runs a specific command.
- Task: A collection of sequential steps that run in a single Kubernetes pod. Steps within a task share a workspace volume.
- Pipeline: A directed acyclic graph (DAG) of Tasks that defines the overall workflow. Tasks can run sequentially or in parallel.
Supporting Resources
- TaskRun: An execution instance of a Task.
- PipelineRun: An execution instance of a Pipeline.
- PipelineResource: (Deprecated in favor of Tasks and workspaces) Inputs and outputs for pipelines.
- Workspace: A shared volume that allows data to pass between Tasks.
- Params: Configurable values passed into Tasks and Pipelines.
- Results: Values produced by a Task that can be consumed by downstream Tasks.
Installing Tekton
Tekton Pipelines can be installed on any Kubernetes cluster version 1.22 or later. The recommended approach is to use the official release manifests.
Prerequisites
- A running Kubernetes cluster (minikube, kind, or a managed cloud cluster)
kubectlconfigured and connected to your cluster- Cluster admin privileges
Installation Steps
Apply the official Tekton Pipelines manifest to install the Tekton controllers and CRDs:
kubectl apply --filename \
https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
Verify the installation by checking the Tekton pods in the tekton-pipelines namespace:
kubectl get pods --namespace tekton-pipelines \
--watch
Once both the tekton-pipelines-controller and tekton-pipelines-webhook pods are running, Tekton is ready to use. Optionally, install the Tekton CLI for a more convenient experience:
# On macOS
brew install tektoncd-cli
# On Linux
curl -sL https://github.com/tektoncd/cli/releases/download/v0.31.0/tkn_0.31.0_Linux_x86_64.tar.gz | tar xz -C /usr/local/bin tkn
Creating Your First Task
Let us begin by creating a simple Task that clones a Git repository and lists its contents. Save the following YAML to a file named git-clone-task.yaml:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: git-clone-and-list
spec:
params:
- name: repo-url
type: string
description: The Git repository URL to clone
- name: revision
type: string
description: The branch or commit to checkout
default: main
workspaces:
- name: source
description: Workspace to store the cloned repository
steps:
- name: clone
image: alpine/git:v2.34.2
script: |
#!/bin/sh
set -e
git clone $(params.repo-url) $(workspaces.source.path)/repo
cd $(workspaces.source.path)/repo
git checkout $(params.revision)
- name: list-files
image: alpine:3.18
script: |
#!/bin/sh
ls -la $(workspaces.source.path)/repo
Apply the Task to your cluster:
kubectl apply -f git-clone-task.yaml
Running the Task
To execute this Task, create a TaskRun that provides the required parameters and a workspace. Save the following to task-run.yaml:
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: git-clone-run
spec:
taskRef:
name: git-clone-and-list
params:
- name: repo-url
value: https://github.com/tektoncd/cli.git
- name: revision
value: main
workspaces:
- name: source
emptyDir: {}
Apply and monitor the TaskRun:
kubectl apply -f task-run.yaml
kubectl get taskrun git-clone-run -o yaml
tkn taskrun logs git-clone-run -f
Building a Complete Pipeline
Now let us construct a more realistic pipeline that clones a repository, runs tests, builds a container image, and pushes it to a registry. This example demonstrates how Tasks connect through workspaces and results.
Defining the Pipeline
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: build-and-deploy
spec:
params:
- name: repo-url
type: string
- name: revision
type: string
default: main
- name: image
type: string
description: Full image name including registry
workspaces:
- name: shared-data
description: Shared workspace between tasks
- name: docker-credentials
description: Docker registry credentials
tasks:
- name: fetch-repo
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-data
params:
- name: url
value: $(params.repo-url)
- name: revision
value: $(params.revision)
- name: run-tests
runAfter:
- fetch-repo
taskRef:
name: golang-test
workspaces:
- name: source
workspace: shared-data
- name: build-image
runAfter:
- run-tests
taskRef:
name: kaniko
workspaces:
- name: source
workspace: shared-data
- name: dockerconfig
workspace: docker-credentials
params:
- name: IMAGE
value: $(params.image)
- name: CONTEXT
value: .
- name: DOCKERFILE
value: ./Dockerfile
This pipeline references pre-built Tasks from the Tekton Catalog. Install them before running the pipeline:
# Install git-clone task
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.9/git-clone.yaml
# Install golang-test task
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/golang-test/0.2/golang-test.yaml
# Install kaniko task for building images
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/kaniko/0.6/kaniko.yaml
Executing the Pipeline
Create a PipelineRun to execute the pipeline with specific parameters and workspaces:
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: build-deploy-run-1
spec:
pipelineRef:
name: build-and-deploy
params:
- name: repo-url
value: https://github.com/example/my-go-app.git
- name: revision
value: main
- name: image
value: registry.example.com/my-go-app:latest
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- name: docker-credentials
secret:
secretName: docker-registry-secret
Apply the PipelineRun and monitor its progress:
kubectl apply -f pipeline-run.yaml
tkn pipelinerun logs build-deploy-run-1 -f
Working with Workspaces
Workspaces are the primary mechanism for sharing data between Tasks in a pipeline. They abstract away the underlying storage, allowing you to use different volume types depending on your needs.
Workspace Binding Options
Tekton supports several ways to bind workspaces in a TaskRun or PipelineRun:
workspaces:
# Option 1: PersistentVolumeClaim
- name: source
persistentVolumeClaim:
claimName: my-pvc
# Option 2: VolumeClaimTemplate (creates a PVC automatically)
- name: source
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi
# Option 3: emptyDir (ephemeral, cleared when pod is deleted)
- name: source
emptyDir: {}
# Option 4: ConfigMap (read-only configuration data)
- name: config
configMap:
name: app-config
# Option 5: Secret (sensitive data)
- name: credentials
secret:
secretName: registry-credentials
Using Conditions and When Expressions
Tekton provides when expressions to conditionally execute Tasks based on parameters, results, or static values. This is useful for implementing deployment strategies that vary by branch or environment.
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: conditional-pipeline
spec:
params:
- name: branch
type: string
tasks:
- name: build
taskRef:
name: build-task
- name: deploy-staging
runAfter:
- build
when:
- input: "$(params.branch)"
operator: in
values: ["develop", "staging"]
taskRef:
name: deploy-staging-task
- name: deploy-production
runAfter:
- build
when:
- input: "$(params.branch)"
operator: in
values: ["main"]
taskRef:
name: deploy-production-task
Handling Results Between Tasks
Tekton Tasks can produce results that downstream Tasks consume. This enables dynamic, data-driven pipelines. For example, a Task that builds an image can emit the image digest, which a subsequent deployment Task uses.
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: produce-result
spec:
results:
- name: image-digest
description: The digest of the built image
steps:
- name: produce
image: alpine:3.18
script: |
#!/bin/sh
echo -n "sha256:abc123def456" | tee $(results.image-digest.path)
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: consume-result
spec:
params:
- name: digest
type: string
steps:
- name: consume
image: alpine:3.18
script: |
#!/bin/sh
echo "Deploying image with digest: $(params.digest)"
Reference the result in your Pipeline using the $(tasks.<task-name>.results.<result-name>) syntax:
tasks:
- name: produce
taskRef:
name: produce-result
- name: consume
runAfter:
- produce
taskRef:
name: consume-result
params:
- name: digest
value: "$(tasks.produce.results.image-digest)"
Triggering Pipelines with Tekton Triggers
Tekton Triggers extends Tekton Pipelines by enabling event-driven execution. You can configure your pipelines to start automatically in response to Git webhooks, Kubernetes events, or custom events.
Installing Tekton Triggers
kubectl apply --filename \
https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
kubectl apply --filename \
https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml
Creating a Trigger Template, Binding, and Listener
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: github-pipeline-template
spec:
params:
- name: git-repo-url
- name: git-revision
- name: git-repo-name
resourcetemplates:
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: github-run-
spec:
pipelineRef:
name: build-and-deploy
params:
- name: repo-url
value: $(tt.params.git-repo-url)
- name: revision
value: $(tt.params.git-revision)
- name: image
value: registry.example.com/$(tt.params.git-repo-name):latest
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: github-binding
spec:
params:
- name: git-repo-url
value: $(body.repository.clone_url)
- name: git-revision
value: $(body.ref)
- name: git-repo-name
value: $(body.repository.name)
---
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: github-listener
spec:
serviceAccountName: tekton-triggers-sa
triggers:
- name: github-push-trigger
bindings:
- ref: github-binding
template:
ref: github-pipeline-template
Expose the EventListener to receive webhooks from GitHub:
kubectl port-forward service/el-github-listener 8080:8080 --namespace default
Configure your GitHub repository webhook to point to http://your-cluster:8080 with content type application/json.
Best Practices
1. Reuse Tasks from the Tekton Catalog
Before writing custom Tasks, check the Tekton Hub and Catalog for existing, community-maintained Tasks. These are tested, documented, and regularly updated. Reusing them reduces maintenance burden and promotes consistency.
2. Use Workspaces Instead of PipelineResources
PipelineResources are deprecated. Always use workspaces for sharing data between Tasks. They are more flexible, support multiple volume types, and integrate cleanly with Kubernetes storage primitives.
3. Keep Tasks Small and Focused
Each Task should perform a single logical operation. This improves reusability, simplifies debugging, and allows parallel execution where possible. Compose complex workflows by chaining focused Tasks in Pipelines.
4. Secure Sensitive Data with Secrets
Never hardcode credentials in Task or Pipeline definitions. Use Kubernetes Secrets bound to workspaces or environment variables. For registry credentials, use the dockerconfig workspace type with Kaniko or other build tools.
5. Use VolumeClaimTemplates for PipelineRuns
When using volumeClaimTemplate in a PipelineRun, Tekton automatically creates and cleans up a PVC for each run. This prevents storage leaks and ensures isolation between pipeline executions.
6. Implement Proper Error Handling
Use the onError field and finally tasks to handle failures gracefully. finally tasks always execute, regardless of whether the pipeline succeeds or fails, making them ideal for cleanup and notification:
spec:
tasks:
- name: build
taskRef:
name: build-task
finally:
- name: cleanup
taskRef:
name: cleanup-task
- name: notify-slack
taskRef:
name: slack-notify
params:
- name: status
value: "$(tasks.build.status)"
7. Leverage Tekton Results for Observability
Tekton Results is an optional component that stores pipeline execution history in a database, enabling long-term auditing and querying. For production deployments, install Tekton Results to maintain a persistent record of pipeline executions.
8. Set Resource Limits on Steps
Define CPU and memory limits on individual steps to prevent runaway tasks from consuming cluster resources:
steps:
- name: build
image: golang:1.21
resources:
requests:
memory: 512Mi
cpu: 500m
limits:
memory: 1Gi
cpu: 1000m
script: |
go build ./...
9. Use Tekton Chains for Supply Chain Security
Tekton Chains is a Kubernetes CRD controller that enables signing and attestation of pipeline artifacts. It integrates with Sigstore, OCI registries, and storage backends to provide provenance metadata for built images, supporting SLSA compliance.
10. Version Your Pipeline Definitions
Store all Tekton resource definitions in Git alongside your application code. Use GitOps principles to manage pipeline configurations, enabling version control, code review, and rollback capabilities for your CI/CD infrastructure itself.
Conclusion
Tekton provides a robust, Kubernetes-native foundation for building scalable and portable CI/CD pipelines. By leveraging its composable architecture of Tasks, Pipelines, workspaces, and triggers, development teams can create sophisticated delivery workflows that integrate seamlessly with their existing Kubernetes infrastructure. The decoupled design promotes reuse across projects, while the event-driven capabilities of Tekton Triggers enable fully automated, GitOps-style deployments. As organizations continue adopting cloud-native practices, Tekton's vendor-neutral, community-driven approach positions it as a compelling choice for teams seeking a flexible and future-proof CI/CD platform. Start small with individual Tasks, gradually compose them into Pipelines, and incorporate triggers and chains as your delivery maturity grows.