Skip to content

Latest commit

 

History

History
514 lines (430 loc) · 15.3 KB

tasks.md

File metadata and controls

514 lines (430 loc) · 15.3 KB

Tasks

A Task (or a ClusterTask) is a collection of sequential steps you would want to run as part of your continuous integration flow. A task will run inside a container on your cluster.

A Task declares:

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


ClusterTask

Similar to Task, but with a cluster scope.

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

apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
  name: demo-pipeline
  namespace: default
spec:
  tasks:
    - name: build-skaffold-web
      taskRef:
        name: build-push
        kind: ClusterTask
      params: ....

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

Syntax

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

  • Required:
    • apiVersion - Specifies the API version, for example tekton.dev/v1alpha1.
    • kind - Specify the Task resource object.
    • metadata - Specifies data to uniquely identify the Task resource object, for example a name.
    • spec - Specifies the configuration information for your Task resource object. Task steps must be defined through either of the following fields:
      • steps - Specifies one or more container images that you want to run in your Task.
  • Optional:

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

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: example-task-name
spec:
  inputs:
    resources:
      - name: workspace
        type: git
    params:
      - name: pathToDockerFile
        description: The path to the dockerfile to build
        default: /workspace/workspace/Dockerfile
  outputs:
    resources:
      - name: builtImage
        type: image
  steps:
    - name: ubuntu-example
      image: ubuntu
      args: ["ubuntu-build-example", "SECRETS-example.md"]
    - image: gcr.io/example-builders/build-example
      command: ["echo"]
      args: ["${inputs.resources.params.pathToDockerFile}"]
    - name: dockerfile-pushexample
      image: gcr.io/example-builders/push-example
      args: ["push", "${outputs.resources.builtImage.url}"]
      volumeMounts:
        - name: docker-socket-example
          mountPath: /var/run/docker.sock
  volumes:
    - name: example-volume
      emptyDir: {}

Steps

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

Each steps in a Task must specify a container image that adheres to the container 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 of the configuration file.
  • Each container image runs until completion or until the first failure is detected.
  • The CPU, memory, and ephemeral storage resource requests will be set to zero if the container image does not have the largest resource request out of all container images in the Task. This ensures that the Pod that executes the Task will only request the resources necessary to execute any single container image in the Task, rather than requesting the sum of all of the container image's resource requests.

Inputs

A Task can declare the inputs it needs, which can be either or both of:

Parameters

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

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

Parameters name are limited to alpha-numeric characters, - and _ and can only start with alpha characters and _. For example, fooIs-Bar_ is a valid parameter name, barIsBa$ or 0banana are not.

Usage

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

Input parameters in the form of ${inputs.params.foo} are replaced inside of the steps (see also templating).

The following Task declares an input parameter called 'flags', and uses it in the steps.args list.

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: task-with-parameters
spec:
  inputs:
    params:
      - name: flags
        value: -someflag
  steps:
    - name: build
      image: my-builder
      args: ["build", "--flags=${inputs.params.flags}"]

The following TaskRun supplies a value for flags:

apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
  name: run-with-parameters
spec:
  taskRef:
    name: task-with-parameters
  inputs:
    params:
      - name: "flags"
        value: "foo=bar,baz=bat"

Input resources

Use input PipelineResources field to provide your Task with data or context that is needed by your Task.

Input resources, like source code (git) or artifacts, are dumped at path /workspace/task_resource_name within a mounted volume and is available to all steps of your Task. The path that the resources are mounted at can be overridden with the targetPath value.

Outputs

Task definitions can include inputs and outputs PipelineResource declarations. If specific set of resources are only declared in output then a copy of resource to be uploaded or shared for next Task is expected to be present under the path /workspace/output/resource_name/.

resources:
  outputs:
    name: storage-gcs
    type: gcs
steps:
  - image: objectuser/run-java-jar #https://hub.docker.com/r/objectuser/run-java-jar/
    command: [jar]
    args:
      ["-cvf", "-o", "/workspace/output/storage-gcs/", "projectname.war", "*"]
    env:
      - name: "FOO"
        value: "world"

note: if the task is relying on output resource functionality then the containers 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 and output so input resource is downloaded into directory customworkspace(as specified in targetPath). Step untar extracts tar file into tar-scratch-space directory , edit-tar adds a new file and last step tar-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 in tar-artifact resource definition.

resources:
  inputs:
    name: tar-artifact
    targetPath: customworkspace
  outputs:
    name: tar-artifact
