18 January 2024
Reading time 15 min
Tekton: The Powerful Open Source CI/CD Framework
<span id="hs_cos_wrapper_name" class="hs_cos_wrapper hs_cos_wrapper_meta_field hs_cos_wrapper_type_text" style="" data-hs-cos-general-type="meta_field" data-hs-cos-type="text" >Tekton: The Powerful Open Source CI/CD Framework</span>
Share this via:
Tekton: The Powerful Open Source CI/CD Framework
28:57

Tekton, a powerful and flexible open-source framework, empowers developers to build, test, and deploy CI/CD systems, both in the cloud and on-premises. In this article, we delve deeper into what Tekton is, its advantages, and how major companies such as Google, Elastic, and RedHat leverage it.

What is Tekton?

Tekton is an open-source framework designed for developing Continuous Integration and Continuous Deployment (CI/CD) systems. It enables developers to work seamlessly with both cloud providers and on-premise infrastructures. With Tekton, developers can build, test, and deploy pipelines, benefiting from a flexible and extensible architecture.

Benefits of Tekton

Cloud-Native Ecosystem

Tekton leverages Kubernetes clusters to manage resources and components. This enables Tekton to run on various cloud providers and be deployed locally.

Kubernetes Custom Resources

All resources needed to build a pipeline are available as Kubernetes Custom Resources. This means that pipelines can be fully described in YAML files, allowing GitOps principles to be applied for an automated and version-controlled build process.

Extensibility

The core of Tekton is easily extendable with additional components, such as Tekton Triggers or Dashboards. These components are not directly located in the core, keeping it compact and utilizing minimal resources.

Easy Maintenance

Thanks to Tekton's modular design, the core can be upgraded independently without impacting builds. The separation of the core and extensions makes maintenance much simpler.

Scalability

As a Cloud-Native solution, Tekton can easily scale for high availability, making it suitable for a variety of projects and environments.

Tekton Friends: Major Companies Embracing Tekton

Several leading IT companies have adopted Tekton and actively contribute to its development through a GitHub repository. Some notable companies include:

  • Google: The initiator of the Tekton project and an active developer.
  • Elastic: The entire Elastic stack is built and released using the Tekton ecosystem.
  • Red Hat: Ensures seamless operation of the Tekton ecosystem on OpenShift and provides dedicated contributions to the Tekton project.

Tekton Ecosystem: Components and Functionalities

The Tekton ecosystem consists of diverse components that can be deployed collectively or individually. Below is an explanation of some key components.

1. Tekton Pipelines

Tekton Pipelines utilizes Kubernetes Custom Resources to define build processes. Following the 'pipeline-as-code' principle, developers can describe pipelines in YAML files and apply version control with GitOps.

Storing each resource in Git allows working with versions across different Pipeline resources. Moreover, by applying the GitOps principle, the resource is automatically deployed to the cluster, ensuring assurance in consistently having the correct and latest version without any manual handling of Tekton resources.

