Tasks

A Task (or a ClusterTask) is a collection of sequentialsteps you would want to run as part of your continuous integration flow. A taskwill run inside a pod on your cluster.

A Task declares:

A Task is available within a namespace, and ClusterTask is available acrossentire Kubernetes cluster.

ClusterTask

Similar to Task, but with a cluster scope.

In case of using a ClusterTask, the TaskRef kind should be added. The defaultkind is Task which represents a namespaced Task

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Pipeline
  3. metadata:
  4. name: demo-pipeline
  5. namespace: default
  6. spec:
  7. tasks:
  8. - name: build-skaffold-web
  9. taskRef:
  10. name: build-push
  11. kind: ClusterTask
  12. params: ....

A Task functions exactly like a ClusterTask, and as such all references toTask below are also describing ClusterTask.

Syntax

To define a configuration file for a Task resource, you can specify thefollowing fields:

  • Required:
    • apiVersion - Specifies the API version, for exampletekton.dev/v1beta.
    • kind - Specify the Task resource object.
    • metadata - Specifies data to uniquely identify theTask resource object, for example a name.
    • spec - Specifies the configuration information foryour Task resource object. Task steps must be defined through either ofthe following fields:
    • steps - Specifies one or more container images that you wantto run in your Task.
  • Optional:
    • description - Description of the Task.
    • params - Specifies parameters
    • resources - SpecifiesPipelineResources needed or created by yourTask. Note: this is an alpha field, it is not supported as therest of the beta field.
    • inputs - resources needed by your Task.
    • outputs - resources created by your Task
    • workspaces - Specifies paths at which you expect volumes tobe mounted and available
    • results - Specifies the result file name where the task can write its result
    • volumes - Specifies one or more volumes that you want to makeavailable to your Task’s steps.
    • stepTemplate - Specifies a Container stepdefinition to use as the basis for all steps within your Task.
    • sidecars - Specifies sidecar containers to run alongsidesteps.

The following example is a non-working sample where most of the possibleconfiguration fields are used:

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Task
  3. metadata:
  4. name: example-task-name
  5. spec:
  6. params:
  7. - name: pathToDockerFile
  8. type: string
  9. description: The path to the dockerfile to build
  10. default: /workspace/workspace/Dockerfile
  11. resources:
  12. inputs:
  13. - name: workspace
  14. type: git
  15. outputs:
  16. - name: builtImage
  17. type: image
  18. steps:
  19. - name: ubuntu-example
  20. image: ubuntu
  21. args: ["ubuntu-build-example", "SECRETS-example.md"]
  22. - image: gcr.io/example-builders/build-example
  23. command: ["echo"]
  24. args: ["$(params.pathToDockerFile)"]
  25. - name: dockerfile-pushexample
  26. image: gcr.io/example-builders/push-example
  27. args: ["push", "$(resources.outputs.builtImage.url)"]
  28. volumeMounts:
  29. - name: docker-socket-example
  30. mountPath: /var/run/docker.sock
  31. volumes:
  32. - name: example-volume
  33. emptyDir: {}

Steps

The steps field is required. You define one or more steps fields to definethe body of a Task.

If multiple steps are defined, they will be executed in the same order as theyare defined, if the Task is invoked by a TaskRun.Each steps in a Task must specify a container image that adheres to thecontainer contract. For each of the steps fields,or container images that you define:

  • The container images are run and evaluated in order, starting from the top ofthe configuration file.
  • Each container image runs until completion or until the first failure isdetected.
  • The CPU, memory, and ephemeral storage resource requests will be set to zeroif the container image does not have the largest resource request out of allcontainer images in the Task. This ensures that the Pod that executes the Taskwill only request the resources necessary to execute any single containerimage in the Task, rather than requesting the sum of all of the containerimage’s resource requests.

Step Script

To simplify executing scripts inside a container, a step can specify a script.If this field is present, the step cannot specify command.

When specified, a script gets invoked as if it were the contents of a file inthe container. Any args are passed to the script file.

Scripts that do not start with a shebang)line will use the following default preamble:

  1. #!/bin/sh
  2. set -xe

Users can override this by starting their script with a shebang to declare whattool should be used to interpret the script. That tool must then also beavailable within the step’s container.

This allows you to execute a Bash script, if the image includes bash:

  1. steps:
  2. - image: ubuntu # contains bash
  3. script: |
  4. #!/usr/bin/env bash
  5. echo "Hello from Bash!"

…or to execute a Python script, if the image includes python:

  1. steps:
  2. - image: python # contains python
  3. script: |
  4. #!/usr/bin/env python3
  5. print("Hello from Python!")

