5 min read | by Jordi Prats
We can build containers from within a Kubernetes cluster using Kaniko using Pods or use some framework to streamline the process such as Shipwright that uses tekton pipelines to actually run the process. We can skip Shipwright and create directly tekton pipelines.
First we'll need to install tekton, to do so we just need to apply the following manifests:
kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
To be able to work with private repositories and registries we'll have to push som secrets:
To configure a private registry we'll need to create a secret with the following type: kubernetes.io/dockerconfigjson. The data it requires is the following:
kubectl create secret docker-registry private-registry \
--docker-server=$REGISTRY_SERVER \
--docker-username=$REGISTRY_USER \
--docker-password=$REGISTRY_PASS \
--docker-email=$REGISTRY_EMAIL
In order to tell tekton to use a given private ssh key for github.com we'll need to create a secret as follows:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: github-key
annotations:
tekton.dev/git-0: github.com
type: kubernetes.io/ssh-auth
data:
ssh-privatekey: $(base64 -w0 ~/.ssh/id_rsa)
EOF
In order to let tekton have these secrets we are going to create a ServiceAccount referencing the secrets:
cat <<"EOF" | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: pipeline-runner
secrets:
- name: private-registry
- name: github-key
EOF
To actually define what we want to run we can do so using tekton tasks either by defining it from scratch or reusing one from tekton hub. For this demo we are going to reuse publicly available git-clone and the kaniko tasks:
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.3/git-clone.yaml
kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/kaniko/0.2/kaniko.yaml
We can check it's yaml definition to see what it basically does is to run a container. For example, the kaniko task looks like this:
$ kubectl get task kaniko -o yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: kaniko
(...)
spec:
description: |-
This Task builds source into a container image using Google's kaniko tool.
Kaniko doesn't depend on a Docker daemon and executes each command within a Dockerfile completely in userspace. This enables building container images in environments that can't easily or securely run a Docker daemon, such as a standard Kubernetes cluster.
params:
- description: Name (reference) of the image to build.
name: IMAGE
type: string
- default: ./Dockerfile
description: Path to the Dockerfile to build.
name: DOCKERFILE
type: string
- default: ./
description: The build context used by Kaniko.
name: CONTEXT
type: string
- default: ""
name: EXTRA_ARGS
type: string
- default: gcr.io/kaniko-project/executor:v1.5.1@sha256:c6166717f7fe0b7da44908c986137ecfeab21f31ec3992f6e128fff8a94be8a5
description: The image on which builds will run (default is v1.5.1)
name: BUILDER_IMAGE
type: string
results:
- description: Digest of the image just built.
name: IMAGE-DIGEST
type: string
steps:
- args:
- $(params.EXTRA_ARGS)
- --dockerfile=$(params.DOCKERFILE)
- --context=$(workspaces.source.path)/$(params.CONTEXT)
- --destination=$(params.IMAGE)
- --oci-layout-path=$(workspaces.source.path)/$(params.CONTEXT)/image-digest
computeResources: {}
env:
- name: DOCKER_CONFIG
value: /tekton/home/.docker
image: $(params.BUILDER_IMAGE)
name: build-and-push
securityContext:
runAsUser: 0
workingDir: $(workspaces.source.path)
(...)
Once we have them in the namespace, we'll be able to start creating the pipeline definition:
$ kubectl get tasks
NAME AGE
git-clone 6s
kaniko 3s
The pipeline definition (Pipeline object) will hold that tasks that it is going to run and the parameters it is going to need to configure it:
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: build-and-deploy-pipeline
spec:
workspaces:
- name: git-source
description: The git repo
params:
- name: gitUrl
description: Git repository url
type: string
- name: gitRevision
description: Git revision to check out
type: string
default: master
- name: pathToContext
description: The path to the build context
default: src
type: string
- name: imageUrl
description: Image name including repository
type: string
- name: imageTag
description: Image tag
type: string
default: latest
tasks:
- name: clone-repo
taskRef:
name: git-clone
workspaces:
- name: output
workspace: git-source
params:
- name: url
value: "$(params.gitUrl)"
- name: revision
value: "$(params.gitRevision)"
- name: subdirectory
value: "."
- name: deleteExisting
value: "true"
- name: verbose
value: "true"
- name: build-and-push-image
taskRef:
name: kaniko
runAfter:
- clone-repo
workspaces:
- name: source
workspace: git-source
params:
- name: CONTEXT
value: $(params.pathToContext)
- name: IMAGE
value: $(params.imageUrl):$(params.imageTag)
To actually run the pipeline, building and pushing the container image to the private registry we'll have to create a PipelineRun object, specifying the ServiceAccount with the appropriate secrets:
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: build-and-deploy-execution
spec:
pipelineRef:
name: build-and-deploy-pipeline
params:
- name: gitUrl
value: git@github.com:pet2cattle/demo-app.git
- name: gitRevision
value: HEAD
- name: imageUrl
value: repo.pet2cattle.com/demo-app
- name: imageTag
value: latest
- name: pathToContext
value: '.'
serviceAccountName: pipeline-runner
workspaces:
- name: git-source
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
As soon as this object gets picked up, it will create a volumeClaim to hold the temporal data it uses and start running the Pods with each of the tasks that we have configured with the Pipeline template. We can check it's status using kubectl get pipelinerun:
$ kubectl get pipelinerun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
build-and-deploy-execution Unknown Running 10s
$ kubectl get pipelinerun
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
build-and-deploy-execution True Succeeded 48m 44m
Posted on 04/01/2023