Skip to content

Instantly share code, notes, and snippets.

@bigkevmcd
Last active January 13, 2022 14:17
Show Gist options
  • Save bigkevmcd/cf2413ff0fd47191401181891cab9104 to your computer and use it in GitHub Desktop.
Save bigkevmcd/cf2413ff0fd47191401181891cab9104 to your computer and use it in GitHub Desktop.

Tekton Walkthrough

1. Install Tekton Pipeline and Triggers and Dashboard

$ kubectl apply -f https://github.com/tektoncd/pipeline/releases/download/v0.18.1/release.yaml
$ kubectl apply -f https://github.com/tektoncd/triggers/releases/download/v0.10.1/release.yaml
$ kubectl apply -f https://github.com/tektoncd/dashboard/releases/download/v0.11.1/tekton-dashboard-release.yaml

2. Install the Tekton CLI tool

https://github.com/tektoncd/cli#installing-tkn

Hello, World Task

hello-world-task.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: hello-world-task
spec:
  steps:
  - name: say-hello
    image: alpine
    script: |
        set +x
        echo "Hello, World!"
$ kubectl create -f hello-world-task.yaml

3. Create a simple TaskRun for the Task

hello-world-task-run.yaml

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  generateName: hello-world-
spec:
  taskRef:
    name: hello-world-task
$ kubectl create -f hello-world-task-run.yaml

Getting the results of the TaskRun

$ kubectl get taskrun/<insert taskrun>
NAME                SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME
hello-world-d6l84   True        Succeeded   30s         13s
$ kubectl get taskrun/<insert taskrun> -o yaml | yq r - 'status.podName'
$ kubectl logs pod/<task run pod>

Or alternatively...

$ tkn taskrun logs --last

4. Start the Task from tkn

$ tkn task start hello-world-task

5. Tekton Dashboard

Expose the Tekton Dashboard service

$ kubectl port-forward svc/tekton-dashboard 9097 -n tekton-pipelines

Or alternatively, use kube proxy...

$ kubectl proxy

And visit http://localhost:8001/api/v1/namespaces/tekton-pipelines/services/tekton-dashboard:http/proxy/#/namespaces/default/taskruns/

6. Adding a parameter to a Task

Update the hello-world-task.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: hello-world-task
spec:
  params:
  - name: name
    type: string
    default: World
    description: Name of the user to greet
  steps:
  - name: say-hello
    image: alpine
    script: |
        set +x
        echo "Hello, $(params.name)!"
$ kubectl replace -f hello-world-task.yaml

7. TaskRun for executing the Task with a parameter

Update the hello-world-task-run.yaml

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  generateName: hello-world-
spec:
  taskRef:
    name: hello-world-task
  params:
  - name: name
    value: universe
$ kubectl create -f hello-world-task-run.yaml
$ tkn taskrun logs --last

8. Execute the Taskrun from tkn with a parameter

$ tkn task start hello-world-task

9. Adding an additional step to the Task

Update the hello-world-task.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: hello-world-task
spec:
  params:
  - name: name
    type: string
    default: world
  steps:
  - name: say-hello
    image: alpine
    script: |
        set +x
        echo "Hello, $(params.name)"
  - name: say-goodbye
    image: alpine
    script: |
        set +x
        echo "Goodbye, $(params.name)"
$ kubectl replace -f hello-world-task.yaml
$ tkn task start hello-world-task

10. Executing a command inside a Task

execute-ls-task.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: execute-ls
spec:
  params:
  - name: path
    type: string
    default: "."
  steps:
  - name: ls-dir
    image: alpine
    command:
      - ls
    args:
      - $(params.path)
$ kubectl create -f execute-ls-task.yaml
$ tkn task start execute-ls

11. Task Results

top-language-task.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: top-language-task
spec:
  params:
    - name: repo
      type: string
      description: The repository full-name to query e.g. tektoncd/pipeline
  results:
    - name: top-language
      description: Top language for repo
  steps:
    - name: top-language
      image: bigkevmcd/jq-curl:latest
      script: |
        set +x
        echo -n `curl -s https://api.github.com/repos/$(params.repo)/languages | jq 'to_entries|sort_by(.value)[-1].key'` > $(results.top-language.path)
