Getting Started with Tekton Pipelines Part 1 — Container Image Build and Push
Tekton is an open-source project for creating CI/CD systems.
allowing developers to build, test, and deploy across cloud providers and on-premise systems.
In this Part 1, I will address the Basic Pipeline with real everyday tasks.
In the next part, I will address the Tekton Triggers.
The separation into two parts hopefully would minimize the complexity.
There is a lot of documentation both at the Tekton site and at the Tekton GitHub project.
But still, when you are about to use it for real tasks, it is confusing, and maybe an exact real day-to-day example would help, and when I was starting with Tekton, I wished for a simple example that would show me the way.
Simple Example
I have created a very simple example for Tekton Pipelines.
These examples contain the minimal entities needed to create a pipeline.
It would be better to follow them first, you can read it over https://github.com/yossicohn/tekton-pipelines/blob/main/Part-1-pipelines/simple-example/README.md
The README.md there would walk you through the implementation, step by step.
What will we do?
The article would go and try to describe the different entities and concepts in the Tekton flow.
We will go from top to bottom, meaning:
Pipelinerun ➨ Pipeline ➨Task, and in the journey, we will go over what we meet.
Our Task:
1. Pull a private git repository
2. Build the container image
3. Push the image to the private container registry
Obviously, we would use Tekton as the CI framework to define and execute the steps.
We will use Kaniko for the container image build and image push to the registry.
For more info on Kaniko, you can see my previous article kaniko-builds-with-private-repository
Note, in this article, I would assume the reader has a basic understanding of Kubernetes, moreover, I will not reference the stage of installing Tekton as you can have it over Tekton’s installation guide.
So let’s get started!
Tekton defines Kubernetes resources which are its pipeline building blocks.
Following are the resources we will use and some basic definitions for you to grasp.
● Pipeline
● Task
● PipelineResource
● Workspace
● Results
● Parameters
With the following schema, you can learn about the entities and the relationships between them.
Basic familiarity with some of the entities:
Pipeline
A
Pipeline
defines an ordered series ofTasks
that you want to execute along with the corresponding inputs and outputs for eachTask
. You can specify whether the output of oneTask
is used as an input for the nextTask
using thefrom
property.Pipelines
offer the same variable substitution asTasks
.
Task
A
Task
defines a series ofsteps
that run in a desired order and complete a set amount of build work. EveryTask
runs as a Pod on your Kubernetes cluster with eachstep
as its own container.
PipelineResources
PipelineResources
in a pipeline are the set of objects that are going to be used as inputs to aTask
and can be output by aTask
.A
Task
can have multiple inputs and outputs.
For example:A
Task
's input could be a GitHub source that contains your application code.A
Task
's output can be your application container image (that was built) which can be then deployed in a cluster.Another example for a
Task
's output can be a jar file to be uploaded to a storage bucket.
Workspace
A
Pipeline
can useWorkspaces
to show how storage will be shared through itsTasks
. For example,Task
A might clone a source repository onto aWorkspace
andTask
B might compile the code that it finds in thatWorkspace
. It’s thePipeline's
responsibility to ensure that theWorkspace
these twoTasks
use is the same, and more importantly, that the order in which they access theWorkspace
is correct.
You can read more on workspace here
Results
A Task can emit a string result that users can view and pass to other Tasks in a Pipeline.
These results have a wide variety of potential usages.
To define a
Task's
results, use theresults
field. Eachresults
entry in theTask's
YAML corresponds to a file that theTask
should store the result in. These files should be created by aTask
in the/tekton/results
directory. The directory itself is created automatically if theTask
has aresults
field but it’s the responsibility of theTask
to generate its contents.
You can read more on results here
Parameters
You can specify parameters, such as compilation flags or artifact names, that you want to supply to the
Task
at execution time.Parameters
are passed to theTask
from its correspondingTaskRun
Parameters
are passed to thePipeline
from its correspondingPipelineRun
and can replace template values specified within eachTask
in thePipeline
.
Our Pipeline
In our example, we will have a Pipeline that would be finalized by pulling, building, and pushing an image to a container registry.
The pipeline would be composed out of 2 tasks:
1. git-pull-source-and-get-sha — which will pull the git repository and will define the image push tag out of the git last commit sha1
2. build-docker-image-from-source — which will use Kaniko to build the container image and push it to the DockerHub private registry (we will show usage for AWS ECR as well)
Below you can see the Pipeline definition via the pipeline.yaml
The Pipeline contains the following references:
- PipelineResources — which are Git and Image resources named as i
nput-git
,output-image
- Tasks — via the
task-ref
element under tasks element
we will use:
-build-docker-image-from-source
-git-pull-source-and-get-sha
- Workspace — we will use a single workspace, to share our git source.
The workspace in this example is a localhost volume (and is defined bypipelinerun.yaml
which we will reference later), but we can use otherPVC’s
Our Pipeline defines:
- PipelineResources used by the tasks
- Results to be used by the contained Tasks
- Parameters passed to the tasks
- Workspace passed to the tasks
Note, an example for results usage:“$(tasks.pipeline-git-source.results.dockerfile-path)”
This way we get the result propagated from the task pipeline-git-sourc
e by the name dockerfile-path
All the definitions regarding the Workspace
(volumes), Parameters
, ServiceAccount
, and PipelineResources
are found at the Pipelinerun
which is used by the pipeline.yaml
In the following schema, you can see the entities relationships
- Pipeline — is manifested by PODS (Pod per Task)
- Task — is manifested as a POD
- Steps — are manifested as Containers in the Task POD
Pipelinerun
In the pipelinerun.yaml
you can see the defined resources that would be used in the pipeline.yaml
, this way we can inject the Pipeline
with different resources, having the pipeline behave as a template.
Here we define the PipelineResources
which in this case are:
- Input Resource (type git) —
go-api-skeleton-git
used to define git repositories as a resource - Output Resource (type image) —
go-api-skeleton-image
used to define container registry as a resource - Workspace — a volume claim which is named as
shared-data
and is referenced from thepipeline
- ServiceAccount — with which we define the pipeline credentials
- Parameters — the
parameters
injected into the pipeline
Running the Pipeline
To run the pipeline, we need to create the resources in the kubernetes cluster.
To follow the instructions, it would be better to clone the repo and cd into part-1-pipelines.
Over the Part 1 README.md at https://github.com/yossicohn/tekton-pipelines/blob/main/Part-1-pipelines/README.md you can have a step by step instructions on how to create the secrets and PipelineResources.
To show the example you can refer to my private GitHub repo yossicohn/go-api-skeleton
and my private DockerHub Registry.
- Creating the pipeline https://github.com/yossicohn/tekton-pipelines/blob/main/Part-1-pipelines/pipeline.yaml
- Create the PipelineResources
Creating two resources, git and image
Note, that you need to update the resources to reference your own!
- Create the Tasks
Create the 2 tasks as defined above.
- Create Secrets
After you have the secret yaml files ready, as instructed in the README.md we can create them (this way we will have the git SSH secret defined and the Container Registry secret)
You can see the secret usage in the tasks yaml files. - Create authentication via k8s secret of type docker-registry
- Create the secret for the git SSH Credentials
Last, we need to create the Pipelinerun
kubectl apply -f pipeline/pipelinerun.yaml
Get the Pipelinerun
list and logs via the Tekton CLI (also referenced in the README)
Note, regarding the workspace,
The workspace volume would be created automatically and is dependent on the infra you are running on (for Minikube/Kind you will have hostpath
volume, and in AWS and alike you would get a provisioned Block device)
Summary
In this Part, we referenced the Tekton Pipeline and saw how we can use it to build a pipeline.
In the next part, we will reference the Tekton Triggers, and learn how we can use triggers, and Github triggers to trigger a pipeline.
Thanks for assisting Regev Golan