…or to execute a Node script, if the image includes node:

  1. steps:
  2. - image: node # contains node
  3. script: |
  4. #!/usr/bin/env node
  5. console.log("Hello from Node!")

This also simplifies executing script files in the workspace:

  1. steps:
  2. - image: ubuntu
  3. script: |
  4. #!/usr/bin/env bash
  5. /workspace/my-script.sh # provided by an input resource

…or in the container image:

  1. steps:
  2. - image: my-image # contains /bin/my-binary
  3. script: |
  4. #!/usr/bin/env bash
  5. /bin/my-binary

Description

The description field is an optional field and can be used to provide description of the Task.

Parameters

Tasks can declare input parameters that must be supplied to the task during aTaskRun. Some example use-cases of this include:

  • A Task that needs to know what compilation flags to use when building anapplication.
  • A Task that needs to know what to name a built artifact.

Parameters name are limited to alpha-numeric characters, - and and canonly start with alpha characters and . For example, fooIs-Bar_ is a validparameter name, barIsBa$ or 0banana are not.

Each declared parameter has a type field, assumed to be string if not provided by the user. The other possible type is array — useful, for instance, when a dynamic number of compilation flags need to be supplied to a task building an application. When the actual parameter value is supplied, its parsed type is validated against the type field.

Usage

The following example shows how Tasks can be parameterized, and these parameterscan be passed to the Task from a TaskRun.

Input parameters in the form of $(params.foo) are replaced inside ofthe steps (see also variable substitution).

The following Task declares two input parameters named ‘flags’ (array) and ‘someURL’ (string), and uses them inthe steps.args list. Array parameters like ‘flags’ can be expanded inside of an existing array by using star expansion syntax by adding [] to the named parameter as we do below using $(params.flags[]).

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Task
  3. metadata:
  4. name: task-with-parameters
  5. spec:
  6. params:
  7. - name: flags
  8. type: array
  9. - name: someURL
  10. type: string
  11. steps:
  12. - name: build
  13. image: my-builder
  14. args: ["build", "$(params.flags[*])", "url=$(params.someURL)"]

The following TaskRun supplies a dynamic number of strings within the flags parameter:

  1. apiVersion: tekton.dev/v1beta1
  2. kind: TaskRun
  3. metadata:
  4. name: run-with-parameters
  5. spec:
  6. taskRef:
  7. name: task-with-parameters
  8. params:
  9. - name: flags
  10. value:
  11. - "--set"
  12. - "arg1=foo"
  13. - "--randomflag"
  14. - "--someotherflag"
  15. - name: someURL
  16. value: "http://google.com"

Resources

A Task can declare the resources it needs and create, which can be either or both of:

Input resources

Use input PipelineResources field to provide your Task withdata or context that is needed by your Task. See the using resources docs.

Output resources

Task definitions can include inputs and outputsPipelineResource declarations. If specific set of resourcesare only declared in output then a copy of resource to be uploaded or shared fornext Task is expected to be present under the path/workspace/output/resource_name/.

  1. resources:
  2. outputs:
  3. name: storage-gcs
  4. type: gcs
  5. steps:
  6. - image: objectuser/run-java-jar #https://hub.docker.com/r/objectuser/run-java-jar/
  7. command: [jar]
  8. args:
  9. ["-cvf", "-o", "/workspace/output/storage-gcs/", "projectname.war", "*"]
  10. env:
  11. - name: "FOO"
  12. value: "world"

note: if the task is relying on output resource functionality then thecontainers in the task steps field cannot mount anything in the path/workspace/output.

In the following example Task tar-artifact resource is used both as input andoutput so input resource is downloaded into directory customworkspace(asspecified in targetPath). Step untar extracts tar file intotar-scratch-space directory , edit-tar adds a new file and last steptar-it-up creates new tar file and places in /workspace/customworkspace/directory. After execution of the Task steps, (new) tar file in directory/workspace/customworkspace will be uploaded to the bucket defined intar-artifact resource definition.

  1. resources:
  2. inputs:
  3. name: tar-artifact
  4. targetPath: customworkspace
  5. outputs:
  6. name: tar-artifact
  7. steps:
  8. - name: untar
  9. image: ubuntu
  10. command: ["/bin/bash"]
  11. args: ['-c', 'mkdir -p /workspace/tar-scratch-space/ && tar -xvf /workspace/customworkspace/rules_docker-master.tar -C /workspace/tar-scratch-space/']
  12. - name: edit-tar
  13. image: ubuntu
  14. command: ["/bin/bash"]
  15. args: ['-c', 'echo crazy > /workspace/tar-scratch-space/rules_docker-master/crazy.txt']
  16. - name: tar-it-up
  17. image: ubuntu
  18. command: ["/bin/bash"]
  19. args: ['-c', 'cd /workspace/tar-scratch-space/ && tar -cvf /workspace/customworkspace/rules_docker-master.tar rules_docker-master']

