| name | cicd-tekton-pipelines-dev |
| description | Develop and troubleshoot Tekton Pipelines on Kubernetes. Use when creating cloud-native CI/CD pipelines, debugging TaskRuns and PipelineRuns, understanding Tekton CRDs, or building reusable Tasks and Pipelines. |
Tekton Pipelines Development
Guide for developing, debugging, and optimizing Tekton Pipelines - the Kubernetes-native CI/CD framework.
When to Use This Skill
- Creating Kubernetes-native CI/CD pipelines
- Debugging TaskRuns and PipelineRuns
- Building reusable Tasks for Tekton Hub
- Understanding Tekton CRDs and architecture
- Integrating with Tekton Triggers for GitOps
- Optimizing pipeline performance on Kubernetes
Core Concepts
Tekton Architecture
┌─────────────────────────────────────────────────────────────┐
│ Tekton Components │
├─────────────────────────────────────────────────────────────┤
│ │
│ Task ─────────► TaskRun │
│ │ │ │
│ ├── Steps ├── Pod (one per TaskRun) │
│ ├── Params ├── Containers (one per Step) │
│ ├── Workspaces └── Status │
│ └── Results │
│ │
│ Pipeline ─────► PipelineRun │
│ │ │ │
│ ├── Tasks ├── TaskRuns (one per Task) │
│ ├── Params ├── PVCs (for Workspaces) │
│ ├── Workspaces └── Status │
│ └── Results │
│ │
│ Trigger ─────► EventListener ─────► PipelineRun │
│ │ │
│ ├── TriggerBinding (extract data) │
│ └── TriggerTemplate (create resources) │
│ │
└─────────────────────────────────────────────────────────────┘
Custom Resource Definitions (CRDs)
| CRD | Purpose |
|---|---|
Task |
Reusable unit of work (collection of steps) |
TaskRun |
Execution instance of a Task |
Pipeline |
Ordered collection of Tasks |
PipelineRun |
Execution instance of a Pipeline |
TriggerTemplate |
Template for creating PipelineRuns |
TriggerBinding |
Extracts data from events |
EventListener |
Listens for incoming events |
Task Definition
Basic Task
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: build-push
spec:
params:
- name: image
type: string
description: Image name to build
- name: dockerfile
type: string
default: ./Dockerfile
workspaces:
- name: source
description: Source code workspace
results:
- name: image-digest
description: Digest of the built image
steps:
- name: build
image: gcr.io/kaniko-project/executor:latest
args:
- --dockerfile=$(params.dockerfile)
- --destination=$(params.image)
- --context=$(workspaces.source.path)
- --digest-file=$(results.image-digest.path)
Step Configuration
steps:
- name: run-tests
image: node:20
workingDir: $(workspaces.source.path)
script: |
#!/usr/bin/env bash
set -ex
npm ci
npm test
env:
- name: NODE_ENV
value: test
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: my-secret
key: api-key
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 1Gi
cpu: 500m
Sidecars
spec:
steps:
- name: test
image: node:20
script: |
npm test
sidecars:
- name: postgres
image: postgres:15
env:
- name: POSTGRES_PASSWORD
value: test
readinessProbe:
exec:
command: ["pg_isready", "-U", "postgres"]
Pipeline Definition
Basic Pipeline
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: ci-pipeline
spec:
params:
- name: repo-url
type: string
- name: image-name
type: string
workspaces:
- name: shared-workspace
- name: docker-credentials
tasks:
- name: fetch-source
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-workspace
params:
- name: url
value: $(params.repo-url)
- name: run-tests
taskRef:
name: npm-test
runAfter:
- fetch-source
workspaces:
- name: source
workspace: shared-workspace
- name: build-push
taskRef:
name: kaniko
runAfter:
- run-tests
workspaces:
- name: source
workspace: shared-workspace
- name: dockerconfig
workspace: docker-credentials
params:
- name: IMAGE
value: $(params.image-name)
Parallel Tasks
spec:
tasks:
- name: fetch-source
taskRef:
name: git-clone
# These run in parallel after fetch-source
- name: lint
taskRef:
name: npm-lint
runAfter:
- fetch-source
- name: unit-test
taskRef:
name: npm-test
runAfter:
- fetch-source
- name: security-scan
taskRef:
name: trivy-scan
runAfter:
- fetch-source
# This waits for all three
- name: build
taskRef:
name: build-push
runAfter:
- lint
- unit-test
- security-scan
Conditional Execution (when)
tasks:
- name: deploy-staging
when:
- input: $(params.environment)
operator: in
values: ["staging", "all"]
taskRef:
name: kubectl-deploy
params:
- name: namespace
value: staging
- name: deploy-production
when:
- input: $(params.environment)
operator: in
values: ["production"]
- input: $(tasks.run-tests.results.passed)
operator: in
values: ["true"]
taskRef:
name: kubectl-deploy
params:
- name: namespace
value: production
Matrix (Fan-out)
tasks:
- name: test-matrix
taskRef:
name: npm-test
matrix:
params:
- name: node-version
value:
- "18"
- "20"
- "22"
- name: os
value:
- "linux"
- "darwin"
Running Pipelines
TaskRun
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
generateName: build-push-run-
spec:
taskRef:
name: build-push
params:
- name: image
value: gcr.io/myproject/myapp:latest
workspaces:
- name: source
persistentVolumeClaim:
claimName: source-pvc
PipelineRun
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
generateName: ci-pipeline-run-
spec:
pipelineRef:
name: ci-pipeline
params:
- name: repo-url
value: https://github.com/org/repo
- name: image-name
value: gcr.io/myproject/myapp:v1
workspaces:
- name: shared-workspace
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- name: docker-credentials
secret:
secretName: docker-credentials
Using tkn CLI
# Start a PipelineRun
tkn pipeline start ci-pipeline \
-p repo-url=https://github.com/org/repo \
-p image-name=gcr.io/myproject/myapp:v1 \
-w name=shared-workspace,claimName=my-pvc \
--showlog
# Start a TaskRun
tkn task start build-push \
-p image=myimage:latest \
-w name=source,claimName=source-pvc \
--showlog
# List runs
tkn pipelinerun list
tkn taskrun list
# View logs
tkn pipelinerun logs ci-pipeline-run-xyz -f
tkn taskrun logs build-push-run-abc -f
# Describe run
tkn pipelinerun describe ci-pipeline-run-xyz
Tekton Triggers
EventListener
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: github-listener
spec:
serviceAccountName: tekton-triggers-sa
triggers:
- name: github-push
interceptors:
- ref:
name: github
params:
- name: secretRef
value:
secretName: github-secret
secretKey: secret
- name: eventTypes
value: ["push"]
bindings:
- ref: github-push-binding
template:
ref: ci-pipeline-template
TriggerBinding
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: github-push-binding
spec:
params:
- name: repo-url
value: $(body.repository.clone_url)
- name: revision
value: $(body.head_commit.id)
- name: branch
value: $(body.ref)
TriggerTemplate
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: ci-pipeline-template
spec:
params:
- name: repo-url
- name: revision
- name: branch
resourcetemplates:
- apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
generateName: ci-pipeline-run-
spec:
pipelineRef:
name: ci-pipeline
params:
- name: repo-url
value: $(tt.params.repo-url)
- name: revision
value: $(tt.params.revision)
workspaces:
- name: shared-workspace
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Debugging
View Logs
# PipelineRun logs
tkn pipelinerun logs <pipelinerun-name> -f
# TaskRun logs
tkn taskrun logs <taskrun-name> -f
# Specific task in pipeline
tkn pipelinerun logs <pipelinerun-name> -f --task=<task-name>
# Using kubectl
kubectl logs -l tekton.dev/pipelineRun=<pipelinerun-name> -c step-<step-name>
Describe Resources
tkn pipelinerun describe <name>
tkn taskrun describe <name>
kubectl describe pipelinerun <name>
kubectl describe taskrun <name>
kubectl describe pod <taskrun-pod>
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Pod pending | No PVC or node resources | Check PVC binding and node capacity |
| Step fails | Script error or missing deps | Check step logs and image |
| Workspace empty | PVC not mounted correctly | Verify workspace binding |
| Timeout | Task exceeds timeout | Increase timeout in spec |
| Permission denied | RBAC issues | Check ServiceAccount permissions |
Debug Step
Add a debug step to inspect workspace:
steps:
- name: debug
image: busybox
script: |
echo "=== Workspace contents ==="
ls -la $(workspaces.source.path)
echo "=== Environment ==="
env | sort
Workspaces
Types
workspaces:
# PersistentVolumeClaim
- name: source
persistentVolumeClaim:
claimName: my-pvc
# VolumeClaimTemplate (created per-run)
- name: source
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
# Secret
- name: credentials
secret:
secretName: docker-credentials
# ConfigMap
- name: config
configMap:
name: my-config
# EmptyDir (ephemeral)
- name: temp
emptyDir: {}
Results and Parameters
Passing Results Between Tasks
# Task that produces result
spec:
results:
- name: image-digest
description: The image digest
steps:
- name: build
script: |
echo -n "sha256:abc123" > $(results.image-digest.path)
# Pipeline consuming result
tasks:
- name: build
taskRef:
name: build-image
- name: deploy
taskRef:
name: deploy
params:
- name: digest
value: $(tasks.build.results.image-digest)
Tekton Hub Tasks
Use pre-built tasks from Tekton Hub:
# Install a task
tkn hub install task git-clone
# Search for tasks
tkn hub search build
Common Hub Tasks:
| Task | Purpose |
|---|---|
git-clone |
Clone git repository |
kaniko |
Build container images |
buildah |
Build OCI images |
trivy-scanner |
Security scanning |
kubectl-actions |
Kubernetes deployments |
helm-upgrade |
Helm deployments |
Performance Optimization
Resource Requests
steps:
- name: build
resources:
requests:
memory: 512Mi
cpu: 250m
limits:
memory: 1Gi
cpu: 1
Workspace Caching
Use a shared PVC for caching:
workspaces:
- name: cache
persistentVolumeClaim:
claimName: build-cache-pvc
Parallel Tasks
Design pipelines with parallel paths where possible.
Timeout Configuration
spec:
timeouts:
pipeline: 1h
tasks: 30m
finally: 15m
Debugging Checklist
- Check PipelineRun/TaskRun status with
tkn describe - View pod logs with
kubectl logs - Verify workspace PVCs are bound
- Check RBAC permissions for ServiceAccount
- Verify image pull secrets if using private registries
- Check resource limits aren't too restrictive
- Verify parameters are passed correctly
- Check results paths are correct