From 2c17d701b2014e8cfa5ce57e8648fcde5f466c7f Mon Sep 17 00:00:00 2001 From: Jonas Pettersson Date: Fri, 1 May 2020 10:11:32 +0200 Subject: [PATCH] Document how PVC access modes affect pipeline execution 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 #2506 --- docs/workspaces.md | 141 +++++++++++------- ...using-different-subpaths-of-workspace.yaml | 3 +- ...linerun-with-parallel-tasks-using-pvc.yaml | 85 +++++++++++ 3 files changed, 177 insertions(+), 52 deletions(-) create mode 100644 examples/v1beta1/pipelineruns/pipelinerun-with-parallel-tasks-using-pvc.yaml diff --git a/docs/workspaces.md b/docs/workspaces.md index 3a5edddd020..99e6fd4efaf 100644 --- a/docs/workspaces.md +++ b/docs/workspaces.md @@ -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 @@ -118,6 +120,8 @@ The following variables make information about `Workspaces` available to `Tasks` - `$(workspaces..path)` - specifies the path to a `Workspace` where `` is the name of the `Workspace`. +- `$(workspaces..claim)` - specifies the name of the `PersistentVolumeClaim` used as a volume source for the `Workspace` + where `` is the name of the `Workspace`. If the volume source other than `PersistentVolumeClaim` is used, an empty string is returned. - `$(workspaces..volume)`- specifies the name of the `Volume` provided for a `Workspace` where `` is the name of the `Workspace`. @@ -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: @@ -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: @@ -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: @@ -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: @@ -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: @@ -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). diff --git a/examples/v1beta1/pipelineruns/pipelinerun-using-different-subpaths-of-workspace.yaml b/examples/v1beta1/pipelineruns/pipelinerun-using-different-subpaths-of-workspace.yaml index 4fd1058615b..d96ac0e2671 100644 --- a/examples/v1beta1/pipelineruns/pipelinerun-using-different-subpaths-of-workspace.yaml +++ b/examples/v1beta1/pipelineruns/pipelinerun-using-different-subpaths-of-workspace.yaml @@ -46,6 +46,8 @@ spec: workspace: ws subPath: dir-1 - name: writer-2 + runAfter: + - writer-1 taskRef: name: writer workspaces: @@ -54,7 +56,6 @@ spec: subPath: dir-2 - name: read-all runAfter: - - writer-1 - writer-2 params: - name: directory1 diff --git a/examples/v1beta1/pipelineruns/pipelinerun-with-parallel-tasks-using-pvc.yaml b/examples/v1beta1/pipelineruns/pipelinerun-with-parallel-tasks-using-pvc.yaml new file mode 100644 index 00000000000..5446ac4ebc7 --- /dev/null +++ b/examples/v1beta1/pipelineruns/pipelinerun-with-parallel-tasks-using-pvc.yaml @@ -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