Skip to main content
This guide walks you through creating and running your first Tekton Task and Pipeline. You’ll learn the fundamentals by building working examples.

Prerequisites

Before starting, make sure you have:
  • Tekton Pipelines installed on your cluster (installation guide)
  • kubectl configured to access your cluster
  • Basic familiarity with Kubernetes concepts

Understanding Tasks and TaskRuns

A Task defines a series of steps that execute in order. A TaskRun instantiates and executes a Task. Think of Tasks as templates and TaskRuns as instances.

Your First Task

Let’s create a simple Task that prints the current date in two formats.

Create the TaskRun

Create a file named print-date-taskrun.yaml:
print-date-taskrun.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  generateName: print-date-
spec:
  taskSpec:
    description: |
      A simple task that prints the date.
    results:
      - name: current-date-unix-timestamp
        description: The current date in unix timestamp format
      - name: current-date-human-readable
        description: The current date in human readable format
    steps:
      - name: print-date-unix-timestamp
        image: mirror.gcr.io/bash
        script: |
          #!/usr/bin/env bash
          date +%s | tee $(results.current-date-unix-timestamp.path)
      - name: print-date-human-readable
        image: mirror.gcr.io/bash
        script: |
          #!/usr/bin/env bash
          date | tee $(results.current-date-human-readable.path)
The generateName field creates a unique name with a random suffix (e.g., print-date-abc123). This is useful for creating multiple TaskRuns from the same definition.

Run the Task

Apply the TaskRun to your cluster:
kubectl create -f print-date-taskrun.yaml

View the Results

Check the TaskRun status:
kubectl get taskrun
You should see:
NAME                SUCCEEDED   REASON      STARTTIME   COMPLETIONTIME
print-date-abc123   True        Succeeded   30s         25s
View the detailed logs:
# Get the TaskRun name
TASKRUN_NAME=$(kubectl get taskrun -o jsonpath='{.items[0].metadata.name}')

# View logs from the first step
kubectl logs $TASKRUN_NAME --container=step-print-date-unix-timestamp

# View logs from the second step
kubectl logs $TASKRUN_NAME --container=step-print-date-human-readable
Each step in a Task runs in its own container. The steps execute sequentially in the order defined.

Adding Parameters

Let’s create a Task that accepts parameters for more flexibility. Create echo-message-task.yaml:
echo-message-task.yaml
apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: echo-message
spec:
  params:
  - name: MESSAGE
    type: string
    default: "Hello World"
  steps:
    - name: echo
      image: mirror.gcr.io/ubuntu
      command:
        - echo
      args:
        - "$(params.MESSAGE)"
Apply the Task:
kubectl apply -f echo-message-task.yaml
Now create a TaskRun that uses this Task with a custom parameter:
echo-taskrun.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  name: echo-hello-tekton
spec:
  taskRef:
    name: echo-message
  params:
    - name: MESSAGE
      value: "Hello from Tekton Pipelines!"
Run it:
kubectl create -f echo-taskrun.yaml
kubectl logs echo-hello-tekton --container=step-echo

Your First Pipeline

Pipelines chain multiple Tasks together. Let’s create a Pipeline that uses our echo-message Task twice.

Create the Pipeline

Create greeting-pipeline.yaml:
greeting-pipeline.yaml
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
  name: greeting-pipeline-run
spec:
  pipelineSpec:
    params:
      - name: MORNING_GREETINGS
        description: "morning greetings, default is Good Morning!"
        type: string
        default: "Good Morning!"
      - name: NIGHT_GREETINGS
        description: "Night greetings, default is Good Night!"
        type: string
        default: "Good Night!"
    tasks:
      # Task to display morning greetings
      - name: echo-good-morning
        taskRef:
          name: echo-message
        params:
          - name: MESSAGE
            value: $(params.MORNING_GREETINGS)
      # Task to display night greetings
      - name: echo-good-night
        taskRef:
          name: echo-message
        params:
          - name: MESSAGE
            value: $(params.NIGHT_GREETINGS)
  params:
    - name: MORNING_GREETINGS
      value: "Good Morning, Bob!"
    - name: NIGHT_GREETINGS
      value: "Good Night, Bob!"

Run the Pipeline

Apply the PipelineRun:
kubectl create -f greeting-pipeline.yaml

Monitor Pipeline Execution

Watch the PipelineRun status:
kubectl get pipelinerun greeting-pipeline-run
View detailed information:
kubectl describe pipelinerun greeting-pipeline-run
View logs from individual tasks:
# Morning greeting task
kubectl logs -l tekton.dev/pipelineTask=echo-good-morning --container=step-echo

# Night greeting task
kubectl logs -l tekton.dev/pipelineTask=echo-good-night --container=step-echo
By default, Pipeline tasks run in parallel unless you specify dependencies with runAfter. In this example, both greeting tasks run simultaneously.

Using Scripts in Steps

For more complex logic, use the script field instead of command and args:
script-example.yaml
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
  generateName: script-example-
spec:
  taskSpec:
    params:
    - name: PARAM
      default: param-value
    steps:
    - name: bash-script
      image: mirror.gcr.io/ubuntu
      env:
      - name: FOO
        value: "example value"
      script: |
        #!/usr/bin/env bash
        set -euxo pipefail
        echo "Hello from Bash!"
        echo "FOO is ${FOO}"
        echo "PARAM is $(params.PARAM)"
        for i in {1..5}; do
          echo "Line $i"
        done
Run it:
kubectl create -f script-example.yaml
Always include set -e in bash scripts to ensure the step fails if any command fails. Use set -euxo pipefail for better debugging output.

Key Concepts Recap

  • Task: A reusable template defining steps, parameters, and results
  • TaskRun: An execution instance of a Task with specific parameter values
  • Tasks can be embedded in TaskRuns (taskSpec) or referenced by name (taskRef)
  • Pipeline: A reusable workflow definition that orchestrates multiple Tasks
  • PipelineRun: An execution instance of a Pipeline
  • PipelineRuns can embed Pipeline specs or reference named Pipelines
  • Define inputs to Tasks and Pipelines with type checking
  • Support default values and descriptions
  • Reference parameters using $(params.PARAM_NAME) syntax
  • Types include: string, array, and object
  • Tasks can output results that other Tasks consume
  • Write results to $(results.RESULT_NAME.path)
  • Pipelines can pass results between Tasks and emit final results

Next Steps

Now that you’ve created your first Tasks and Pipeline, explore more advanced features:

Working with Workspaces

Share data between Tasks using Workspaces and persistent volumes

Task Results

Pass data between Tasks using results and parameters

Pipeline Dependencies

Control task execution order with runAfter and when expressions

Official Examples

Browse 100+ examples covering real-world CI/CD scenarios

Cleaning Up

Remove the resources created in this tutorial:
# Delete TaskRuns
kubectl delete taskrun --all

# Delete PipelineRuns
kubectl delete pipelinerun greeting-pipeline-run

# Delete the Task
kubectl delete task echo-message
TaskRuns and PipelineRuns are retained after completion so you can inspect logs and results. Clean them up periodically or configure automatic cleanup using Tekton’s retention policies.

Build docs developers (and LLMs) love