Tekton is a Kubernetes-native open-source framework for building continuous integration and delivery (CI/CD) pipelines. Unlike Jenkins or GitLab CI, Tekton runs entirely as Kubernetes Custom Resource Definitions (CRDs), meaning every pipeline, task, and run is a Kubernetes object you manage with kubectl — no separate CI server to maintain. This cloud-native approach gives you full portability across any Kubernetes cluster: on-premises, managed, or bare-metal. This guide covers installing Tekton Pipelines on a Kubernetes cluster running on Red Hat Enterprise Linux 9, writing reusable Tasks, assembling them into a Pipeline that clones a Git repository, builds a Docker image, and deploys to the cluster, and monitoring runs through the Tekton Dashboard.

Prerequisites

  • RHEL 9 server with a running Kubernetes cluster (k3s, kubeadm, or OpenShift) and kubectl configured
  • kubectl version 1.24 or later with cluster-admin privileges
  • A container registry (Docker Hub, Quay.io, or private) with push credentials
  • A Git repository containing a Dockerfile at the repository root
  • At least 2 CPU cores and 4 GB RAM available in the cluster for pipeline pods

Step 1 — Install Tekton Pipelines

Tekton Pipelines is installed by applying a single manifest that creates all required CRDs, RBAC objects, and the pipeline controller and webhook deployments in the tekton-pipelines namespace.

kubectl apply --filename 
  https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

# Wait for the controller and webhook to become ready
kubectl wait --for=condition=ready pod 
  --selector=app=tekton-pipelines-controller 
  --namespace=tekton-pipelines 
  --timeout=120s

kubectl get pods --namespace tekton-pipelines

Step 2 — Understand Core Tekton Concepts

Before writing YAML, understand the four key abstractions. A Task is a reusable unit of work composed of ordered Steps, each running in its own container. A TaskRun instantiates a Task with concrete parameter values and executes it. A Pipeline chains multiple Tasks together, optionally passing outputs as inputs between them. A PipelineRun instantiates a Pipeline and triggers the full execution. Create a Kubernetes Secret to hold your container registry credentials:

kubectl create secret docker-registry registry-credentials 
  --docker-server=https://index.docker.io/v1/ 
  --docker-username=YOUR_USERNAME 
  --docker-password=YOUR_PASSWORD 
  --docker-email=YOUR_EMAIL

kubectl create serviceaccount pipeline-sa
kubectl patch serviceaccount pipeline-sa 
  -p '{"secrets":[{"name":"registry-credentials"}]}'

Step 3 — Write a Task to Build a Docker Image

The following Task uses kaniko — a daemonless Docker image builder — to build and push an image from a cloned workspace. Save it as task-build-image.yaml and apply it to the cluster.

# task-build-image.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: build-and-push
spec:
  params:
    - name: image
      description: Full image name including tag
    - name: context
      default: "."
  workspaces:
    - name: source
  steps:
    - name: build-push
      image: gcr.io/kaniko-project/executor:latest
      args:
        - --context=$(workspaces.source.path)/$(params.context)
        - --destination=$(params.image)
        - --dockerfile=$(workspaces.source.path)/Dockerfile
      volumeMounts:
        - name: docker-config
          mountPath: /kaniko/.docker
  volumes:
    - name: docker-config
      secret:
        secretName: registry-credentials
        items:
          - key: .dockerconfigjson
            path: config.json
kubectl apply -f task-build-image.yaml

Step 4 — Assemble a Multi-Stage Pipeline

This Pipeline chains three tasks: the Tekton Catalog’s git-clone task, the custom build-and-push task, and a simple kubectl deploy step. Tasks share data through a PersistentVolumeClaim-backed workspace.

# Install the git-clone task from Tekton Hub
kubectl apply -f 
  https://api.hub.tekton.dev/v1/resource/tekton/task/git-clone/0.9/raw

# pipeline.yaml
cat <<EOF | kubectl apply -f -
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: build-deploy-pipeline
spec:
  params:
    - name: repo-url
    - name: image-name
  workspaces:
    - name: shared-workspace
  tasks:
    - name: clone
      taskRef:
        name: git-clone
      workspaces:
        - name: output
          workspace: shared-workspace
      params:
        - name: url
          value: $(params.repo-url)
    - name: build
      runAfter: [clone]
      taskRef:
        name: build-and-push
      workspaces:
        - name: source
          workspace: shared-workspace
      params:
        - name: image
          value: $(params.image-name)
    - name: deploy
      runAfter: [build]
      taskSpec:
        steps:
          - name: kubectl-apply
            image: bitnami/kubectl:latest
            script: |
              kubectl set image deployment/myapp app=$(params.image-name) 
                --record
      params:
        - name: image-name
          value: $(params.image-name)
EOF

Step 5 — Run the Pipeline and Monitor Progress

Create a PersistentVolumeClaim for the shared workspace, then submit a PipelineRun to trigger execution. Use tkn CLI or kubectl to tail logs.

# Create the workspace PVC
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pipeline-workspace-pvc
spec:
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 1Gi
EOF

# Submit a PipelineRun
kubectl create -f - <<EOF
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  generateName: build-deploy-run-
spec:
  pipelineRef:
    name: build-deploy-pipeline
  params:
    - name: repo-url
      value: https://github.com/YOUR_ORG/YOUR_REPO.git
    - name: image-name
      value: docker.io/YOUR_USERNAME/myapp:latest
  workspaces:
    - name: shared-workspace
      persistentVolumeClaim:
        claimName: pipeline-workspace-pvc
EOF

# Follow logs (install tkn CLI from https://github.com/tektoncd/cli)
tkn pipelinerun logs --last -f

Step 6 — Install the Tekton Dashboard

The Tekton Dashboard provides a web UI for browsing PipelineRuns, TaskRuns, and logs without requiring CLI access.

kubectl apply --filename 
  https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml

# Port-forward to access the dashboard locally
kubectl port-forward --namespace tekton-pipelines 
  service/tekton-dashboard 9097:9097 &

# Open http://localhost:9097 in your browser

Conclusion

You now have a fully functional Tekton CI/CD pipeline running natively on Kubernetes that clones source code, builds a container image with kaniko, and deploys it to the cluster — all without a dedicated CI server. The key strength of Tekton is composability: Tasks are independently versioned and reusable across Pipelines, and the Tekton Hub at hub.tekton.dev provides hundreds of community-maintained Tasks for common operations. For production, store PipelineRun triggers in a TriggerTemplate and EventListener to automatically launch pipelines on Git push events, and configure a ClusterTask to make your Tasks available cluster-wide across all namespaces.

Next steps: How to Set Up Argo CD for GitOps on Kubernetes on RHEL 9, How to Install Jenkins on Kubernetes with Helm on RHEL 9, and How to Configure GitHub Actions Self-Hosted Runners on RHEL 9.