steps:
 - name: untar
    image: ubuntu
    command: ["/bin/bash"]
    args: ['-c', 'mkdir -p /workspace/tar-scratch-space/ && tar -xvf /workspace/customworkspace/rules_docker-master.tar -C /workspace/tar-scratch-space/']
 - name: edit-tar
    image: ubuntu
    command: ["/bin/bash"]
    args: ['-c', 'echo crazy > /workspace/tar-scratch-space/rules_docker-master/crazy.txt']
 - name: tar-it-up
   image: ubuntu
   command: ["/bin/bash"]
   args: ['-c', 'cd /workspace/tar-scratch-space/ && tar -cvf /workspace/customworkspace/rules_docker-master.tar rules_docker-master']

Controlling where resources are mounted

Tasks can opitionally provide targetPath to initialize resource in specific directory. If targetPath is set then resource will be initialized under /workspace/targetPath. If targetPath is not specified then resource will be initialized under /workspace. Following example demonstrates how git input repository could be initialized in $GOPATH to run tests:

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: task-with-input
  namespace: default
spec:
  inputs:
    resources:
      - name: workspace
        type: git
        targetPath: go/src/github.com/tektoncd/pipeline
  steps:
    - name: unit-tests
      image: golang
      command: ["go"]
      args:
        - "test"
        - "./..."
      workingDir: "/workspace/go/src/github.com/tektoncd/pipeline"
      env:
        - name: GOPATH
          value: /workspace/go

Volumes

Specifies one or more volumes that you want to make available to your Task, including all the steps. Add volumes to complement the volumes that are implicitly created for input 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 build steps. Consider using a persistent volume for inter-build caching.
  • Mount Kubernetes configmap as 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 very unsafe. Use kaniko instead. This is used only for the purposes of demonstration.

Container Template

Specifies a Container configuration that will be used as the basis for all steps in your Task. Configuration in an individual step will override or merge with the container template's configuration.

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

containerTemplate:
  env:
    - name: "FOO"
      value: "bar"
steps:
  - image: ubuntu
    command: [echo]
    args: ["FOO is ${FOO}"]
  - image: ubuntu
    command: [echo]
    args: ["FOO is ${FOO}"]
    env:
      - name: "FOO"
        value: "baz"

Templating

Tasks support templating using values from all inputs and outputs.

PipelineResources can be referenced in a Task spec like this, where <name> is the Resource Name and <key> is a one of the resource's params:

${inputs.resources.<name>.<key>}

Or for an output resource:

${outputs.resources.<name>.<key>}

To access an input parameter, replace resources with params.

${inputs.params.<name>}

Templating Volumes

Task volume names and different types of volumes can be parameterized. Current support includes for widely used types of volumes like configmap, secret and PersistentVolumeClaim. Here is an example on how to use this in Task definitions.

Examples

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

Tip: See the collection of simple examples for additional code samples.

Example Task

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

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

spec:
  inputs:
    resources:
      - name: workspace
        type: git
    params:
      # These may be overridden, but provide sensible defaults.
      - name: directory
        description: The directory containing the build context.
        default: /workspace
      - name: dockerfileName
        description: The name of the Dockerfile
        default: Dockerfile
  outputs:
    resources:
      - name: builtImage
        type: image
  steps:
    - name: dockerfile-build
      image: gcr.io/cloud-builders/docker
      workingDir: "${inputs.params.directory}"
      args:
        [
          "build",
          "--no-cache",
          "--tag",
          "${outputs.resources.image}",
          "--file",
          "${inputs.params.dockerfileName}",
          ".",
        ]
      volumeMounts:
        - name: docker-socket
          mountPath: /var/run/docker.sock

    - name: dockerfile-push
      image: gcr.io/cloud-builders/docker
      args: ["push", "${outputs.resources.image}"]
      volumeMounts:
        - name: docker-socket
          mountPath: /var/run/docker.sock

  # As an implementation detail, this template mounts the host's daemon socket.
  volumes:
    - name: docker-socket
      hostPath:
        path: /var/run/docker.sock
        type: Socket

Using an extra volume

Mounting multiple volumes:

spec:
  steps:
    - image: ubuntu
      entrypoint: ["bash"]
      args: ["-c", "curl https://foo.com > /var/my-volume"]
      volumeMounts:
        - name: my-volume
          mountPath: /var/my-volume

    - image: ubuntu
      args: ["cat", "/etc/my-volume"]
      volumeMounts:
        - name: my-volume
          mountPath: /etc/my-volume

  volumes:
    - name: my-volume
      emptyDir: {}

Using Kubernetes Configmap as Volume Source

spec:
  inputs:
    params:
      - name: CFGNAME
        description: Name of config map
      - name: volumeName
        description: Name of volume
  steps:
    - image: ubuntu
      entrypoint: ["bash"]
      args: ["-c", "cat /var/configmap/test"]
      volumeMounts:
        - name: "${inputs.params.volumeName}"
          mountPath: /var/configmap

  volumes:
    - name: "${inputs.params.volumeName}"
      configMap:
        name: "${inputs.params.CFGNAME}"

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