A Pipeline is a subset of tasks executed in a specific order.
Let's take an example of a Pipeline for building a Docker image:

  • Task 1: Clone Git repository
  • Task 2: Scan for vulnerabilities
  • Task 3: Read Dockerfile and build the image
  • Task 4: Push Docker container images to a registry (https://acagroup.be/en/blog/navigating-the-cloud-native-landscape-with-harbor-registry/)

Now, let's visualize this.

  • Each execution of a pipeline is called a PipelineRun.
  • Each execution of a task is called a TaskRun.


In the pipeline, we define the tasks. These tasks are also individual Tekton Custom Resources residing in Kubernetes. When executing the pipeline, Tekton consults the defined resource and utilizes it to perform its tasks.

Tasks are quite flexible. You can reuse a task repeatedly within a pipeline and even across different pipelines. Tasks can be modified or written from scratch without the need for separately installing plugins or additional resources. A task can be a simple container image executed with specific parameters.

Applying version control to tasks makes it easy to use a different version of the task for each specific purpose. This eliminates the need to upgrade all pipelines when a task is updated.

What Does a Developer Gain from This?

  • Adaptability: All Tekton resources are customizable, enabling developers to write highly detailed pipelines and tasks.
  • Reusability: Pipelines and/or tasks can be deployed repeatedly, both within the same pipeline and across different pipelines.
  • Extensibility: Tekton provides a catalog of pre-configured, commonly used tasks. The resources in this catalog can be downloaded and customized to align with the specific needs of your project.

Example: A Docker Container Image Pipeline


Let's create a pipeline as an example that builds a Docker container image and pushes it to a Docker container registry.

First, we will prepare our Tekton tasks so that we can define them in our Tekton pipeline.

What steps are needed to build a Docker container image?

  1. Git Clone: To fetch our source code.
  2. Git Version: To define a version for our container.
  3. Trivy Scanning: To initially check if our image contains CVEs.
  4. Kaniko Builder: A tool to build a Docker image from a Dockerfile and push it to the registry.
  5. Pipeline Launch: With Tekton PipelineRun, we can define our parameters, such as branch_name, repository_url, and repository_name.
  6. Deployment: Sequentially deploy the resources for testing: Tasks, Pipeline, and PipelineRun.

You can find the corresponding YAML files for each of these tasks on the Tekton Hub.

Tasks

Git Clone

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: git-clone
  labels:
    app.kubernetes.io/version: "0.9"
  annotations:
    tekton.dev/pipelines.minVersion: "0.38.0"
    tekton.dev/categories: Git
    tekton.dev/tags: git
    tekton.dev/displayName: "git clone"
    tekton.dev/platforms: "linux/amd64,linux/s390x,linux/ppc64le,linux/arm64"
spec:
  description: >-
    These Tasks are Git tasks to work with repositories used by other tasks
    in your Pipeline.
 
    The git-clone Task will clone a repo from the provided url into the
    output Workspace. By default the repo will be cloned into the root of
    your Workspace. You can clone into a subdirectory by setting this Task's
    subdirectory param. This Task also supports sparse checkouts. To perform
    a sparse checkout, pass a list of comma separated directory patterns to
    this Task's sparseCheckoutDirectories param.
  workspaces:
    - name: output
      description: The git repo will be cloned onto the volume backing this Workspace.
    - name: ssh-directory
      optional: true
      description: |
        A .ssh directory with private key, known_hosts, config, etc. Copied to
        the user's home before git commands are executed. Used to authenticate
        with the git remote when performing the clone. Binding a Secret to this
        Workspace is strongly recommended over other volume types.
    - name: basic-auth
      optional: true
      description: |
        A Workspace containing a .gitconfig and .git-credentials file. These
        will be copied to the user's home before any git commands are run. Any
        other files in this Workspace are ignored. It is strongly recommended
        to use ssh-directory over basic-auth whenever possible and to bind a
        Secret to this Workspace over other volume types.
    - name: ssl-ca-directory
      optional: true
      description: |
        A workspace containing CA certificates, this will be used by Git to
        verify the peer with when fetching or pushing over HTTPS.
  params:
    - name: url
      description: Repository URL to clone from.
      type: string
    - name: revision
      description: Revision to checkout. (branch, tag, sha, ref, etc...)
      type: string
      default: ""
    - name: refspec
      description: Refspec to fetch before checking out revision.
      default: ""
    - name: submodules
      description: Initialize and fetch git submodules.
      type: string
      default: "true"
    - name: depth
      description: Perform a shallow clone, fetching only the most recent N commits.
      type: string
      default: "1"
    - name: sslVerify
      description: Set the `http.sslVerify` global git config. Setting this to `false` is not advised unless you are sure that you trust your git remote.
      type: string
      default: "true"
    - name: crtFileName
      description: file name of mounted crt using ssl-ca-directory workspace. default value is ca-bundle.crt.
      type: string
      default: "ca-bundle.crt"
    - name: subdirectory
      description: Subdirectory inside the `output` Workspace to clone the repo into.
      type: string
      default: ""
    - name: sparseCheckoutDirectories
      description: Define the directory patterns to match or exclude when performing a sparse checkout.
      type: string
      default: ""
    - name: deleteExisting
      description: Clean out the contents of the destination directory if it already exists before cloning.
      type: string
      default: "true"
    - name: httpProxy
      description: HTTP proxy server for non-SSL requests.
      type: string
      default: ""
    - name: httpsProxy
      description: HTTPS proxy server for SSL requests.
      type: string
      default: ""
    - name: noProxy
      description: Opt out of proxying HTTP/HTTPS requests.
      type: string
      default: ""
    - name: verbose
      description: Log the commands that are executed during `git-clone`'s operation.
      type: string
      default: "true"
    - name: gitInitImage
      description: The image providing the git-init binary that this Task runs.
      type: string
      default: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2"
    - name: userHome
      description: |
        Absolute path to the user's home directory.
      type: string
      default: "/home/git"
  results:
    - name: commit
      description: The precise commit SHA that was fetched by this Task.
    - name: url
      description: The precise URL that was fetched by this Task.
    - name: committer-date
      description: The epoch timestamp of the commit that was fetched by this Task.
  steps:
    - name: clone
      image: "$(params.gitInitImage)"
      env:
      - name: HOME
        value: "$(params.userHome)"
      - name: PARAM_URL
        value: $(params.url)
      - name: PARAM_REVISION
        value: $(params.revision)
      - name: PARAM_REFSPEC
        value: $(params.refspec)
      - name: PARAM_SUBMODULES
        value: $(params.submodules)
      - name: PARAM_DEPTH
        value: $(params.depth)
      - name: PARAM_SSL_VERIFY
        value: $(params.sslVerify)
      - name: PARAM_CRT_FILENAME
        value: $(params.crtFileName)
      - name: PARAM_SUBDIRECTORY
        value: $(params.subdirectory)
      - name: PARAM_DELETE_EXISTING
        value: $(params.deleteExisting)
      - name: PARAM_HTTP_PROXY
        value: $(params.httpProxy)
      - name: PARAM_HTTPS_PROXY
        value: $(params.httpsProxy)
      - name: PARAM_NO_PROXY
        value: $(params.noProxy)
      - name: PARAM_VERBOSE
        value: $(params.verbose)
      - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES
        value: $(params.sparseCheckoutDirectories)
      - name: PARAM_USER_HOME
        value: $(params.userHome)
      - name: WORKSPACE_OUTPUT_PATH
        value: $(workspaces.output.path)
      - name: WORKSPACE_SSH_DIRECTORY_BOUND
        value: $(workspaces.ssh-directory.bound)
      - name: WORKSPACE_SSH_DIRECTORY_PATH
        value: $(workspaces.ssh-directory.path)
      - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND
        value: $(workspaces.basic-auth.bound)
      - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH
        value: $(workspaces.basic-auth.path)
      - name: WORKSPACE_SSL_CA_DIRECTORY_BOUND
        value: $(workspaces.ssl-ca-directory.bound)
      - name: WORKSPACE_SSL_CA_DIRECTORY_PATH
        value: $(workspaces.ssl-ca-directory.path)
      securityContext:
        runAsNonRoot: true
        runAsUser: 65532
      script: |
        #!/usr/bin/env sh
        set -eu
 
        if [ "${PARAM_VERBOSE}" = "true" ] ; then
          set -x
        fi
 
        if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then
          cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials"
          cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig"
          chmod 400 "${PARAM_USER_HOME}/.git-credentials"
          chmod 400 "${PARAM_USER_HOME}/.gitconfig"
        fi
 
        if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then
          cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh
          chmod 700 "${PARAM_USER_HOME}"/.ssh
          chmod -R 400 "${PARAM_USER_HOME}"/.ssh/*
        fi
 
        if [ "${WORKSPACE_SSL_CA_DIRECTORY_BOUND}" = "true" ] ; then
           export GIT_SSL_CAPATH="${WORKSPACE_SSL_CA_DIRECTORY_PATH}"
           if [ "${PARAM_CRT_FILENAME}" != "" ] ; then
              export GIT_SSL_CAINFO="${WORKSPACE_SSL_CA_DIRECTORY_PATH}/${PARAM_CRT_FILENAME}"
           fi
        fi
        CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}/${PARAM_SUBDIRECTORY}"
 
        cleandir() {
          # Delete any existing contents of the repo directory if it exists.
          #
          # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"
          # or the root of a mounted volume.
          if [ -d "${CHECKOUT_DIR}" ] ; then
            # Delete non-hidden files and directories
            rm -rf "${CHECKOUT_DIR:?}"/*
            # Delete files and directories starting with . but excluding ..
            rm -rf "${CHECKOUT_DIR}"/.[!.]*
            # Delete files and directories starting with .. plus any other character
            rm -rf "${CHECKOUT_DIR}"/..?*
          fi
        }
 
        if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then
          cleandir || true
        fi
 
        test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}"
        test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}"
        test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}"
 
        git config --global --add safe.directory "${WORKSPACE_OUTPUT_PATH}"
        /ko-app/git-init \
          -url="${PARAM_URL}" \
          -revision="${PARAM_REVISION}" \
          -refspec="${PARAM_REFSPEC}" \
          -path="${CHECKOUT_DIR}" \
          -sslVerify="${PARAM_SSL_VERIFY}" \
          -submodules="${PARAM_SUBMODULES}" \
          -depth="${PARAM_DEPTH}" \
          -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}"
        cd "${CHECKOUT_DIR}"
        RESULT_SHA="$(git rev-parse HEAD)"
        EXIT_CODE="$?"
        if [ "${EXIT_CODE}" != 0 ] ; then
          exit "${EXIT_CODE}"
        fi
        RESULT_COMMITTER_DATE="$(git log -1 --pretty=%ct)"
        printf "%s" "${RESULT_COMMITTER_DATE}" > "$(results.committer-date.path)"
        printf "%s" "${RESULT_SHA}" > "$(results.commit.path)"
        printf "%s" "${PARAM_URL}" > "$(results.url.path)"

Git versioning

---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: git-version
  labels:
    app.kubernetes.io/version: "0.1"
  annotations:
    tekton.dev/pipelines.minVersion: "0.12.0"
    tekton.dev/displayName: "git version"
    tekton.dev/categories: Git
    tekton.dev/tags: git
    tekton.dev/platforms: "linux/amd64"
spec:
  description: >-
    This task can be used to create a version from git history
  params:
    - description: branch to checkout to create a version for e.g. "develop"
      name: branch
      type: string
  results:
    - description: The calculated git version you could use for git tagging e.g. "0.1.0-tektonize.1-188"
      name: gitVersion
    - description: A normalized version for use in container images e.g. "0.1.0-tektonize.1-188"
      name: packageVersion
  steps:
    - image: mcr.microsoft.com/dotnet/sdk:3.1-focal@sha256:1d31e2582f69920c3a6ea9498bb7da285baffbca7ea84d90d9e5b545604cc92d
      name: set-git-version
      workingDir: $(workspaces.source.path)
      securityContext:
        runAsUser: 0
      env:
        - name: PARAM_BRANCH
          value: $(params.branch)
      script: |
        #!/usr/bin/env bash
        export PATH="$PATH:/tekton/home/.dotnet/tools"
        dotnet tool install GitVersion.Tool --version 5.5.0 --tool-path "/tekton/home/.dotnet/tools"
 
        git checkout "${PARAM_BRANCH}"
 
        export GITVERSION=$(dotnet gitversion /showvariable FullSemVer)
        echo -n "${GITVERSION}" | tee $(results.gitVersion.path)
 
        # normalize a bit because
        # image tags can only contain `abcdefghijklmnopqrstuvwxyz0123456789_-.ABCDEFGHIJKLMNOPQRSTUVWXYZ`
        export PACKAGEVERSION=$(echo -n $GITVERSION | sed 's/[^-._0-9A-Za-z]/-/g')
        echo -n "${PACKAGEVERSION}" | tee $(results.packageVersion.path)
  workspaces:
    - name: source
      description: A workspace that contains the fetched git repository to create a version for.

Trivy Scanner

---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: trivy-scanner
  labels:
    app.kubernetes.io/version: "0.2"
  annotations:
    tekton.dev/pipelines.minVersion: "0.12.1"
    tekton.dev/categories: Security
    tekton.dev/tags: CLI, trivy
    tekton.dev/displayName: "trivy scanner"
    tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le,linux/390x"
spec:
  description: >-
    Trivy is a simple and comprehensive scanner for
    vulnerabilities in container images,file systems
    ,and Git repositories, as well as for configuration issues.
 
    This task can be used to scan for vulnenrabilities on the source code
    in stand alone mode.
  workspaces:
    - name: manifest-dir
  params:
    - name: ARGS
      description: The Arguments to be passed to Trivy command.
      type: array
    - name: TRIVY_IMAGE
      default: docker.io/aquasec/trivy@sha256:944a044451791617cc0ed2ee4d1942a4f66b790d527fcd0575a6b399ccbc05a1  # 0.43.1
      description: Trivy scanner image to be used
    - name: IMAGE_PATH
      description: Image or Path to be scanned by trivy.
      type: string
    - name: AIR_GAPPED_ENABLED
      default: "false"
      description: a flag enabling Air-Gapped mode
      type: string
  steps:
    - name: trivy-scan
      image: $(params.TRIVY_IMAGE)
      workingDir: $(workspaces.manifest-dir.path)
      script: |
        #!/usr/bin/env sh
          cmd="trivy $* "
          if [ "$(params.AIR_GAPPED_ENABLED)" = "true" ]; then
            echo "Air-Gapped mode enabled"
            TRIVY_TEMP_DIR=$(mktemp -d)
            trivy --cache-dir "$TRIVY_TEMP_DIR" image --download-db-only
            tar -cf ./db.tar.gz -C "$TRIVY_TEMP_DIR/db" metadata.json trivy.db
            rm -rf "$TRIVY_TEMP_DIR"
            mkdir -p "$HOME"/.cache/trivy/db
            tar xvf ./db.tar.gz -C "$HOME"/.cache/trivy/db
            cmd="${cmd}--skip-update "
          fi
          cmd="${cmd}$(params.IMAGE_PATH)"
          echo "Running trivy task with command below"
          echo "$cmd"
          eval "$cmd"
      args:
        - "$(params.ARGS)"

Kaniko Builder

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: kaniko
  labels:
    app.kubernetes.io/version: "0.6"
  annotations:
    tekton.dev/pipelines.minVersion: "0.17.0"
    tekton.dev/categories: Image Build
    tekton.dev/tags: image-build
    tekton.dev/displayName: "Build and upload container image using Kaniko"
    tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le"
spec:
  description: >-
    This Task builds a simple Dockerfile with kaniko and pushes to a registry.
    This Task stores the image name and digest as results, allowing Tekton Chains to pick up
    that an image was built & sign it.
  params:
    - name: IMAGE
      description: Name (reference) of the image to build.
    - name: DOCKERFILE
      description: Path to the Dockerfile to build.
      default: ./Dockerfile
    - name: CONTEXT
      description: The build context used by Kaniko.
      default: ./
    - name: EXTRA_ARGS
      type: array
      default: []
    - name: BUILDER_IMAGE
      description: The image on which builds will run (default is v1.5.1)
      default: gcr.io/kaniko-project/executor:v1.5.1@sha256:c6166717f7fe0b7da44908c986137ecfeab21f31ec3992f6e128fff8a94be8a5
  workspaces:
    - name: source
      description: Holds the context and Dockerfile
    - name: dockerconfig
      description: Includes a docker `config.json`
      optional: true
      mountPath: /kaniko/.docker
  results:
    - name: IMAGE_DIGEST
      description: Digest of the image just built.
    - name: IMAGE_URL
      description: URL of the image just built.
  steps:
    - name: build-and-push
      workingDir: $(workspaces.source.path)
      image: $(params.BUILDER_IMAGE)
      args:
        - $(params.EXTRA_ARGS)
        - --dockerfile=$(params.DOCKERFILE)
        - --context=$(workspaces.source.path)/$(params.CONTEXT) # The user does not need to care the workspace and the source.
        - --destination=$(params.IMAGE)
        - --digest-file=$(results.IMAGE_DIGEST.path)
      # kaniko assumes it is running as root, which means this example fails on platforms
      # that default to run containers as random uid (like OpenShift). Adding this securityContext
      # makes it explicit that it needs to run as root.
      securityContext:
        runAsUser: 0
    - name: write-url
      image: docker.io/library/bash:5.1.4@sha256:c523c636b722339f41b6a431b44588ab2f762c5de5ec3bd7964420ff982fb1d9
      script: |
        set -e
        image="$(params.IMAGE)"
        echo -n "${image}" | tee "$(results.IMAGE_URL.path)"

Now that we have our tasks in preparation, we can write our custom Tekton Pipeline.
Tekton Pipeline is constructed from top to bottom.

Tekton Pipeline

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: custom-docker-image
  namespace: tekton-pipelines
spec:
  params:
    - name: branch_name
      description: The git branch
    - name: repository_url
      description: The git repository url
    - name: repository_name
      description: The git repository name
  tasks:
    - name: clonegit
      taskRef:
        name: git-clone
      params:
        - name: url
          value: $(params.repository_url)
        - name: revision
          value: $(params.branch_name)
        - name: deleteExisting
          value: true
        - name: depth
          value: "0"
      workspaces:
        - name: output
          workspace: source-workspace
    - name: gitversion
      taskRef:
        name: git-version
      runAfter:
        - clonegit
      params:
        - name: branch
          value: "$(params.branch_name)"
      workspaces:
        - name: source
          workspace: source-workspace
    - name: trivyscanner
      taskRef:
        name: trivy-scanner
      runAfter:
        - gitversion
      params:
        - name: IMAGE_PATH
          value: "."
        - name: ARGS
          value: [ ]
      workspaces:
        - name: source
          workspace: source-workspace
    - name: kanikobuilder
      taskRef:
        name: kaniko
      runAfter:
        - trivyscanner
      params:
        - name: IMAGE
          value: "<your-custom-registry>/$(params.repository_name):$(tasks.gitversion.results.packageVersion)"
        - name: DOCKERFILE
          value: "Dockerfile"
      workspaces:
        - name: source
          workspace: source-workspace
        - name: dockerconfig
          workspace: docker-credentials
  workspaces:
    - name: source-workspace
    - name: docker-credentials

PipelineRun

Now that we have a complete Tekton Pipeline, we can start our pipeline.

For this we need Tekton PipelineRun. Here we are going to define our parameters like:

  • branch_name
  • repository_url
  • repository_name
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: custom-docker-image
  namespace: tekton-pipelines
spec:
  serviceAccountName: tekton-pipelines-build-bot
  pipelineRef:
    name: custom-docker-image
  params:
    - name: branch_name
      value: "develop"
    - name: repository_url
      value: "<repository-branch>"
    - name: repository_name
      value: "<repository-name>"
  workspaces:
    - name: source-workspace
      subPath: source
      persistentVolumeClaim:
        claimName: custom-docker-image-source
    - name: docker-credentials
      subPath: source
      persistentVolumeClaim:
        claimName: custom-docker-image-docker-credentials
  pipelineSpec:
    tasks:
      - name: clonegit
        taskRef:
          name: git-clone]
      - name: gitversion
        taskRef:
          name: git-version
      - name: trivyscanner
        taskRef:
          name: gitversion
      - name: kanikobuilder
        taskRef:
          name: kaniko

Deploy the resources to test in order: Tasks, Pipeline and PipelineRun.

2. Tekton Triggers: Launching Pipelines with Events

Triggers ensure that Tekton Pipelines can be initiated by an event, such as a commit to a repository that then sends a webhook to your Trigger Listener.
There are various options to activate your pipeline from an event.

When we further elaborate on the above diagram and incorporate Tekton Triggers, it looks like this:

Steps:

  1. Git sends a payload via a webhook to the EventListener.
  2. The EventListener reads the incoming webhook and payload, checking if it is intended for it.
  3. When the EventListener determines it is intended for it, it places the configured values from the payload into a variable. This is done through TriggerBinding.
  4. The EventListener then creates a TriggerTemplate with the values from TriggerBinding.
  5. TriggerTemplate subsequently initiates a PipelineRun and executes the defined tasks.

Example

EventListener

First we will create our EventListener based on a CEL expression.

 

apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: custom-docker-build-listener
  namespace: tekton-pipelines
spec:
  serviceAccountName: tekton-triggers-build-bot
  triggers:
    - name: git-custom-docker-build-listener
      interceptors:
        - cel:
              filter: (body.repository.workspace.slug.matches('<WORKSPACE>') && body.push.changes[0].new.name.matches('<branch-name>') && body.repository.name.matches('<repository-name>'))
      template:
        - ref: git-custom-docker-build-listener
      bindings:
        - ref: git-custom-docker-build-listener

In our EventListener we have configured triggers that:

  • will look at the WORKSPACE name
  • will look at the BRANCH name
  • will look at the REPOSITORY name

If these fields are correct, he will prepare a template.

We are also going to prepare a TriggerTemplate and TriggerBinding to use parameters during the trigger.

TriggerBinding

In the TriggerBinding we will extract the Trigger Body and load the variables with body values ​​sent from Webhook.

apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerBinding
metadata:
  name: custom-docker-build-listener
  namespace: tekton-pipelines
spec:
  params:    
    - name: branch_name
      value: $(body.pullrequest.destination.branch.name)
    - name: repository_url
      value: $(body.repository.links.html.href)
    - name: repository_name
      value: $(body.repository.name)

TriggerTemplate

Now that we have the variables in the TriggerBinding, we can start our Pipeline from TriggerTemplate with our variables coming from Trigger.

We can use the ${tt.xx} notation for this.

apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
  name: custom-docker-build-listener
  namespace: tekton-pipelines
spec:
  params:
    - name: branch_name
      description: The git branch name
    - name: repository_url
      description: The git repository url
    - name: repository_name
      description: The git repository name
  resourcetemplates:
    - apiVersion: tekton.dev/v1beta1
      kind: PipelineRun
      metadata:
        generateName: $(tt.params.repository_name)-
        labels:
          tekton.dev/pipeline: tekton-pipeline
      spec:
        serviceAccountName: tekton-pipelines-build-bot
        pipelineRef:
          name: custom-docker-build-listener
        params:
          - name: branch_name
            value: $(tt.params.branch_name)
          - name: repository_url
            value: $(tt.params.repository_url)
          - name: repository_name
            value: $(tt.params.repository_name)
        workspaces:
          - name: source-workspace
            subPath: source
            persistentVolumeClaim:
              claimName: custom-docker-image-source
          - name: docker-credentials
            subPath: source
            persistentVolumeClaim:
              claimName: custom-docker-image-docker-credentials
        pipelineSpec:
          tasks:
            - name: clonegit
              taskRef:
                name: git-clone]
            - name: gitversion
              taskRef:
                name: git-version
            - name: trivyscanner
              taskRef:
                name: gitversion
            - name: kanikobuilder
              taskRef:
                name: kaniko

Deploy the resources in order to test: TriggerTemplate, TriggerBinding, EventListener.

3. Tekton Dashboard: Streamlined Management and Monitoring

Observing and managing Tekton resources within a Kubernetes environment is not always straightforward, especially considering developers often have restricted access rights in the Kubernetes environment.

For this reason, utilizing Tekton Dashboards is recommended. Tekton Dashboard serves as an extension to the Tekton ecosystem, offering a user-friendly web interface for the administration and monitoring of Tekton resources in Kubernetes environments. It facilitates developers in tracking pipelines, monitoring real-time logs, and verifying task statuses. Consequently, developers can promptly identify the reasons for build failures and their specific locations.

4. Tekton Hub: Comprehensive Library of Pipelines and Tasks

Tekton offers an extensive range of pipelines and tasks readily available. While developers can write pipelines or tasks from scratch, they also have the option to adopt tasks and pipelines from the Tekton Hub. The resources acquired from the Hub can be customized as needed.

This provides flexibility for developers, allowing them to refrain from adhering strictly to predefined resources and instead fully rewrite their resources according to their preferences.

Some key tasks available from the Hub include:

  • Git-Clone
  • Workspace Cleaner
  • Maven
  • Jib-Maven
  • BuildPacks
  • Kaniko/Docker

More tasks are accessible at https://hub.tekton.dev/.

Getting Started with Tekton

For developers looking to utilize Tekton, the official Tekton-documentation provides detailed information on installation and configuration.

In conclusion, Tekton offers a powerful, flexible, and scalable solution for CI/CD processes. With its CloudNative characteristics, extensibility, and support from major companies, Tekton has established itself as a reliable framework for developers.

Do you want to experience the benefits of Tekton in practice and discover how ACA Group can provide innovative solutions for your IT challenges?

Feel free to contact our experts for personalized advice and a seamless implementation.

 


Ugur Akkar
Ugur Akkar
Solution Engineer, ACA Group
Contact us

Want to dive deeper into this topic?

Get in touch with our experts today. They are happy to help!

ACA mug mok koffie tas
Contact us

Want to dive deeper into this topic?

Get in touch with our experts today. They are happy to help!

ACA mug mok koffie tas
Contact us

Want to dive deeper into this topic?

Get in touch with our experts today. They are happy to help!

ACA mug mok koffie tas
Contact us

Want to dive deeper into this topic?

Get in touch with our experts today. They are happy to help!

ACA mug mok koffie tas