Skip to main content

Kubernetes Tekton

Introduction

Tekton is a powerful, flexible, and Kubernetes-native framework for creating continuous integration and continuous delivery (CI/CD) systems. Developed as part of the CD Foundation (a Linux Foundation project), Tekton provides a set of shared, open-source components for building CI/CD pipelines that can be used across cloud providers and on-premises systems.

Unlike traditional CI/CD tools that run alongside Kubernetes, Tekton is built specifically to leverage Kubernetes' capabilities and runs entirely on a Kubernetes cluster. This native integration allows Tekton to take full advantage of Kubernetes' scaling, resource management, and extensibility features.

Understanding Tekton Core Concepts

Tekton introduces several custom resources to Kubernetes that form the building blocks of a CI/CD pipeline:

Task

A Task is the smallest building block in Tekton. It defines a series of steps that run sequentially in a pod to achieve a specific goal, such as compiling code, running tests, or building a container image.

yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: hello-world
spec:
steps:
- name: say-hello
image: ubuntu
command:
- echo
args:
- "Hello, Tekton!"

TaskRun

A TaskRun is an instance of a Task execution. It defines the inputs, outputs, and execution parameters for a Task.

yaml
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: hello-world-run
spec:
taskRef:
name: hello-world

Output:

TaskRun hello-world-run started
Step say-hello completed with output: Hello, Tekton!
TaskRun hello-world-run succeeded

Pipeline

A Pipeline defines a collection of Tasks that should be executed in a specific order, with defined inputs, outputs, and parameters.

yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: build-test-deploy
spec:
tasks:
- name: build
taskRef:
name: build-app
- name: test
taskRef:
name: test-app
runAfter:
- build
- name: deploy
taskRef:
name: deploy-app
runAfter:
- test

PipelineRun

A PipelineRun is an instance of Pipeline execution, defining the parameters, resources, and service accounts to use for the Pipeline.

yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: build-test-deploy-run
spec:
pipelineRef:
name: build-test-deploy

PipelineResource (Deprecated)

PipelineResource was a concept for defining input and output resources for Tasks and Pipelines. However, it's been deprecated in favor of using parameters and workspaces.

Workspaces

Workspaces provide a mechanism for Tasks to share data. They can be backed by various volume types such as PersistentVolumeClaims, ConfigMaps, or Secrets.

yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: task-with-workspace
spec:
workspaces:
- name: source-code
steps:
- name: list-files
image: ubuntu
command: ["ls"]
args: ["-la", "$(workspaces.source-code.path)"]

Setting Up Tekton

Let's walk through setting up Tekton on your Kubernetes cluster:

Prerequisites

  • A running Kubernetes cluster (v1.18 or newer)
  • kubectl installed and configured
  • Cluster admin permissions

Installation Steps

  1. Install Tekton Pipelines:
bash
kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
  1. Verify the installation:
bash
kubectl get pods -n tekton-pipelines

You should see several Tekton controller pods running.

  1. (Optional) Install Tekton Dashboard:
bash
kubectl apply -f https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml
  1. (Optional) Install Tekton CLI (tkn):
bash
# For macOS
brew tap tektoncd/tools
brew install tektoncd/tools/tektoncd-cli

# For Linux
curl -LO https://github.com/tektoncd/cli/releases/download/v0.30.0/tkn_0.30.0_Linux_x86_64.tar.gz
tar xvzf tkn_0.30.0_Linux_x86_64.tar.gz -C /usr/local/bin/ tkn

Building Your First Tekton Pipeline

Let's create a simple CI pipeline for a Node.js application:

1. Create a Task for cloning a Git repository

yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: git-clone
spec:
workspaces:
- name: output
params:
- name: url
type: string
description: Git repository URL
steps:
- name: clone
image: alpine/git
script: |
git clone $(params.url) $(workspaces.output.path)/source

Save this as git-clone-task.yaml and apply:

bash
kubectl apply -f git-clone-task.yaml

2. Create a Task for testing the Node.js application

yaml
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: npm-test
spec:
workspaces:
- name: source
steps:
- name: install-and-test
image: node:16
workingDir: $(workspaces.source.path)/source
script: |
npm install
npm test

Save this as npm-test-task.yaml and apply:

bash
kubectl apply -f npm-test-task.yaml

3. Create a Pipeline combining these Tasks

yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: nodejs-test-pipeline
spec:
workspaces:
- name: shared-workspace
params:
- name: repo-url
type: string
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

Save this as nodejs-pipeline.yaml and apply:

bash
kubectl apply -f nodejs-pipeline.yaml

4. Create a PersistentVolumeClaim for the workspace

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pipeline-workspace
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

Save this as workspace-pvc.yaml and apply:

bash
kubectl apply -f workspace-pvc.yaml

5. Run the Pipeline

yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: nodejs-test-run
spec:
pipelineRef:
name: nodejs-test-pipeline
workspaces:
- name: shared-workspace
persistentVolumeClaim:
claimName: pipeline-workspace
params:
- name: repo-url
value: https://github.com/example/nodejs-sample-app

Save this as pipeline-run.yaml and apply:

bash
kubectl apply -f pipeline-run.yaml

6. Monitor the Pipeline execution

bash
kubectl get pipelineruns
kubectl describe pipelinerun nodejs-test-run

Or, if you installed the Tekton CLI:

bash
tkn pipelinerun describe nodejs-test-run
tkn pipelinerun logs nodejs-test-run -f

Advanced Tekton Features

Triggers

Tekton Triggers allow you to automate pipeline execution in response to events like webhook calls from GitHub, GitLab, or other systems.

Here's a simple example of creating a Trigger for GitHub webhooks:

yaml
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: github-template
spec:
params:
- name: gitrepositoryurl
- name: gitrevision
resourcetemplates:
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: nodejs-test-run-
spec:
pipelineRef:
name: nodejs-test-pipeline
workspaces:
- name: shared-workspace
persistentVolumeClaim:
claimName: pipeline-workspace
params:
- name: repo-url
value: $(tt.params.gitrepositoryurl)
---
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: github-binding
spec:
params:
- name: gitrepositoryurl
value: $(body.repository.url)
- name: gitrevision
value: $(body.head_commit.id)
---
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: github-listener
spec:
triggers:
- bindings:
- ref: github-binding
template:
ref: github-template

Conditions

Tekton Conditions allow you to specify criteria that must be met before a Task is executed:

yaml
apiVersion: tekton.dev/v1alpha1
kind: Condition
metadata:
name: file-exists
spec:
params:
- name: file-path
type: string
check:
image: alpine
script: |
if [ -f $(params.file-path) ]; then
exit 0
else
exit 1
fi

Then in your Pipeline:

yaml
tasks:
- name: conditional-task
conditions:
- conditionRef: file-exists
params:
- name: file-path
value: "$(workspaces.source.path)/package.json"
taskRef:
name: npm-test
# ...

When Expressions

When expressions provide a more powerful way to conditionally execute tasks:

yaml
tasks:
- name: build-on-main
when:
- input: "$(params.git-branch)"
operator: in
values: ["main", "master"]
taskRef:
name: build-app
# ...

Custom Tasks

Custom Tasks allow you to extend Tekton's functionality by implementing your own Task controllers:

yaml
apiVersion: tekton.dev/v1beta1
kind: CustomTask
metadata:
name: slack-notification
spec:
params:
- name: message
value: "Pipeline completed successfully!"

Real-World Application: Complete CI/CD Pipeline

Let's build a more complete example of a CI/CD pipeline for a containerized application:

Here's how this would look in Tekton:

yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: complete-cicd-pipeline
spec:
workspaces:
- name: shared-workspace
- name: docker-credentials
params:
- name: repo-url
type: string
- name: image-name
type: string
- name: image-tag
type: string
default: latest
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-image
taskRef:
name: kaniko-build
runAfter:
- run-tests
workspaces:
- name: source
workspace: shared-workspace
- name: docker-config
workspace: docker-credentials
params:
- name: IMAGE
value: $(params.image-name):$(params.image-tag)
- name: DOCKERFILE
value: ./Dockerfile

- name: deploy-to-cluster
taskRef:
name: kubectl-deploy
runAfter:
- build-image
workspaces:
- name: manifests
workspace: shared-workspace
params:
- name: image
value: $(params.image-name):$(params.image-tag)
- name: manifest_dir
value: k8s/

- name: notify
taskRef:
name: slack-notification
runAfter:
- deploy-to-cluster
params:
- name: message
value: "Deployment of $(params.image-name):$(params.image-tag) completed successfully!"

Best Practices for Tekton Pipelines

  1. Reuse Tasks: Create general-purpose, reusable Tasks and share them across your organization.

  2. Use Workspaces Effectively: Use workspaces to share data between Tasks rather than passing large amounts of data as parameters.

  3. Parameterize Everything: Make your Pipelines and Tasks flexible by parameterizing values.

  4. Organize with Labels: Use consistent labeling for all your Tekton resources to help with organization and querying.

  5. Implement Timeouts: Set appropriate timeouts for your Tasks and Pipelines to prevent stuck runs.

  6. Handle Failures Gracefully: Implement proper error handling and notifications for pipeline failures.

  7. Secure Your Pipelines: Use Kubernetes secrets for sensitive information and implement proper RBAC.

  8. Monitor Pipeline Performance: Set up monitoring and alerting for your Tekton pipelines.

Debugging Tekton Pipelines

When your pipelines don't work as expected, here are some debugging strategies:

  1. Check the status of your PipelineRun:

    bash
    kubectl describe pipelinerun <pipelinerun-name>
  2. Examine the logs of a specific TaskRun:

    bash
    kubectl logs -l tekton.dev/taskRun=<taskrun-name> -c step-<step-name>
  3. Use the Tekton CLI for more detailed information:

    bash
    tkn pipelinerun logs <pipelinerun-name> -f
  4. Check events in the namespace:

    bash
    kubectl get events

Integrating Tekton with Other Tools

Tekton works well with various other tools in the Kubernetes ecosystem:

  • Argo CD: Use Tekton for CI and Argo CD for GitOps-based CD
  • Prometheus/Grafana: Monitor your Tekton pipelines
  • Vault: Securely manage secrets for your pipelines
  • Knative: Deploy serverless applications from your Tekton pipelines
  • Kustomize/Helm: Package and customize your Kubernetes manifests

Summary

Tekton provides a powerful, Kubernetes-native way to build CI/CD pipelines. Its key advantages include:

  • Kubernetes-native: Runs entirely on Kubernetes, leveraging its features
  • Declarative: Pipelines and tasks are defined as Kubernetes custom resources
  • Modular: Build reusable components that can be shared across teams
  • Scalable: Automatically scales with your Kubernetes cluster
  • Extensible: Create custom tasks and extend functionality
  • Vendor-neutral: Works with any cloud provider or on-premises Kubernetes cluster

By mastering Tekton, you'll be able to create sophisticated CI/CD pipelines that integrate seamlessly with your Kubernetes environment.

Additional Resources

Exercises

  1. Create a simple Tekton pipeline that clones a GitHub repository and counts the lines of code.
  2. Extend the pipeline to run unit tests and report results.
  3. Build a complete CI/CD pipeline for a sample application that builds a container image and deploys it to your Kubernetes cluster.
  4. Implement a webhook-triggered pipeline using Tekton Triggers.
  5. Create a custom Task that sends pipeline results to your preferred messaging platform.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)