Featured image: Tekton Pipelines

Tekton is a powerful, Kubernetes-native framework for creating continuous integration and delivery (CI/CD) systems. In this article, we'll use real-world examples to show you how to install Tekton, create Tasks, and eventually create our own pipeline.

What's a pipeline?

Great question! In software development, pipelines are automated processes that drive software through a process of building, testing, and deploying code. Such an efficient process can help minimize human error, as well as maintain consistency in deployment. Since Tekton is cloud-native, its pipelines are containerized and don't have dependencies on other projects, mitigating potential issues and saving you time.

Defining and running a pipeline from pipeline Tasks through PipelineRun TaskRuns, controllers, and pods.
The structure of a pipeline.
The structure of a pipeline.

About Tekton

Tekton is a Knative-based framework for CI/CD pipelines, but it's unique due to its decoupled nature—meaning that one pipeline can be used to deploy to any Kubernetes cluster across multiple hybrid cloud providers. In addition, Tekton stores everything related to a pipeline as custom resources (CRs) within the cluster, allowing pieces to be used across multiple pipelines.

Installing Tekton

For this guide, we'll assume you're using Minikube for your Kubernetes cluster, although we've created a Tekton lab on OpenShift if you don't have access to Minikube. Once your cluster is running with minikube start, install the latest version of Tekton by applying the YAML from the latest release:

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

This command will create a tekton-pipelines namespace, as well as other resources to finalize your Tekton install. With that namespace in mind, we can easily track the progress of our installation using the command below:

kubectl get pods --namespace tekton-pipelines --watch

Finally, to interact with Tekton through the console, we need to install the Tekton CLI, also known as tkn. Depending on your operating system, please use the instructions from the official repository to install the latest binary executable.

Optional: Install the tutorial repo

The Red Hat OpenShift developer advocate team has created a repository to help you get started and master Tekton concepts. If you're interested in seeing more concepts and getting hands-on, feel free to clone our repo to your local directory:

git clone https://github.com/joellord/handson-tekton

Once you've cloned the tutorial repository, be sure to cd into the folder with:

cd handson-tekton

Creating our first Task

Let's start with a simple "Hello World" Task for our introduction to Tasks. Task resources are essential building block components for creating a Pipeline, and this first Task will allow us to use a Red Hat Universal Base Image and echo a "Hello World". To begin, let's open the file 01-hello.yaml in the /demo folder:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: hello
spec:
  steps:
    - name: say-hello
      image: registry.access.redhat.com/ubi8/ubi
      command:
        - /bin/bash
      args: ['-c', 'echo Hello World']

You'll notice several details above, from the kind being a Task, to the step of "say-hello", and the args being to simply output an echo command to the console. Let's apply this Task to our cluster, similar to any other Kubernetes object:

kubectl apply -f ./demo/01-hello.yaml

tkn task start --showlog hello

Great work! After running this tkn command, you'll soon see an output from the Task in the console like such:

TaskRun started: hello-run-6cgf5
Waiting for logs to be available...
[say-hello] Hello World

Adding parameters to a task

An essential feature of Tasks is the ability to take in and pass parameters. If you're looking to build out various Pipelines, parameters, or params, are instrumental. These properties are constructed of a name and type, but can also accept a description and default value. To take a better look at how parameters work, let's open up the file 02-param.yaml in the /demo folder:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: hello
spec:
  params:
    - name: person
      description: Name of person to greet
      default: World
      type: string
  steps:
    - name: say-hello
      image: registry.access.redhat.com/ubi8/ubi
      command:
        - /bin/bash
      args: ['-c', 'echo Hello $(params.person)']

Building from our "Hello World" example, we've added in a person parameter with generic values. In addition, to access the new param, we can call it using $(params.person). In order to run this new Task, we can add it to our cluster and run the Task with the following command:

kubectl apply -f ./demo/02-param.yaml

tkn task start --showlog hello

Looks good! Now, it looks as if the console is asking for us to specify the parameter in the command line, similar to below:

? Value for param `person` of type `string`? (Default is `World`) Cedric
TaskRun started: hello-run-z4gsw
Waiting for logs to be available...
[say-hello] Hello Cedric

Creating a Pipeline

Now that you understand Tasks and parameters, let's dive into creating a Pipeline. For consistency, Tasks are meant for single actions, while a Pipeline is a series of Tasks that can be run either in parallel or sequentially. For this example, we'll use the 04-tasks.yaml file in the /demo folder for our Pipeline:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: say-something
spec:
  params:
    - name: say-what
      description: What should I say
      default: hello
      type: string
    - name: pause-duration
      description: How long to wait before saying something
      default: 0
      type: string
  steps:
    - name: say-it
      image: registry.access.redhat.com/ubi8/ubi
      command:
        - /bin/bash
      args: ['-c', 'sleep $(params.pause-duration) && echo $(params.say-what)']

With this generic Task file, which will echo whatever it receives in its parameters, we can build our first Pipeline. With the 05-pipeline.yaml file in the /demo folder, we can manipulate the 04-tasks.yaml Task twice, with different outputs:

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: say-things
spec:
  tasks:
    - name: first-task
      params:
        - name: pause-duration
          value: "2"
        - name: say-what
          value: "Hello, this is the first task"
      taskRef:
        name: say-something
    - name: second-task
      params:
        - name: say-what
          value: "And this is the second task"
      taskRef:
        name: say-something

We're now ready to apply the generic Task and the new Pipeline to our cluster, and officially start the Pipeline. Using tkn pipeline start, we create a PipelineRun resource automatically with a random name that will trigger our pipeline.

kubectl apply -f ./demo/04-tasks.yaml

kubectl apply -f ./demo/05-pipeline.yaml

tkn pipeline start say-things --showlog

Congrats! You'll notice the console has to output the logs from the PipelineRun. However, the order seems to be confused.

PipelineRun started: say-things-run-ncfsq
Waiting for logs to be available...
[second-task : say-it] And this is the second task
[first-task : say-it] Hello, this is the first task

You'll notice that the first task seems to happen after the second task, and this is due to Tekton naturally running all the tasks simultaneously.

Run in parallel or sequentially

For Tasks to run in a specific order, the runAfter parameter is needed in the task definition of your Pipeline. Let's open up the 06-pipeline-order.yaml file in the /demo folder:

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: say-things-in-order
spec:
  tasks:
    - name: first-task
      params:
        - name: pause-duration
          value: "2"
        - name: say-what
          value: "Hello, this is the first task"
      taskRef:
        name: say-something
    - name: second-task
      params:
        - name: say-what
          value: "Happening after task 1, in parallel with task 3"
        - name: pause-duration
          value: "2"
      taskRef:
        name: say-something
      runAfter:
        - first-task
    - name: third-task
      params:
        - name: say-what
          value: "Happening after task 1, in parallel with task 2"
        - name: pause-duration
          value: "1"
      taskRef:
        name: say-something
      runAfter:
        - first-task
    - name: fourth-task
      params:
        - name: say-what
          value: "Happening after task 2 and 3"
      taskRef:
        name: say-something
      runAfter:
        - second-task
        - third-task

The runAfter parameter is being applied to specific numbered tasks, and after applying this Pipeline to our cluster, we'll be able to see logs from each task, but ordered:

kubectl apply -f ./demo/06-pipeline-order.yaml

tkn pipeline start say-things-in-order --showlog

After running tkn, your CLI output should be similar to this example:

PipelineRun started: say-things-in-order-run-5dklz
Waiting for logs to be available...
[first-task : say-it] Hello, this is the first task
[second-task : say-it] Happening after task 1, in parallel with task 3
[third-task : say-it] Happening after task 1, in parallel with task 2
[fourth-task : say-it] Happening after task 2 and 3

Conclusion

Feel free to continue the demo here, and try out our guided OpenShift and Kubernetes learning here as well, which offers an interactive environment right in your browser.

Check out our video for more interactive demonstrations of many examples you've seen here!

Resources

If you want to keep learning about Tekton, start with these articles on Red Hat Developer:

Last updated: February 5, 2024