Workspaces

workspaces are a way of declaring volumes you expect to be made available to yourexecuting Task and the path to make them available at.

Here’s a short example of a Task spec with a workspace:

  1. spec:
  2. steps:
  3. - name: write-message
  4. image: ubuntu
  5. script: |
  6. #!/usr/bin/env bash
  7. set -xe
  8. echo hello! > $(workspaces.messages.path)/message
  9. workspaces:
  10. - name: messages
  11. description: The folder where we write the message to
  12. mountPath: /custom/path/relative/to/root

For complete documentation on using workspaces in Tasks, seeworkspaces.md.

For a complete example see the Workspaces TaskRunin the examples directory.

Results

Specifies one or more result files in which you want the task’s steps to write a result. All result files are writteninto the /tekton/results folder. This folder is created automatically if the task defines one or more results.

For example, this task:

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Task
  3. metadata:
  4. name: print-date
  5. annotations:
  6. description: |
  7. A simple task that prints the date
  8. spec:
  9. results:
  10. - name: current-date-unix-timestamp
  11. description: The current date in unix timestamp format
  12. - name: current-date-human-readable
  13. description: The current date in human readable format
  14. steps:
  15. - name: print-date-unix-timestamp
  16. image: bash:latest
  17. script: |
  18. #!/usr/bin/env bash
  19. date +%s | tee /tekton/results/current-date-unix-timestamp
  20. - name: print-date-humman-readable
  21. image: bash:latest
  22. script: |
  23. #!/usr/bin/env bash
  24. date | tee /tekton/results/current-date-human-readable

defines two results current-date-unix-timestamp and current-date-human-readable. To define a result, you specify a name that will correspond to the file name in the /tekton/results folder and a description where you can explain the purpose of the result.

Note: The maximum size of a Task’s results is limited by Kubernetes’ container termination log feature. The resultsare passed back to the controller via this mechanism. At time of writing this has a capped maximum size of“2048 bytes or 80 lines, whichever is smaller”.

A Task Result is encoded as a JSON object when it is written to the termination log and Tekton also uses thisobject to pass some other information back to the controller as well. As such Task Results are best utilized forsmall pieces of data. Good candidates are commit SHAs, branch names, ephemeral namespace names, and so on.

If you are writing many small Task Results from a single Task you can work around this size limit by writingthe results from separate Steps - each Step has its own termination log. But for data larger than a kilobytethe next best alternative is to use a Workspace to shuttle data between Tasks in a Pipeline.

Volumes

Specifies one or morevolumes that you want tomake available to your Task, including all the steps. Add volumesto complement the volumes that are implicitly created forinput resources and output resources.

For example, use volumes to accomplish one of the following common tasks:

  • Mount a Kubernetes secret.
  • Create an emptyDir volume to act as a cache for use across multiple buildsteps. Consider using a persistent volume for inter-build caching.
  • MountKubernetes configmapas volume source.
  • Mount a host’s Docker socket to use a Dockerfile for container image builds.Note: Building a container image using docker build on-cluster is veryunsafe. Use kaniko instead.This is used only for the purposes of demonstration.

Step Template

Specifies a Containerconfiguration that will be used as the basis for all steps in yourTask. Configuration in an individual step will override or merge with thestep template’s configuration.

In the example below, the Task specifies a stepTemplate with theenvironment variable FOO set to bar. The first step will use that value forFOO, but in the second step, FOO is overridden and set to baz.

  1. stepTemplate:
  2. env:
  3. - name: "FOO"
  4. value: "bar"
  5. steps:
  6. - image: ubuntu
  7. command: [echo]
  8. args: ["FOO is ${FOO}"]
  9. - image: ubuntu
  10. command: [echo]
  11. args: ["FOO is ${FOO}"]
  12. env:
  13. - name: "FOO"
  14. value: "baz"

Sidecars

Specifies a list ofContainers to runalongside your Steps. These containers can provide auxiliary functions likeDocker in Docker or running a mock APIserver for your app to hit during tests.

Sidecars are started before your Task’s steps are executed and are torndown after all steps have completed. For further information about a sidecar’slifecycle see the TaskRun doc.