$ tkn task start top-language-task -p repo=bigkevmcd/go-demo
$ tkn taskrun describe --last
$ kubectl get taskrun/<task run> -o yaml | yq r - 'status.taskResults.(name==top-language).value'

12. First Pipeline

demo-pipeline.yaml

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: demo-pipeline
spec:
  params:
    - name: message
      description: incoming notification message
      type: string
  tasks:
    - name: task-echo-message
      taskRef:
         name: hello-world-task
         kind: Task
      params:
        - name: name
          value: $(params.message)
$ tkn pipeline start demo-pipeline

13. Combining Tasks into a Pipeline

Install the git-clone task.

https://github.com/tektoncd/catalog/tree/master/task/git-clone/0.2

$ kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/master/task/git-clone/0.2/git-clone.yaml

build-source-pipeline.yaml

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: build-source-pipeline
spec:
  params:
  - name: GIT_REPO
    type: string
    description: the clonable repo source e.g.  https://github.com/tektoncd/pipeline.git
  - name: GIT_REF
    type: string
    description: git revision to checkout (branch, tag, sha, ref…)
  tasks:
  - name: clone-source
    params:
    - name: url
      value: $(params.GIT_REPO)
    - name: revision
      value: $(params.GIT_REF)
    taskRef:
      kind: Task
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-data
  workspaces:
  - description: This workspace will receive the cloned git repo.
    name: shared-data
$ kubectl create -f build-source-pipeline.yaml
$ tkn pipeline start build-source-pipeline -p GIT_REF=refs/heads/master -p GIT_REPO=https://github.com/bigkevmcd/go-demo
$ tkn pipelinerun logs --last

13. Using a Task Result

build-source-pipeline.yaml

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: build-source-pipeline
spec:
  params:
  - name: GIT_REPO
    type: string
    description: the clonable repo source e.g.  https://github.com/tektoncd/pipeline.git
  - name: GIT_REF
    type: string
    description: git revision to checkout (branch, tag, sha, ref…)
  tasks:
  - name: clone-source
    params:
    - name: url
      value: $(params.GIT_REPO)
    - name: revision
      value: $(params.GIT_REF)
    taskRef:
      kind: Task
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-data
  - name: echo-results
    runAfter:
      - clone-source
    taskSpec:
      params:
        - name: commit
          type: string
        - name: url
          type: string
      steps:
      - name: echo-git-result
        image: alpine
        script: |
          echo $(params.commit)
          echo $(params.url)
    params:
      - name: commit
        value: $(tasks.clone-source.results.commit)
      - name: url
        value: $(tasks.clone-source.results.url)
  workspaces:
  - description: This workspace will receive the cloned git repo.
    name: shared-data
$ kubectl replace -f build-source-pipeline.yaml

And execute it with a PipelineRun.

build-source-pipelinerun.yaml

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: build-source-pipeline-
spec:
  params:
  - name: GIT_REPO
    value: https://github.com/bigkevmcd/go-demo.git
  - name: GIT_REF
    value: master
  pipelineRef:
      name: build-source-pipeline
  workspaces:
  - name: shared-data
    volumeClaimTemplate:
      metadata:
        creationTimestamp: null
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
$ kubectl create -f build-source-pipeline.yaml

15. Building an image from Source

Install the Buildah task, it builds an image from a source repository with a Dockerfile.

https://github.com/tektoncd/catalog/tree/master/task/buildah/0.2

$ kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/master/task/buildah/0.2/buildah.yaml

We need a secret ...

$ kubectl create secret generic regcred \
  --from-file=.dockerconfigjson=$HOME/.docker/config.json \
  --type=kubernetes.io/dockerconfigjson

And grant access to that secret from the default serviceaccount

$ kubectl patch serviceaccount default \
  -p '{"secrets": [{"name": "regcred"}]}'

build-source-pipeline.yaml

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: build-source-pipeline
spec:
  params:
  - name: GIT_REPO
    type: string
    description: the clonable repo source e.g.  https://github.com/tektoncd/pipeline.git
  - name: GIT_REF
    type: string
    description: git revision to checkout (branch, tag, sha, ref…)
  - name: IMAGE
    type: string
    description: image repository to push the completed build to
  tasks:
  - name: clone-source
    params:
    - name: url
      value: $(params.GIT_REPO)
    - name: revision
      value: $(params.GIT_REF)
    taskRef:
      kind: Task
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-data
  - name: build-image
    runAfter:
      - clone-source
    taskRef:
      kind: Task
      name: buildah
    params:
    - name: IMAGE
      value: $(params.IMAGE)
    workspaces:
    - name: source
      workspace: shared-data
  workspaces:
  - description: This workspace will receive the cloned git repo.
    name: shared-data

