--- layout: docs page_title: volume block in the job specification description: >- Configure storage volumes in the `volume` block of a Nomad job specification. Specify dynamic host or Container Storage Interface (CSI) volume type, node access mode, filesystem or block device attachment mode, and mount options. Enable read only access and mounting a unique volume per node. Learn about volume interpolation. --- # `volume` block in the job specification The `volume` block allows the group to specify that it requires a given volume from the cluster. The key of the block is the name of the volume as it will be exposed to task configuration. ```hcl job "docs" { group "example" { volume "certs" { type = "host" source = "ca-certificates" read_only = true } } } ``` ```hcl job "docs" { group "example" { volume "data" { type = "csi" source = "csi-volume" read_only = true attachment_mode = "file-system" access_mode = "single-node-writer" per_alloc = true mount_options { fs_type = "ext4" mount_flags = ["noatime"] } } } } ``` The Nomad server ensures that the allocations are only scheduled on hosts that have a set of volumes that meet the criteria specified in the `volume` blocks. These may be [static host volumes][host_volume] configured on the client, [dynamic host volumes][] created via [`volume create`][] or [`volume register`][], or [CSI volumes][csi_volume] dynamically mounted by [CSI plugins][csi_plugin]. The Nomad client makes the volumes available to tasks according to the [volume_mount][volume_mount] block in the `task` configuration. ## Parameters - `type` `(string: "")` - Specifies the type of a given volume. The valid volume types are `"host"` and `"csi"`. Setting the `"host"` value can request either statically configured host volumes or dynamic host volumes, depending on what is available on a given node. - `source` `(string: )` - The name of the volume to request. When using `host_volume`'s this should match the published name of the host volume. When using `csi` volumes, this should match the ID of the registered volume. - `read_only` `(bool: false)` - Specifies that the group only requires read only access to a volume and is used as the default value for the `volume_mount -> read_only` configuration. This value is also used for validating `host_volume` ACLs and for scheduling when a matching `host_volume` requires `read_only` usage. - `sticky` `(bool: false)` - Specifies that this volume sticks to the allocation that uses it. Upon every reschedule and replacement, the task group always receives the volume with the same ID, if available. Use sticky volumes for [stateful deployments]. You may only use the `sticky` field for dynamic host volumes. For CSI volumes, the `per_alloc` field provides similar functionality - `per_alloc` `(bool: false)` - Specifies that the `source` of the volume should have the suffix `[n]`, where `n` is the allocation index. This allows mounting a unique volume per allocation, so long as the volume's source is named appropriately. For example, with the source `myvolume` and `per_alloc = true`, the allocation named `myjob.mygroup.mytask[0]` will require a volume ID `myvolume[0]`. The `per_alloc` field cannot be true for system jobs, sysbatch jobs, or jobs that use canaries. `per_alloc` is mutually exclusive with the `sticky` property. Use `per_alloc` only with CSI volumes and `sticky` only with dynamic host volumes. The following fields are only valid for volumes with `type = "csi"` or dynamic host volumes with `type = "host"`: - `access_mode` `(string)` - Defines whether a volume should be available concurrently. The `access_mode` and `attachment_mode` together must exactly match one of the volume's `capability` blocks. - For CSI volumes the `access_mode` is required. Can be one of the following: - `"single-node-reader-only"` - `"single-node-writer"` - `"multi-node-reader-only"` - `"multi-node-single-writer"` - `"multi-node-multi-writer"` Most CSI plugins support only single-node modes. Consult the documentation of the storage provider and CSI plugin. - For dynamic host volumes the `access_mode` is optional. Can be one of the following: - `"single-node-writer"` - `"single-node-reader-only"` - `"single-node-single-writer"` - `"single-node-multi-writer"` Defaults to `single-node-writer` unless `read_only = true`, in which case it defaults to `single-node-reader-only`. - `attachment_mode` `(string)` - The storage API used by the volume. One of `"file-system"` or `"block-device"`. The `access_mode` and `attachment_mode` together must exactly match one of the volume's `capability` blocks. - For CSI volumes the `attachment_mode` field is required. Most storage providers support `"file-system"`, to mount volumes using the CSI filesystem API. Some storage providers support `"block-device"`, which mounts the volume with the CSI block device API within the container. - For dynamic host volumes the `attachment_mode` field is optional and defaults to `"file-system"`. The following fields are only valid for volumes with `type = "csi"`: - `mount_options` - Options for mounting CSI volumes that have the `file-system` [attachment mode]. These options override the `mount_options` field from [volume registration]. Consult the documentation for your storage provider and CSI plugin as to whether these options are required or necessary. - `fs_type`: file system type (ex. `"ext4"`) - `mount_flags`: the flags passed to `mount` (ex. `["ro", "noatime"]`) ## Volume interpolation Because volumes represent state, many workloads with multiple allocations will want to mount specific volumes to specific tasks. The `volume` block is used to schedule workloads, so `${NOMAD_ALLOC_INDEX}` can't be used directly in the `volume.source` field. The following job specification demonstrates how to use multiple volumes with multiple allocations, using the `per_alloc` field. This job specification also shows using HCL2 -variables interpolation to expose information to the task's environment. ```hcl variables { path = "test" } job "example" { datacenters = ["dc1"] group "cache" { count = 2 volume "cache-volume" { type = "csi" source = "test-volume" attachment_mode = "file-system" access_mode = "single-node-writer" per_alloc = true } network { port "db" { to = 6379 } } task "redis" { driver = "docker" config { image = "redis:7" ports = ["db"] } resources { cpu = 500 memory = 256 } env { # this will be available as the MOUNT_PATH environment # variable in the task MOUNT_PATH = "${NOMAD_ALLOC_DIR}/${var.path}" } volume_mount { volume = "cache-volume" destination = "${NOMAD_ALLOC_DIR}/${var.path}" } } } } ``` The job that results from this job specification has two task groups, each one named for each of the two volumes. Each allocation has its own volume. ```shell-session $ nomad job status example ID = example ... Allocations ID Node ID Task Group Version Desired Status Created Modified 81d32909 352c6926 cache-1 0 run running 4s ago 3s ago ce6fbfc8 352c6926 cache-0 0 run running 4s ago 3s ago $ nomad volume status 'test-volume[0]' ... Allocations ID Node ID Task Group Version Desired Status Created Modified ce6fbfc8 352c6926 cache-0 0 run running 29s ago 18s ago $ nomad volume status 'test-volume[1]' ... Allocations ID Node ID Task Group Version Desired Status Created Modified 81d32909 352c6926 cache-0 0 run running 29s ago 18s ago ``` [volume_mount]: /nomad/docs/job-specification/volume_mount 'Nomad volume_mount Job Specification' [host_volume]: /nomad/docs/configuration/client#host_volume-block [csi_volume]: /nomad/docs/commands/volume/register [csi_plugin]: /nomad/docs/job-specification/csi_plugin [csi_volume]: /nomad/docs/commands/volume/register [attachment mode]: /nomad/docs/commands/volume/register#attachment_mode [volume registration]: /nomad/docs/commands/volume/register#mount_options [dynamic host volumes]: /nomad/docs/other-specifications/volume/host [stateful deployments]: /nomad/docs/concepts/stateful-deployments [`volume create`]: /nomad/docs/commands/volume/create [`volume register`]: /nomad/docs/commands/volume/register