Skip to content

Commit

Permalink
Document how PVC access modes affect pipeline execution
Browse files Browse the repository at this point in the history
The access mode configured for a PVC that is used as a workspace volume source
may affect how a pipeline is executed, this is not well documented. This commit
intend to improve the documentation about this and also provide an example
on how to run parallel tasks when using PVC with ReadWriteOnce access mode.

- Document how access mode affect task ordering in pipeline under "Specifying Workspace order in a Pipeline"
- Provide a full pipeline example of how to use parallel tasks when using a PVC with access mode ReadWriteOnce
- We we did provide a "PipelineRun example" under "Example PipelineRun definitions using Workspaces".
  This commit provide a full PipelineRun example using a workspace. Instead of providing examples of
  different volume sources here, examples on how to use different VolumeSources is moved to
  "Specifying VolumeSources in Workspaces"
- The VolumeSources persistentVolumeClaim and volumeClaimTemplate both is a PVC, and PVCs has its own
  peculiarities, e.g. access mode that we document. Both PVC volume sources is moved to a section
  so we can document the common peculiarities in a single place
- Add the workspace variable introduced in tektoncd#2506
  • Loading branch information
jlpettersson committed May 1, 2020
1 parent ab391e7 commit 2c17d70
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 52 deletions.
141 changes: 90 additions & 51 deletions docs/workspaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ weight: 5
- [Specifying `Workspaces` in `PipelineRuns`](#specifying-workspaces-in-pipelineruns)
- [Example `PipelineRun` definitions using `Workspaces`](#example-pipelinerun-definitions-using-workspaces)
- [Specifying `VolumeSources` in `Workspaces`](#specifying-volumesources-in-workspaces)
- [Using `PersistentVolumeClaims` as `VolumeSource`](#using-persistentvolumeclaims-as-volumesource)
- [Using other types of `VolumeSources`](#using-other-types-of-volumesources)
- [More examples](#more-examples)

## Overview
Expand Down Expand Up @@ -118,6 +120,8 @@ The following variables make information about `Workspaces` available to `Tasks`

- `$(workspaces.<name>.path)` - specifies the path to a `Workspace`
where `<name>` is the name of the `Workspace`.
- `$(workspaces.<name>.claim)` - specifies the name of the `PersistentVolumeClaim` used as a volume source for the `Workspace`
where `<name>` is the name of the `Workspace`. If the volume source other than `PersistentVolumeClaim` is used, an empty string is returned.
- `$(workspaces.<name>.volume)`- specifies the name of the `Volume`
provided for a `Workspace` where `<name>` is the name of the `Workspace`.

Expand Down Expand Up @@ -244,20 +248,28 @@ The `subPath` specified in a `Pipeline` will be appended to any `subPath` specif

Sharing a `Workspace` between `Tasks` requires you to define the order in which those `Tasks`
will be accessing that `Workspace` since different classes of storage have different limits
for concurrent reads and writes. For example, a `PersistentVolumeClaim` might only allow a
single `Task` writing to it at once.

**Warning:** You *must* ensure that this order is correct. Incorrectly ordering can result
in a deadlock where multiple `Task` `Pods` are attempting to mount a `PersistentVolumeClaim`
for writing at the same time, which would cause the `Tasks` to time out.

To define this order, use the `runAfter` field in your `Pipeline` definition. For more
for concurrent reads and writes. For example, a `PersistentVolumeClaim` with
[access mode](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes)
`ReadWriteOnce` only allow `Tasks` on a the same node writing to it at once.

Using parallel `Tasks` in a `Pipeline` will work with `PersistentVolumeClaims` configured with
[access mode](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes)
`ReadWriteMany` or `ReadOnlyMany` but you must ensure that those are available for your storage class.
When using `PersistentVolumeClaims` with access mode `ReadWriteOnce` for parallel `Tasks`, you can configure a
workspace with it's own `PersistentVolumeClaim` for each parallel `Task`. See a full example of a
[Pipeline with parallel tasks using PersistentVolumeClaims](../examples/v1beta1/pipelineruns/pipelinerun-with-parallel-tasks-using-pvc.yaml).

Use the `runAfter` field in your `Pipeline` definition to define when a `Task` should be executed. For more
information, see the [`runAfter` documentation](pipelines.md#runAfter).

**Warning:** You *must* ensure that this order is compatible with your configured access modes for your `PersistentVolumeClaim`.
Parallel `Tasks` using the same `PersistentVolumeClaim` with access mode `ReadWriteOnce`, may execute on
different nodes and be forced to execute sequentially which may cause `Tasks` to time out.

#### Specifying `Workspaces` in `PipelineRuns`

For a `PipelineRun` to execute a `Pipeline` that includes one or more `Workspaces`, it needs to
bind the `Workspace` names to physical volumes using its own `workspaces` field. Each entry in
bind the `Workspace` names to volumes using its own `workspaces` field. Each entry in
this list must correspond to a `Workspace` declaration in the `Pipeline`. Each entry in the
`workspaces` list must specify the following:

Expand All @@ -269,12 +281,52 @@ The entry must also include one `VolumeSource`. See [Using `VolumeSources` with

**Note:** If the `Workspaces` specified by a `Pipeline` are not provided at runtime by a `PipelineRun`, that `PipelineRun` will fail.

#### Example `PipelineRun` definitions using `Workspaces`
#### Example `PipelineRun` definition using `Workspaces`

In the example below, a `volumeClaimTemplate` is provided for how a `PersistentVolumeClaim` should be created for a workspace named
`myworkspace` declared in a `Pipeline`. When using `volumeClaimTemplate` a new `PersistentVolumeClaim` is created for
each `PipelineRun` and it allows the user to specify e.g. size and StorageClass for the volume.

```yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: pr-
spec:
pipelineRef:
name: example-pipeline
workspaces:
- name: myworkspace # this workspace name must be declared in the Pipeline
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce # access mode may affect how you can use this volume in parallel tasks
resources:
requests:
storage: 1Gi
```

For examples on how to use other types of volume sources, see [Specifying `VolumeSources` in `Workspaces`](#specifying-volumesources-in-workspaces).
For a more in-depth example, see the [`Workspaces` in `PipelineRun`](../examples/v1beta1/pipelineruns/workspaces.yaml) YAML sample.

### Specifying `VolumeSources` in `Workspaces`

You can only use a single type of `VolumeSource` per `Workspace` entry. The configuration
options differ for each type. `Workspaces` support the following fields:

#### Using `PersistentVolumeClaims` as `VolumeSource`

`PersistentVolumeClaim` volumes are a good choice for sharing data among `Tasks` within a `Pipeline`.
Beware that the [access mode](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes)
configured for the `PersinstentVolumeClaim` affect how you can use the volume for parallel `Tasks` in a `Pipeline`. See
[Specifying `workspace` order in a `Pipeline`](#specifying-workspace-order-in-a-pipeline) for more information about this.
There are two ways of using `PersistentVolumeClaims` as a `VolumeSource`.

The examples below illustrate how to specify `Workspaces` in your `PipelineRuns`. For a more in-depth example, see the
[`Workspaces` in `PipelineRun`](../examples/v1beta1/pipelineruns/workspaces.yaml) YAML sample.
##### `volumeClaimTemplate`

In the example below, a template is provided for how a `PersistentVolumeClaim` should be created for a workspace named `myworkspace` declared in a `Pipeline`. When using `volumeClaimTemplate` a new `PersistentVolumeClaim` is created for each `PipelineRun` and it allows the user to specify e.g. size and StorageClass for the volume.
The `volumeClaimTemplate` is a template of a [`PersistentVolumeClaim` volume](https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim),
created for each `PipelineRun` or `TaskRun`. When the volume is created from a template in a `PipelineRun` or `TaskRun`
it will be deleted when the `PipelineRun` or `TaskRun` is deleted.

```yaml
workspaces:
Expand All @@ -288,8 +340,9 @@ workspaces:
storage: 1Gi
```

In the example below, an existing `PersistentVolumeClaim` named `mypvc` is used for a `Workspace`
named `myworkspace` declared in a `Pipeline`. It exposes only the subdirectory `my-subdir` from that `PersistentVolumeClaim`:
##### `persistentVolumeClaim`

The `persistentVolumeClaim` field references an *existing* [`persistentVolumeClaim` volume](https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim). The example exposes only the subdirectory `my-subdir` from that `PersistentVolumeClaim`

```yaml
workspaces:
Expand All @@ -299,49 +352,21 @@ workspaces:
subPath: my-subdir
```

In the example below, a `ConfigMap` named `my-configmap` is used for a `Workspace`
named `myworkspace` declared in a `Pipeline`:
#### Using other types of `VolumeSources`

```yaml
workspaces:
- name: myworkspace
configmap:
name: my-configmap
```
##### `emptyDir`

In the example below, a `Secret` named `my-secret` is used for a `Workspace`
named `myworkspace` declared in a `Pipeline`:
The `emptyDir` field references an [`emptyDir` volume](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) which holds
a temporary directory that only lives as long as the `TaskRun` that invokes it. `emptyDir` volumes are **not** suitable for sharing data among `Tasks` within a `Pipeline`.
However, they work well for single `TaskRuns` where the data stored in the `emptyDir` needs to be shared among the `Steps` of the `Task` and discarded after execution.

```yaml
workspaces:
- name: myworkspace
secret:
secretName: my-secret
emptyDir: {}
```

### Specifying `VolumeSources` in `Workspaces`

You can only use a single type of `VolumeSource` per `Workspace` entry. The configuration
options differ for each type. `Workspaces` support the following fields:

#### `emptyDir`

The `emptyDir` field references an [`emptyDir` volume](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) which holds
a temporary directory that only lives as long as the `TaskRun` that invokes it. `emptyDir` volumes are **not** suitable for sharing data among `Tasks` within a `Pipeline`.
However, they work well for single `TaskRuns` where the data stored in the `emptyDir` needs to be shared among the `Steps` of the `Task` and discarded after execution.

#### `persistentVolumeClaim`

The `persistentVolumeClaim` field references an existing [`persistentVolumeClaim` volume](https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim).
`PersistentVolumeClaim` volumes are a good choice for sharing data among `Tasks` within a `Pipeline`.

#### `volumeClaimTemplate`

The `volumeClaimTemplate` is a template of a [`persistentVolumeClaim` volume](https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim), created for each `PipelineRun` or `TaskRun`.
When the volume is created from a template in a `PipelineRun` or `TaskRun` it will be deleted when the `PipelineRun` or `TaskRun` is deleted.
`volumeClaimTemplate` volumes are a good choice for sharing data among `Tasks` within a `Pipeline` when the volume is only used during a `PipelineRun` or `TaskRun`. See [`Workspaces` from a volumeClaimTemplate in a `PipelineRun`](../examples/v1beta1/pipelineruns/workspace-from-volumeclaimtemplate.yaml) for a complete example.

#### `configMap`
##### `configMap`

The `configMap` field references a [`configMap` volume](https://kubernetes.io/docs/concepts/storage/volumes/#configmap).
Using a `configMap` as a `Workspace` has the following limitations:
Expand All @@ -350,7 +375,14 @@ Using a `configMap` as a `Workspace` has the following limitations:
- The `configMap` you want to use as a `Workspace` must exist prior to submitting the `TaskRun`.
- `configMaps` are [size-limited to 1MB](https://github.com/kubernetes/kubernetes/blob/f16bfb069a22241a5501f6fe530f5d4e2a82cf0e/pkg/apis/core/validation/validation.go#L5042).

#### `secret`
```yaml
workspaces:
- name: myworkspace
configmap:
name: my-configmap
```

##### `secret`

The `secret` field references a [`secret` volume](https://kubernetes.io/docs/concepts/storage/volumes/#secret).
Using a `secret` volume has the following limitations:
Expand All @@ -359,6 +391,13 @@ Using a `secret` volume has the following limitations:
- The `secret` you want to use as a `Workspace` must exist prior to submitting the `TaskRun`.
- `secret` are [size-limited to 1MB](https://github.com/kubernetes/kubernetes/blob/f16bfb069a22241a5501f6fe530f5d4e2a82cf0e/pkg/apis/core/validation/validation.go#L5042).

```yaml
workspaces:
- name: myworkspace
secret:
secretName: my-secret
```

If you need support for a `VolumeSource` type not listed above, [open an issue](https://github.com/tektoncd/pipeline/issues) or
a [pull request](https://github.com/tektoncd/pipeline/blob/master/CONTRIBUTING.md).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ spec:
workspace: ws
subPath: dir-1
- name: writer-2
runAfter:
- writer-1
taskRef:
name: writer
workspaces:
Expand All @@ -54,7 +56,6 @@ spec:
subPath: dir-2
- name: read-all
runAfter:
- writer-1
- writer-2
params:
- name: directory1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: writer
spec:
steps:
- name: write
image: ubuntu
script: echo bar > $(workspaces.task-ws.path)/foo
workspaces:
- name: task-ws
---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: read-two
spec:
workspaces:
- name: ws-a
- name: ws-b
steps:
- name: read-1
image: ubuntu
script: cat $(workspaces.ws-a.path)/foo | grep bar
- name: read-2
image: ubuntu
script: cat $(workspaces.ws-b.path)/foo | grep bar
---
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: pipeline-using-parallel-tasks
spec:
workspaces:
- name: ws-track-a
- name: ws-track-b
tasks:
- name: parallel-writer-a
taskRef:
name: writer
workspaces:
- name: task-ws
workspace: ws-track-a
- name: parallel-writer-b
taskRef:
name: writer
workspaces:
- name: task-ws
workspace: ws-track-b
- name: read-all
runAfter:
- parallel-writer-a
- parallel-writer-b
taskRef:
name: read-two
workspaces:
- name: ws-a
workspace: ws-track-a
- name: ws-b
workspace: ws-track-b
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: pr-
spec:
pipelineRef:
name: pipeline-using-parallel-tasks
workspaces:
- name: ws-track-a
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
- name: ws-track-b
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

0 comments on commit 2c17d70

Please sign in to comment.