Tekton Pipelines is a CI/CD tool that runs on a Kubernetes cluster.
While it’s common to operate Tekton using a dashboard or CLI, you can also run tasks using a more primitive way: by directly submitting a PipelineRun
resource, one of Tekton’s Custom Resource Definitions (CRDs), to the Kubernetes API server.
For a minimal configuration:
FRAGMENT=$(cat /dev/urandom | base64 | tr -dC '[:alnum:]' | tr '[A-Z]' '[a-z]' | fold -w 5 | head -n 1)
cat << EOF | kubectl apply -f -
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: <some-pipelinerun-name>-$FRAGMENT
spec:
pipelineRef:
name: <some-pipeline-name>
EOF
A manifest for
PipelineRun is written within the here document.
In practice, you’ll also likely specify metadata.namespace
, spec.params
, and spec.workspaces
.
$FRAGMENT
is a work example of generating an identifier to avoid duplication for repeated executions.
Additionally, this method assumes you have the necessary permissions, such as the authority to create Tekton Pipelines resources, when executing kubectl
.
This approach isn’t very useful if Tekton Triggers is set up and working correctly.
However, since setting up Triggers can also be quite complex, this method is a viable option if you want to use Pipelines on their own without the additional complexity.
Run inside containers
CronJob
is a typical use case for launching a Pipeline from within a container.
If you have kubectl
installed in the container image and the necessary permissions are provided via a ServiceAccount
, it can behave just like an operation performed on the host machine.
Here’s an example manifest:
apiVersion: batch/v1
kind: CronJob
metadata:
name: <some-job-name>
spec:
jobTemplate:
spec:
template:
spec:
serviceAccountName: <some-serviceaccount>
containers:
- name: create-pipeline
image: <some-image-name-having-kubectl>
env:
- name: PODNAME
valueFrom:
fieldRef:
fieldPath: metadata.name
command: ["bash"]
args:
- "-c"
- |
cat <<EOF | kubectl apply -f -
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: $PODNAME
spec:
pipelineRef:
name: <some-pipeline-name>
EOF
Here are 2 key characteristics:
- It specifies a ServiceAccount on
spec.jobTemplate.spec.template.spec.serviceAccontName
. - It omits the need to generate a
$FRAGMENT
by reusing the job’s name via the Downward API. While not mandatory, this makes it easier to correlate each PipelineRun with its corresponding job.
ServiceAccont
By pre-registering a set of ServiceAccount
, Role
, and RoleBinding
within your cluster, you can provide the necessary permissions to containers:
apiVersion: v1
kind: ServiceAccount
metadata:
name: <some-serviceaccount>
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tekton-pipelines-operator
rules:
- apiGroups: ["tekton.dev"]
resources: ["pipelineruns", "taskruns"]
verbs: ["get", "list", "create"]
- apiGroups: ["tekton.dev"]
resources: ["pipeline"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pipeline-operator-binding
subjects:
- kind: ServiceAccount
name: <some-serviceaccount>
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: tekton-pipelines-operator
Read access to Pipelines will also be required due to spec.pipelineRef
.
Run as a non-root user inside the container
Since a CronJob
runs as the container’s user, simply specifying a ServiceAccount allows kubectl
to acquire the necessary resources for access.
For special cases, such as running as a non-root user, additional measures like the following are required:
export KUBERNETES_SERVICE_HOST=<some-host-address>
export KUBERNETES_SERVICE_PORT=<some-host-port>
FRAGMENT=$(cat /dev/urandom | base64 | tr -dC '[:alnum:]' | tr '[A-Z]' '[a-z]' | fold -w 5 | head -n 1)
cat << EOF | sudo -E kubectl apply -f -
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: <some-pipelinerun-name>-$FRAGMENT
spec:
pipelineRef:
name: <some-pipeline-name>
EOF
When running as a non-root user, there are 2 main differences from running as root:
- Since tokens are provided for the root user, you’ll need to install
sudo
in your container image and set it up for the non-root execution user. - The API server address that
kubectl
references is registered in the root user’s environment variables, so you need to configure it for the non-root user’s environments.
While you could set up the tokens directly for the execution user without using sudo
, the required effort would be similar.