Tekton is a Kubernetes-native continuous integration and delivery (CI/CD) framework. It allows you to create containerized, composable, and configurable workloads declaratively through Kubernetes Custom Resource Definitions (CRD).
More on Kubernetes
- What is Kubernetes?
- eBook: Storage Patterns for Kubernetes
- Test drive OpenShift hands-on
- eBook: Getting started with Kubernetes
- An introduction to enterprise Kubernetes
- How to explain Kubernetes in plain terms
- eBook: Running Kubernetes on your Raspberry Pi homelab
- Kubernetes cheat sheet
- eBook: A guide to Kubernetes for SREs and sysadmins
- Latest Kubernetes articles
Tekton Triggers is a Tekton component that allows you to detect and extract information from events from various sources and execute TaskRuns and PipelineRuns based on that information. It also enables passing extracted information to TaskRuns and PipelineRuns from events.
This article demonstrates how Tekton Triggers integrates with external services, such as a Git repository, using GitLab as an example.
If you want to follow the steps in this article, you must have a Kubernetes cluster running Kubernetes 1.18 or above with an ingress controller installed that can give you an external IP. You must also have Tekton Pipelines and Tekton Triggers installed.
Tekton Trigger allows you to create a special resource called an EventListener, which is a Kubernetes service that listens for incoming HTTP requests from different sources, usually a Git repository, including those hosted on GitLab, GitHub, and others. Based on those events, the EventListener pod performs actions and creates Tekton resources, such as TaskRun or PipelineRun.
All Triggers resource definitions are created in YAML, the configuration format most commonly used in Kubernetes. However, before writing YAML files to define a Trigger, it's important to understand Tekton Triggers terminology.
An EventListener is a Kubernetes service that listens for incoming HTTP requests and executes a Trigger. For example, after receiving a specific incoming request, this definition executes the
apiVersion: triggers.tekton.dev/v1beta1 kind: EventListener metadata: name: gitlab-event-listener spec: serviceAccountName: gitlab-listener-sa triggers: - triggerRef: gitlab-listener-trigger resources: kubernetesResource: serviceType: NodePort
A Trigger decides what to do with a received event. It also sets a TriggerBinding, TriggerTemplate, and optional interceptors to run. Triggers make use of interceptors to validate or modify incoming requests before proceeding.
apiVersion: triggers.tekton.dev/v1beta1 kind: Trigger metadata: name: gitlab-listener-trigger spec: interceptors: - name: "verify-gitlab-payload" ref: name: "gitlab" kind: ClusterInterceptor params: - name: secretRef value: secretName: "gitlab-secret" secretKey: "secretToken" - name: eventTypes value: - "Push Hook" bindings: - ref: binding template: ref: template
An interceptor is an event processor that runs before the TriggerBinding. It also performs payload filtering, verification (using a secret), and transformation; defines and tests trigger conditions; and implements other useful processing.
By default, four core interceptors are installed when installing Triggers: GitHub, GitLab, Bitbucket, and CEL. The installation also includes one Webhook interceptor for implementing custom business logic.
GitLab interceptors help to validate and filter GitLab webhooks and filter incoming events by event type. The GitLab interceptor requires a secret token. This token is set when creating the webhook in GitLab and is validated by the GitLab interceptor when the request arrives.
apiVersion: v1 kind: Secret metadata: name: gitlab-secret type: Opaque stringData: secretToken: "1234567"
After validating and modifying the incoming request, you need to extract values from the request and bind them to variables that you can later use in a TriggerTemplate to pass our Pipeline.
For our example, you just need a URL and a revision.
apiVersion: triggers.tekton.dev/v1beta1 kind: TriggerBinding metadata: name: binding spec: params: - name: gitrevision value: $(body.checkout_sha) - name: gitrepositoryurl value: $(body.repository.git_http_url)
The TriggerTemplate is a blueprint that instantiates
PipelineRun when EventListener detects an event.
apiVersion: triggers.tekton.dev/v1beta1 kind: TriggerTemplate metadata: name: template spec: params: - name: gitrevision - name: gitrepositoryurl resourcetemplates: - apiVersion: tekton.dev/v1beta1 kind: TaskRun metadata: generateName: gitlab-run- spec: taskSpec: resources: inputs: - name: source type: git steps: - image: ubuntu script: | #! /bin/bash ls -al $(inputs.resources.source.path) resources: inputs: - name: source resourceSpec: type: git params: - name: revision value: $(tt.params.gitrevision) - name: url value: $(tt.params.gitrepositoryurl)
Dynamically schedule workloads by configuring a webhook
First, create a new namespace,
$ kubectl create ns demo
Next, before applying the Triggers resource, configure the required role-based access control (RBAC):
$ kubectl -n demo apply -f \ "https://gist.githubusercontent.com/savitaashture/596bc4d93ff6b7606fe52aa20ba1ba14/raw/158a5ed0dc30fd1ebdac461147a4079cd6187eac/triggers-rbac.yaml"
Note: RBAC configurations vary depending on the permissions.
Apply Triggers resources:
$ kubectl -n demo apply -f \ "https://gist.githubusercontent.com/savitaashture/8aa013db1cb87f5dd1f2f96b0e121363/raw/f4f592d8c1332938878c5ab9641e350c6411e2b0/triggers-resource.yaml"
After applying, verify the successful creation of the EventListener object and pod:
EventListener object READY status should be True.
$ kubectl get el -n demo NAME ADDRESS AVAILABLE REASON READY REASON gitlab-event-listener http://el-gitlab-event-listener.demo.svc.cluster.local:8080 True MinimumReplicasAvailable True
EventListener Pod status should be Running.
$ kubectl get pods -n demo NAME READY STATUS RESTARTS AGE el-gitlab-event-listener-fb77ff8f7-p5wnv 1/1 Running 0 4m22s
Create ingress to get the external IP to configure in the GitLab webhook:
$ kubectl -n demo apply -f \ "https://gist.githubusercontent.com/savitaashture/3b3554810e391477feae21bb8a9af93a/raw/56665b0a31c7a537f9acbb731b68a519be260808/triggers-ingress.yaml"
Get the ingress IP:
$ kubectl get ingress triggers-ingress-resource -n demo NAME CLASS HOSTS ADDRESS PORTS AGE ingress-resource <none> * <address> 80 6s
Configure a webhook in GitLab. In your GitLab repository, go to Settings -> Webhooks.
Then set the below fields:
- URL: external IP Address from the Ingress with
- Secret token: 1234567, which should match the secret value created above from
Choose event type from the Trigger section, then just select Push events, uncheck Enable SSL verification, and click on Add webhook.
Testing GitLab events by pushing PR
Clone your own GitLab repository, make changes, and push. For example:
$ git clone https://gitlab.com/savitaashture1/gitlabtest-triggers $ cd gitlabtest-triggers $ git commit -m "empty-commit" --allow-empty && git push origin main [main 934ecba] empty-commit Username for 'https://gitlab.com': savitaashture Password for 'https://firstname.lastname@example.org': warning: redirecting to https://gitlab.com/savitaashture1/gitlabtest-triggers.git/ Enumerating objects: 1, done. Counting objects: 100% (1/1), done. Writing objects: 100% (1/1), 183 bytes | 183.00 KiB/s, done. Total 1 (delta 0), reused 0 (delta 0) To https://gitlab.com/savitaashture1/gitlabtest-triggers ff1d11e..934ecba main -> main
Events will be generated and sent to the EventListener pod. You can verify this by doing:
kubectl get pods -n demo kubectl logs -f <pod_name> -n demo
Verify successful delivery of events by doing a
get operation for
$ kubectl -n demo get taskruns | grep gitlab-run- gitlab-run-hvtll True Succeeded 95s 87s
Clean all resources created by Triggers by removing namespace
$ kubectl delete ns demo
Tekton Triggers is one of the most useful modules that help schedule workloads dynamically in response to a user-defined set of events. Because of this module, my team was able to achieve end-to-end CI/CD.