In the example below, a Docker in Docker sidecar is run so that a step canuse it to build a docker image:

  1. steps:
  2. - image: docker
  3. name: client
  4. script: |
  5. #!/usr/bin/env bash
  6. cat > Dockerfile << EOF
  7. FROM ubuntu
  8. RUN apt-get update
  9. ENTRYPOINT ["echo", "hello"]
  10. EOF
  11. docker build -t hello . && docker run hello
  12. docker images
  13. volumeMounts:
  14. - mountPath: /var/run/
  15. name: dind-socket
  16. sidecars:
  17. - image: docker:18.05-dind
  18. name: server
  19. securityContext:
  20. privileged: true
  21. volumeMounts:
  22. - mountPath: /var/lib/docker
  23. name: dind-storage
  24. - mountPath: /var/run/
  25. name: dind-socket
  26. volumes:
  27. - name: dind-storage
  28. emptyDir: {}
  29. - name: dind-socket
  30. emptyDir: {}

Sidecars can also run a script, like a Step:

  1. sidecars:
  2. image: busybox
  3. name: hello-sidecar
  4. script: |
  5. echo 'Hello from sidecar!'

Note: There is a known bug with Tekton’s existing sidecar implementation.Tekton uses a specific image, called “nop”, to stop sidecars. The “nop” imageis configurable using a flag of the Tekton controller. If the configured “nop”image contains the command that the sidecar was running before the sidecarwas stopped then the sidecar will actually keep running, causing the TaskRun’sPod to remain running, and eventually causing the TaskRun to timeout ratherthen exit successfully. Issue 1347has been created to track this bug.

Variable Substitution

Tasks support string replacement using values from:

Parameter and Resource substitution

params and resources attributes can be used in replacements,including params and resources.

Parameters can be referenced in the Task spec using the variable substitution syntax below,where <name> is the name of the parameter:

  1. $(params.<name>)

Param values from resources can also be accessed using variable substitution

Variable Substitution with Parameters of Type Array

Referenced parameters of type array can be expanded using ‘star-expansion’ by adding [*] to the named parameter to insert the array elements in the reference string’s spot.

So, with the following parameter:

  1. params:
  2. - name: array-param
  3. value:
  4. - "some"
  5. - "array"
  6. - "elements"

then command: ["first", "$(params.array-param[*])", "last"] will becomecommand: ["first", "some", "array", "elements", "last"]

Note that array parameters must be referenced in a completely isolated string within a larger string array.Any other attempt to reference an array is invalid and will throw an error.

For instance, if build-args is a declared parameter of type array, then this is an invalid step becausethe string isn’t isolated:

  1. - name: build-step
  2. image: gcr.io/cloud-builders/some-image
  3. args: ["build", "additionalArg $(params.build-args[*])"]

Similarly, referencing build-args in a non-array field is also invalid:

  1. - name: build-step
  2. image: "$(params.build-args[*])"
  3. args: ["build", "args"]

A valid reference to the build-args parameter is isolated and in an eligible field (args, in this case):

  1. - name: build-step
  2. image: gcr.io/cloud-builders/some-image
  3. args: ["build", "$(params.build-args[*])", "additonalArg"]

Variable Substitution with Workspaces

Paths to a Task's declared workspaces can be substituted with:

  1. $(workspaces.myworkspace.path)

Since the name of the Volume is not known until runtime and is randomized, you can alsosubstitute the volume name with:

  1. $(workspaces.myworkspace.volume)

Variable Substitution within Volumes

Task volume names and differenttypes of volumescan be parameterized. Current support includes for widely used types of volumeslike configmap, secret and PersistentVolumeClaim. Here is anexample on how to use this inTask definitions.

Examples

Use these code snippets to help you understand how to define your Tasks.

Tip: See the collection of simpleexamples foradditional code samples.

Example Task

For example, a Task to encapsulate a Dockerfile build might look somethinglike this:

Note: Building a container image using docker build on-cluster is veryunsafe. Use kaniko instead.This is used only for the purposes of demonstration.

  1. spec:
  2. params:
  3. # These may be overridden, but provide sensible defaults.
  4. - name: directory
  5. type: string
  6. description: The directory containing the build context.
  7. default: /workspace
  8. - name: dockerfileName
  9. type: string
  10. description: The name of the Dockerfile
  11. default: Dockerfile
  12. resources:
  13. inputs:
  14. - name: workspace
  15. type: git
  16. outputs:
  17. - name: builtImage
  18. type: image
  19. steps:
  20. - name: dockerfile-build
  21. image: gcr.io/cloud-builders/docker
  22. workingDir: "$(params.directory)"
  23. args:
  24. [
  25. "build",
  26. "--no-cache",
  27. "--tag",
  28. "$(resources.outputs.image.url)",
  29. "--file",
  30. "$(params.dockerfileName)",
  31. ".",
  32. ]
  33. volumeMounts:
  34. - name: docker-socket
  35. mountPath: /var/run/docker.sock
  36. - name: dockerfile-push
  37. image: gcr.io/cloud-builders/docker
  38. args: ["push", "$(resources.outputs.image.url)"]
  39. volumeMounts:
  40. - name: docker-socket
  41. mountPath: /var/run/docker.sock
  42. # As an implementation detail, this Task mounts the host's daemon socket.
  43. volumes:
  44. - name: docker-socket
  45. hostPath:
  46. path: /var/run/docker.sock
  47. type: Socket

