An emptyDir workspace in Tekton is a special type of workspace that provides ephemeral storage for tasks, meaning its contents are lost when the pod terminates.
Here’s a Tekton PipelineRun using an emptyDir workspace:
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: empty-dir-example-run
spec:
pipelineRef:
name: build-and-test
workspaces:
- name: shared-data
emptyDir: {} # This is where the emptyDir workspace is defined
And here’s a Pipeline that utilizes this workspace:
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: build-and-test
spec:
workspaces:
- name: shared-data
tasks:
- name: build
taskSpec:
workspaces:
- name: data
mountPath: /workspace/data # The pipeline's shared-data is mounted here
steps:
- name: echo-message
image: ubuntu
script: |
echo "Building artifact..."
echo "Hello from build task!" > /workspace/data/message.txt
echo "Build complete."
- name: test
runAfter:
- build
taskSpec:
workspaces:
- name: data
mountPath: /workspace/data # The pipeline's shared-data is mounted here too
steps:
- name: read-message
image: ubuntu
script: |
echo "Testing artifact..."
if [ -f /workspace/data/message.txt ]; then
MESSAGE=$(cat /workspace/data/message.txt)
echo "Read message: $MESSAGE"
if [ "$MESSAGE" == "Hello from build task!" ]; then
echo "Test successful!"
else
echo "Test failed: Unexpected message content."
exit 1
fi
else
echo "Test failed: message.txt not found!"
exit 1
fi
echo "Test complete."
In this example, the build task writes a file named message.txt into the shared-data workspace. The test task, which runs after build, can then read this same file from the shared-data workspace. This demonstrates how emptyDir workspaces facilitate data sharing between sequential tasks within a pipeline.
The core problem emptyDir workspaces solve is enabling transient, shared storage for tasks within a single pod. When Tekton runs a pipeline, it often consolidates multiple tasks into a single Kubernetes pod for efficiency. An emptyDir workspace acts as a volume mounted into this pod, accessible by all containers (tasks) running within it. This is crucial for passing intermediate build artifacts, configuration files, or any data generated by one task to be consumed by another without needing to persist it externally like a persistent volume. The emptyDir volume is initialized as empty when the pod is created and its life cycle is tied directly to the pod’s life cycle. Once the pod is terminated (e.g., after the PipelineRun completes or fails), the contents of the emptyDir volume are deleted.
The emptyDir volume is backed by the node’s storage, typically tmpfs (RAM-backed filesystem) by default, unless a specific medium is defined. This makes it very fast but also means it’s volatile and its size is limited by the node’s available memory or disk space. You can explicitly set the medium to Memory or HugePages if you want to ensure it uses RAM, or rely on the default behavior. The sizeLimit field can be used to cap the storage consumption, preventing a runaway task from exhausting node resources. For instance, emptyDir: { sizeLimit: "1Gi" } would limit the workspace to 1 gigabyte.
A common misconception is that emptyDir workspaces are slow because they are just "temporary." While they are ephemeral, their performance can be excellent, especially when backed by tmpfs. The key advantage is the low latency of accessing data directly within the pod, avoiding network overhead associated with external storage solutions. This makes them ideal for build steps that generate many small intermediate files or for sharing configuration during the execution of a single pipeline run. The mountPath in the taskSpec is where the workspace is made available to the task’s steps. In our example, /workspace/data is the chosen mount path, and both the build and test tasks mount the shared-data workspace to this exact path, ensuring they are looking in the same place for shared files.
The next concept to explore is how to manage workspace persistence for longer-lived data or when tasks run in separate pods.