How to Set Up a CI/CD Pipeline with Tekton on Kubernetes on RHEL 7

Tekton is a Kubernetes-native CI/CD framework that defines pipelines as Kubernetes Custom Resource Definitions (CRDs). Unlike Jenkins, which runs as a separate server, or GitLab CI, which requires the GitLab platform, Tekton lives entirely inside your cluster and follows standard Kubernetes RBAC, secrets management, and resource scheduling. On RHEL 7, you interact with a Kubernetes cluster (installed via kubeadm, minikube, or a managed provider such as OpenShift) using kubectl and the Tekton CLI (tkn). This tutorial walks through installing Tekton Pipelines into an existing cluster, writing Task and Pipeline resources, running them with TaskRun and PipelineRun, using PipelineResources for Git and container image inputs and outputs, setting up Tekton Triggers for webhook-driven automation, and accessing the Tekton Dashboard for a visual overview of pipeline runs.

Prerequisites

  • RHEL 7 node with kubectl configured pointing to a running Kubernetes cluster (1.21+)
  • Cluster-admin permissions to install CRDs and cluster-scoped resources
  • At least 2 GB of free cluster memory for Tekton controllers
  • A container registry (Docker Hub, Quay.io, or a private registry) for image output
  • Internet access from cluster nodes to pull Tekton images from gcr.io

Step 1: Install Tekton Pipelines on Kubernetes

Tekton Pipelines is installed by applying a single YAML manifest from the official GitHub releases:

# Install Tekton Pipelines CRDs and controllers
kubectl apply --filename 
  https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

# Watch the Tekton Pipelines pods come up
kubectl get pods --namespace tekton-pipelines --watch

Wait until all pods in the tekton-pipelines namespace are Running:

NAME                                           READY   STATUS    RESTARTS   AGE
tekton-pipelines-controller-7d96c5d4d4-xkzqj   1/1     Running   0          90s
tekton-pipelines-webhook-8569965fbd-2xrwk       1/1     Running   0          90s

Step 2: Install the Tekton CLI (tkn)

The tkn CLI provides a Tekton-aware interface for listing, triggering, and inspecting pipeline runs:

curl -LO https://github.com/tektoncd/cli/releases/download/v0.36.0/tkn_0.36.0_Linux_x86_64.tar.gz
tar xvf tkn_0.36.0_Linux_x86_64.tar.gz tkn
sudo mv tkn /usr/local/bin/
tkn version
# Client version: 0.36.0
# Pipeline version: v0.58.0

Step 3: Write a Task Resource

A Task is the atomic unit of work in Tekton — a sequence of steps, each running a container. Create a task that clones a Git repository and runs unit tests:

cat > task-run-tests.yaml <<'EOF'
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: run-python-tests
  namespace: default
spec:
  params:
    - name: repo-url
      type: string
      description: Git repository URL
    - name: revision
      type: string
      default: main
  workspaces:
    - name: source
      description: Workspace for the cloned source code
  steps:
    - name: clone
      image: alpine/git:v2.43.0
      script: |
        git clone $(params.repo-url) /workspace/source
        cd /workspace/source
        git checkout $(params.revision)

    - name: install-deps
      image: python:3.11-slim
      workingDir: /workspace/source
      script: |
        pip install --quiet -r requirements.txt

    - name: test
      image: python:3.11-slim
      workingDir: /workspace/source
      script: |
        python -m pytest tests/ -v --tb=short
EOF
kubectl apply -f task-run-tests.yaml

Verify the task was registered:

tkn task list
# NAME                AGE
# run-python-tests    5 seconds ago

Step 4: Run a Task with TaskRun

A TaskRun instantiates a Task with concrete parameter values:

cat > taskrun-test.yaml <<'EOF'
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  generateName: run-python-tests-
  namespace: default
spec:
  taskRef:
    name: run-python-tests
  params:
    - name: repo-url
      value: https://github.com/your-org/your-repo.git
    - name: revision
      value: main
  workspaces:
    - name: source
      emptyDir: {}
EOF
kubectl create -f taskrun-test.yaml

Watch the logs in real time:

tkn taskrun logs --last -f

Step 5: Define a Pipeline with Multiple Tasks

