Studying Tekton: A Kubernetes-Native CI/CD Tool

4 minute read

What is Tekton?

Tekton is a Kubernetes-native CI/CD tool that provides developers with a robust framework for building and deploying applications in a container-based environment. It leverages Kubernetes resources, allowing seamless integration with existing Kubernetes infrastructure. Tekton comes with a comprehensive set of tools for building, testing, and deploying applications while offering a large library of reusable components to simplify the automation process.

Why Learn Tekton?

My interest in Tekton arose from its Kubernetes-native design. As I explore the Kubernetes ecosystem, understanding how tools are built and operate within this environment is essential. During my learning journey, I built a CI/CD pipeline for both my homelab and cloud environment using Terraform, integrating a GitHub trigger. My goal was to compare the difficulty of replicating the same pipeline setup I have in GitHub Actions using Tekton.

The Tekton Pipeline

Disclaimer: This section assumes the reader is familiar with Kubernetes concepts such as secrets, namespaces, services, and persistent volume claims.

Understanding the Tekton Flow

Tekton Flow

Looking at the Tekton flow diagram, the architecture seems straightforward, but for a newcomer, it can be moderately challenging. Tekton can function without triggers by allowing manual pipeline or task execution. However, I prefer automation, requiring webhooks, triggers, and other integrations.

One of my motivations for writing this post is the lack of clear documentation on GitHub integration with Tekton. Making my pipeline work 100% required learning through trial and error.

Tekton Triggers

This is the typical pattern for creating a trigger for a GitHub webhook. The EventListener creates a Kubernetes service that receives incoming webhooks and sends the request to the EventListener pod. Based on the configured interceptors, the EventListener decides whether to process the request. If the request is approved, the trigger extracts required information like the GitHub repository URL and commit SHA using a TriggerBinding. Finally, it uses this data to populate the TriggerTemplate, which references the corresponding pipeline that needs to be executed.

Event Listener Configuration:

 1apiVersion: triggers.tekton.dev/v1alpha1
 2kind: EventListener
 3metadata:
 4  name: github-pr
 5  namespace: tekton-pipelines
 6spec:
 7  serviceAccountName: tekton-triggers-sa
 8  triggers:
 9    - name: github-listener
10      interceptors:
11        - ref:
12            name: "github"
13          params:
14            - name: "secretRef"
15              value:
16                secretName: github-interceptor-secret
17                secretKey: secretToken
18            - name: "eventTypes"
19              value: ["pull_request", "push"]
20        - ref:
21            name: "cel"
22          params:
23            - name: "filter"
24              value: "body.action in ['opened', 'synchronize', 'reopened']"
25      bindings:
26        - ref: github-pr-binding
27      template:
28        ref: github-pr-pipeline-plan-template

Trigger Binding Configuration:

 1apiVersion: triggers.tekton.dev/v1alpha1
 2kind: TriggerBinding
 3metadata:
 4  name: github-pr-binding
 5  namespace: tekton-pipelines
 6spec:
 7  params:
 8    - name: gitrepositoryurl
 9      value: $(body.repository.clone_url)
10    - name: gitrevision
11      value: $(body.pull_request.head.sha)

Trigger Template Configuration:

 1apiVersion: triggers.tekton.dev/v1alpha1
 2kind: TriggerTemplate
 3metadata:
 4  name: github-push-pipeline-apply-template
 5  namespace: tekton-pipelines
 6spec:
 7  params:
 8    - name: gitrevision
 9      description: The git revision (SHA)
10      default: "$(body.head_commit.id)"
11    - name: gitrepositoryurl
12      description: The git repository URL
13  resourcetemplates:
14    - apiVersion: tekton.dev/v1
15      kind: PipelineRun
16      metadata:
17        generateName: github-push-pipeline-apply-run-
18      spec:
19        pipelineRef:
20          name: github-push-pipeline-apply
21        workspaces:
22          - name: tekton-pipeline
23            persistentVolumeClaim:
24              claimName: tekton-pipeline
25        params:
26          - name: gitrevision
27            value: "$(tt.params.gitrevision)"
28          - name: gitrepositoryurl
29            value: $(tt.params.gitrepositoryurl)

Pipeline Execution

After the trigger fires, the pipeline reference executes:

Pipeline Configuration:

 1apiVersion: tekton.dev/v1
 2kind: Pipeline
 3metadata:
 4  name: github-push-pipeline-apply
 5  namespace: tekton-pipelines
 6spec:
 7  workspaces:
 8    - name: tekton-pipeline
 9  params:
10    - name: gitrepositoryurl
11      description: Git repository URL
12    - name: gitrevision
13      description: Git revision to checkout
14  tasks:
15    - name: aws-cloud-terraform-shared-resources-apply
16      taskRef:
17        name: aws-cloud-terraform-shared-resources-apply
18      params:
19        - name: gitrepositoryurl
20          value: $(params.gitrepositoryurl)
21        - name: gitrevision
22          value: $(params.gitrevision)
23      workspaces:
24        - name: tekton-pipeline
25          workspace: tekton-pipeline

Task Execution

Task Definition:

 1apiVersion: tekton.dev/v1
 2kind: Task
 3metadata:
 4  name: aws-cloud-terraform-shared-resources-apply
 5  namespace: tekton-pipelines
 6spec:
 7  workspaces:
 8    - name: tekton-pipeline
 9  params:
10    - name: gitrepositoryurl
11      description: Git repository URL
12    - name: gitrevision
13      description: Git revision to checkout
14  stepTemplate:
15    env:
16      - name: AWS_ACCESS_KEY_ID
17        valueFrom:
18          secretKeyRef:
19            name: tekton-aws-creds
20            key: AWS_ACCESS_KEY_ID
21      - name: AWS_SECRET_ACCESS_KEY
22        valueFrom:
23          secretKeyRef:
24            name: tekton-aws-creds
25            key: AWS_SECRET_ACCESS_KEY
26      - name: AWS_REGION
27        valueFrom:
28          secretKeyRef:
29            name: tekton-aws-creds
30            key: AWS_REGION
31  steps:
32    - name: git-clone
33      image: alpine/git
34      script: |
35        #!/bin/sh
36        rm -rf /workspace/tekton-pipeline/*
37        git clone $(params.gitrepositoryurl) /workspace/tekton-pipeline/repo
38        cd /workspace/tekton-pipeline/repo
39        git checkout $(params.gitrevision)        
40      workingDir: /workspace/tekton-pipeline
41    - name: terraform-init
42      image: hashicorp/terraform
43      script: |
44        #!/bin/sh
45        cd /workspace/tekton-pipeline/repo/aws/terraform/shared-resources
46        terraform init        
47    - name: terraform-apply
48      image: hashicorp/terraform
49      script: |
50        #!/bin/sh
51        cd /workspace/tekton-pipeline/repo/aws/terraform/shared-resources
52        terraform apply        

A pipeline in Tekton is essentially a collection of tasks, and each task is composed of multiple steps. Each step defines a specific action that can be performed, similar to stages in GitHub Actions or GitLab CI. These steps can execute public or private container images and run custom scripts or commands through an entry point.

Final Thoughts

What I like about Tekton is its dashboard, allowing users to manage pipelines, view logs, and rerun or edit tasks. Compared to GitHub Actions, GitLab CI, or Jenkins, Tekton is a powerful tool that integrates well with Kubernetes-native tools like Helm. I will continue using Tekton to manage my homelab, learn more, and possibly contribute to the community.