build-source-pipelinerun.yaml

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: build-source-pipeline-
spec:
  params:
  - name: GIT_REPO
    value: https://github.com/bigkevmcd/go-demo.git
  - name: GIT_REF
    value: master
  - name: IMAGE
    value: quay.io/kmcdermo/demo:latest
  pipelineRef:
      name: build-source-pipeline
  workspaces:
  - name: shared-data
    volumeClaimTemplate:
      metadata:
        creationTimestamp: null
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
$ kubectl create -f build-source-pipelinerun.yaml

16. Let's lint the code.

go-test-task.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: go-test-task
spec:
  params:
    - name: lint-version
      description: the version of golangci-lint to run
      default: v1.33.0
  workspaces:
    - name: source
      description: the git source to execute on
  steps:
    - name: go-mod-setup
      image: golang:latest
      workingDir: $(workspaces.source.path)
      command: ["go", "mod", "download"]

    - name: go-vet
      image: golang:latest
      workingDir: $(workspaces.source.path)
      command: ["go", "vet", "./..."]

    - name: ci-lint
      image: golangci/golangci-lint:$(params.lint-version)
      workingDir: $(workspaces.source.path)
      command: ["golangci-lint", "run"]

    - name: go-test
      image: golang:latest
      workingDir: $(workspaces.source.path)
      command: ["go", "test", "./..."]

Insert this task into build-source-pipeline.yaml

  - name: check-source
    runAfter:
      - clone-source
    taskRef:
      kind: Task
      name: go-test-task
    workspaces:
    - name: source
      workspace: shared-data

Update the set of tasks, so that the tests run (and fail) after check-source.

$ kubectl create -f build-source-pipelinerun.yaml

17. First EventListener

demo-event-listener.yaml

Need to grant permissions for Tekton to execute in the default namespace.

$ kubectl apply -f https://gist.github.com/bigkevmcd/cf2413ff0fd47191401181891cab9104/raw/89979a254625958431ff1551a94b851e3a724c77/permissions.yaml
apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: demo-event-listener
spec:
  serviceAccountName: demo-sa
  triggers:
  - name: demo-trigger
    template:
      name: demo-template
    bindings:
    - ref: demo-binding

demo-binding.yaml

apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerBinding
metadata:
  name: demo-binding
spec:
  params:
  - name: message
    value: $(body.message)

demo-template.yaml

apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
  name: demo-template
spec:
  params:
  - description: message
    name: message
  resourcetemplates:
  - apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      annotations:
      name: demo-run-$(uid)
    spec:
      params:
      - name: message
        value: $(tt.params.message)
      pipelineRef:
        name: demo-pipeline
$ kubectl apply -f demo-template.yaml
$ kubectl apply -f demo-binding.yaml
$ kubectl apply -f demo-event-listener.yaml

Trigger a PipelineRun:

$ kubectl port-forward svc/el-demo-event-listener 8080
$ curl -H "Content-Type: application/json" -d '{"message": "from JSON"}' http://localhost:8080/

18. GitHub Interceptor

$ kubectl create secret generic github-secret --from-literal=secretToken=abcdefghihj

The documentation for the GitHub Push event:

https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#push

github-event-listener.yaml

apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: github-event-listener
spec:
  serviceAccountName: demo-sa
  triggers:
  - name: demo-trigger
    interceptors:
      - github:
          secretRef:
            secretName: github-secret
            secretKey: secretToken
          eventTypes:
            - push
    template:
      name: build-code-template
    bindings:
    - ref: github-push-binding

github-push-binding.yaml

apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerBinding
metadata:
  name: github-push-binding
spec:
  params:
  - name: gitref
    value: $(body.head_commit.id)
  - name: gitrepositoryurl
    value: $(body.repository.clone_url)

build-code-template.yaml

apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
  name: build-code-template