Using an extra volume

Mounting multiple volumes:

  1. spec:
  2. steps:
  3. - image: ubuntu
  4. script: |
  5. #!/usr/bin/env bash
  6. curl https://foo.com > /var/my-volume
  7. volumeMounts:
  8. - name: my-volume
  9. mountPath: /var/my-volume
  10. - image: ubuntu
  11. script: |
  12. #!/usr/bin/env bash
  13. cat /etc/my-volume
  14. volumeMounts:
  15. - name: my-volume
  16. mountPath: /etc/my-volume
  17. volumes:
  18. - name: my-volume
  19. emptyDir: {}

Using Kubernetes Configmap as Volume Source

  1. spec:
  2. params:
  3. - name: CFGNAME
  4. type: string
  5. description: Name of config map
  6. - name: volumeName
  7. type: string
  8. description: Name of volume
  9. steps:
  10. - image: ubuntu
  11. script: |
  12. #!/usr/bin/env bash
  13. cat /var/configmap/test
  14. volumeMounts:
  15. - name: "$(params.volumeName)"
  16. mountPath: /var/configmap
  17. volumes:
  18. - name: "$(params.volumeName)"
  19. configMap:
  20. name: "$(params.CFGNAME)"

Using secret as environment source

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Task
  3. metadata:
  4. name: goreleaser
  5. spec:
  6. params:
  7. - name: package
  8. type: string
  9. description: base package to build in
  10. - name: github-token-secret
  11. type: string
  12. description: name of the secret holding the github-token
  13. default: github-token
  14. resources:
  15. inputs:
  16. - name: source
  17. type: git
  18. targetPath: src/$(params.package)
  19. steps:
  20. - name: release
  21. image: goreleaser/goreleaser
  22. workingDir: /workspace/src/$(params.package)
  23. command:
  24. - goreleaser
  25. args:
  26. - release
  27. env:
  28. - name: GOPATH
  29. value: /workspace
  30. - name: GITHUB_TOKEN
  31. valueFrom:
  32. secretKeyRef:
  33. name: $(params.github-token-secret)
  34. key: bot-token

Using a sidecar

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Task
  3. metadata:
  4. name: with-sidecar-task
  5. spec:
  6. params:
  7. - name: sidecar-image
  8. type: string
  9. description: Image name of the sidecar container
  10. - name: sidecar-env
  11. type: string
  12. description: Environment variable value
  13. sidecars:
  14. - name: sidecar
  15. image: $(params.sidecar-image)
  16. env:
  17. - name: SIDECAR_ENV
  18. value: $(params.sidecar-env)
  19. steps:
  20. - name: test
  21. image: hello-world

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License,and code samples are licensed under theApache 2.0 License.

Debugging

In software, we do things not because they are easy, but because we think they will be.Lots of things can go wrong when writing a Task.This section contains some tips on how to debug one.

Inspecting the Filesystem

One common problem when writing Tasks is not understanding where files are on disk.For the most part, these all live somewhere under /workspace, but the exact layout canbe tricky.To see where things are before your task runs, you can add a step like this:

  1. - name: build-and-push-1
  2. image: ubuntu
  3. command:
  4. - /bin/bash
  5. args:
  6. - -c
  7. - |
  8. set -ex
  9. find /workspace

This step will output the name of every file under /workspace to your build logs.

To see the contents of every file, you can use a similar step:

  1. - name: build-and-push-1
  2. image: ubuntu
  3. command:
  4. - /bin/bash
  5. args:
  6. - -c
  7. - |
  8. set -ex
  9. find /workspace | xargs cat

These steps are useful both before and after your Task steps!

Inspecting the pod

One task will map to one Pod, to check arbitrary thing in Pod, the best way is to login the pod, add a step at the position you want to pause the task, then checking.

  1. - name: pause
  2. image: docker
  3. args: ["sleep", "6000"]