A Pipeline orchestrates multiple tasks, passing results between them and optionally running tasks in parallel:

cat > pipeline-ci.yaml <<'EOF'
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
  name: python-ci-pipeline
  namespace: default
spec:
  params:
    - name: repo-url
      type: string
    - name: image-name
      type: string
  workspaces:
    - name: shared-workspace
  tasks:
    - name: fetch-source
      taskRef:
        name: git-clone        # from Tekton Catalog
      params:
        - name: url
          value: $(params.repo-url)
        - name: revision
          value: main
      workspaces:
        - name: output
          workspace: shared-workspace

    - name: run-tests
      runAfter:
        - fetch-source
      taskRef:
        name: run-python-tests
      params:
        - name: repo-url
          value: $(params.repo-url)
      workspaces:
        - name: source
          workspace: shared-workspace

    - name: build-image
      runAfter:
        - run-tests
      taskRef:
        name: kaniko            # from Tekton Catalog
      params:
        - name: IMAGE
          value: $(params.image-name):$(tasks.fetch-source.results.commit)
        - name: DOCKERFILE
          value: ./Dockerfile
        - name: CONTEXT
          value: ./
      workspaces:
        - name: source
          workspace: shared-workspace
EOF
kubectl apply -f pipeline-ci.yaml

Step 6: Run the Pipeline with PipelineRun

cat > pipelinerun-ci.yaml <<'EOF'
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  generateName: python-ci-pipeline-run-
  namespace: default
spec:
  pipelineRef:
    name: python-ci-pipeline
  params:
    - name: repo-url
      value: https://github.com/your-org/your-repo.git
    - name: image-name
      value: quay.io/your-org/your-app
  workspaces:
    - name: shared-workspace
      volumeClaimTemplate:
        spec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 1Gi
EOF
kubectl create -f pipelinerun-ci.yaml

# Watch all task logs
tkn pipelinerun logs --last -f

# List pipeline runs
tkn pipelinerun list

Step 7: Set Up Tekton Triggers for Webhook-Driven Pipelines

Tekton Triggers installs additional CRDs — EventListener, TriggerTemplate, and TriggerBinding — that allow HTTP webhooks (e.g., from GitHub) to automatically create PipelineRuns:

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

kubectl get pods --namespace tekton-pipelines | grep trigger

Create a TriggerBinding that extracts parameters from a GitHub push webhook payload:

cat > trigger-binding.yaml <<'EOF'
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.after)
EOF

cat > trigger-template.yaml <<'EOF'
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: github-push-template
spec:
  params:
    - name: repo-url
    - name: revision
  resourcetemplates:
    - apiVersion: tekton.dev/v1
      kind: PipelineRun
      metadata:
        generateName: triggered-pipeline-run-
      spec:
        pipelineRef:
          name: python-ci-pipeline
        params:
          - name: repo-url
            value: $(tt.params.repo-url)
          - name: image-name
            value: quay.io/your-org/your-app
        workspaces:
          - name: shared-workspace
            volumeClaimTemplate:
              spec:
                accessModes: [ReadWriteOnce]
                resources:
                  requests:
                    storage: 1Gi
EOF

cat > event-listener.yaml <<'EOF'
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: github-listener
spec:
  serviceAccountName: tekton-triggers-sa
  triggers:
    - bindings:
        - ref: github-push-binding
      template:
        ref: github-push-template
EOF

kubectl apply -f trigger-binding.yaml -f trigger-template.yaml -f event-listener.yaml

Step 8: Install and Access the Tekton Dashboard

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

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

Open http://localhost:9097 in a browser. The dashboard shows all TaskRuns and PipelineRuns with their status, logs, and YAML definitions. For production, expose the dashboard through an Ingress controller with TLS and authentication.

Tekton brings the same declarative, YAML-driven philosophy that defines Kubernetes to the CI/CD layer, making your pipelines as observable and reproducible as your application deployments. Running entirely in-cluster means your pipeline steps have direct access to cluster secrets, service accounts, and storage without complex credential injection. From here, explore the Tekton Catalog at hub.tekton.dev for hundreds of pre-built tasks covering linting, container scanning, Helm deployment, and notification steps, saving you from writing boilerplate and letting you compose sophisticated pipelines from well-tested building blocks.