โ† Back to DevBytes

Tekton CI/CD Pipelines: Complete Implementation Guide

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:

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:

Supporting Resources

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

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.

๐Ÿ›  Tools from DevBytes

Inventory Tracker Pro โ€” Excel inventory system, low-stock alerts ยท $19
AI Dev Kit for Mac โ€” local AI dev environment templates ยท $9.99
KeyMapper for Mac โ€” custom keyboard shortcut toolkit ยท $7.99

โ† Back to all articles