spec:
  params:
  - name: gitref
    description: The specific ref to build from the repo.
  - name: gitrepositoryurl
    description: The repo to build from.
  resourcetemplates:
    - apiVersion: tekton.dev/v1beta1
      kind: PipelineRun
      metadata:
        name: build-source-pipeline-$(uid)
      spec:
        params:
        - name: GIT_REPO
          value: $(tt.params.gitrepositoryurl)
        - name: GIT_REF
          value: $(tt.params.gitref)
        - name: IMAGE
          value: bigkevmcd/tekton-demo:$(tt.params.gitref)
        pipelineRef:
            name: build-source-pipeline
        workspaces:
        - name: shared-data
          volumeClaimTemplate:
            metadata:
              creationTimestamp: null
            spec:
              accessModes:
              - ReadWriteOnce
              resources:
                requests:
                  storage: 1Gi

19. CEL Interceptor

github-event-listener.yaml

apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
  name: github-event-listener
spec:
  serviceAccountName: demo-sa
  triggers:
  - name: demo-trigger
    interceptors:
      - github:
          secretRef:
            secretName: github-secret
            secretKey: secretToken
          eventTypes:
            - push
      - cel:
          filter: body.repository.full_name == 'bigkevmcd/no-demo'
          overlays:
            - key: intercepted.short_sha
              expression: body.head_commit.id.truncate(7)
    template:
      name: build-code-template
    bindings:
    - ref: github-push-binding

github-push-binding.yaml

apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerBinding
metadata:
  name: github-push-binding
spec:
  params:
  - name: gitref
    value: $(body.head_commit.id)
  - name: gitrepositoryurl
    value: $(body.repository.clone_url)
  - name: shortsha
    value: $(extensions.intercepted.short_sha)

build-code-template.yaml

apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
  name: build-code-template
spec:
  params:
    - name: gitref
      description: The specific ref to build from the repo.
    - name: gitrepositoryurl
      description: The repo to build from.
    - name: shortsha
      description: shortened version of the SHA useful for tagging.
  resourcetemplates:
    - apiVersion: tekton.dev/v1beta1
      kind: PipelineRun
      metadata:
        name: build-source-pipeline-$(uid)
      spec:
        params:
          - name: GIT_REPO
            value: $(tt.params.gitrepositoryurl)
          - name: GIT_REF
            value: $(tt.params.gitref)
          - name: IMAGE
            value: bigkevmcd/demo:$(tt.params.shortsha)
        pipelineRef:
          name: build-source-pipeline
        workspaces:
          - name: shared-data
            volumeClaimTemplate:
              metadata:
                creationTimestamp: null
              spec:
                accessModes:
                - ReadWriteOnce
                resources:
                  requests:
                    storage: 1Gi

20. Debugging EventListeners

21. VSCode extensions

22. ClusterTasks vs Tasks

23. Embedded PipelineRuns

24. Final Tasks

  finally:
    # Cleanup workspace
    - name: cleanup
      taskSpec:
        name: cleanup-workspace
        image: alpine
        command: ["echo", "cleaning up"]

25. Kubernetes Events

$ kubectl get events

https://github.com/tektoncd/pipeline/blob/master/docs/events.md

26. CloudEvents

FROM alpine:3.12
RUN apk add --no-cache curl jq bash
CMD ["/bin/sh"]
apiVersion: v1
kind: ServiceAccount
metadata:
name: demo-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: demo-role
rules:
- apiGroups:
- triggers.tekton.dev
resources:
- eventlisteners
- triggerbindings
- triggertemplates
- triggers
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- tekton.dev
resources:
- pipelineruns
- pipelineresources
- taskruns
verbs:
- create
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- impersonate
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: demo-clusterrole
rules:
- apiGroups:
- triggers.tekton.dev
resources:
- clustertriggerbindings
- eventlisteners
- triggerbindings
- triggertemplates
- triggers
verbs:
- get
- list
- watch
- apiGroups:
- tekton.dev
resources:
- pipelineruns
- pipelineresources
- taskruns
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: demo-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: demo-role
subjects:
- kind: ServiceAccount
name: demo-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: demo-clusterrole-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: demo-clusterrole
subjects:
- kind: ServiceAccount
name: demo-sa
namespace: default
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment