Annotations and Selection
When a workflow uses an
ephemeral volume
without naming a specific provisioner, Fuzzball
automatically selects a provisioner based on annotations and group access policies.
Specifying size on a volume (without use or name) triggers this automatic selection,
but the size value itself is not used as a selection criterion — provisioner selection
is determined solely by annotation matching and group permissions.
This page describes how annotations work and how the selection algorithm resolves which provisioner to use.
Provisioner annotations are string key-value pairs that describe characteristics of the
storage backend. Fuzzball treats annotation keys and values as opaque strings — the
platform does not assign special meaning to any particular key or value. You define
whatever annotations make sense for your organization (e.g., tier: fast,
region: us-west, purpose: archive). Workflow volumes can request specific annotations,
and Fuzzball will match them against provisioner annotations to find a compatible
provisioner.
Add annotations to a provisioner definition:
fast-storage:
description: "Fast NVMe-backed NFS"
driver:
type: nfs
target: "nfs-fast:/export/nvme"
annotations:
tier: fast
region: us-west
access: all
ephemeral: all
In a workflow definition, specify annotations: on a volume to request a provisioner with
matching annotations:
volumes:
scratch:
annotations:
tier: fast
Fuzzball will select a provisioner that has tier: fast in its annotations (among other
checks).
The matching logic follows these rules:
- Every annotation requested by the volume must exist on the provisioner with an exactly matching value
- Provisioners may have extra annotations — additional annotations on the provisioner that are not requested by the volume are ignored
- A volume with no annotations matches any provisioner — if the volume does not specify annotations, the annotation check is skipped
- Matching is exact — no wildcards, patterns, or partial matches. The key and value must be identical strings
| Volume annotations | Provisioner annotations | Match? | Reason |
|---|---|---|---|
tier: fast | tier: fast, region: us-west | Yes | All requested annotations present |
tier: fast | tier: slow | No | Value mismatch |
tier: fast | region: us-west | No | Key not found |
| (none) | tier: fast, region: us-west | Yes | No annotations requested |
tier: fast, region: us-west | tier: fast | No | Missing region key |
When Fuzzball needs to select a provisioner (for ephemeral volumes or when the workflow does not specify a provisioner by name), it applies the following checks to each provisioner in the organization:
- Status check — skip provisioners that are not in
Readystatus - Annotation match — skip provisioners that do not match the requested annotations
- Group permission check — skip provisioners where the user’s group does not have the required access for the operation type
The first provisioner that passes all three checks is selected.
If multiple provisioners match all criteria, the selection is non-deterministic — Fuzzball does not guarantee which one is chosen. Use annotations to distinguish provisioners when you need deterministic selection.
Fuzzball resolves volumes differently depending on what the workflow specifies:
When a workflow specifies use: my-provisioner, Fuzzball looks up the named provisioner
directly. No selection algorithm runs — the provisioner must exist and the user’s group
must have the required access.
volumes:
data:
use: my-nfs
name: project-data
When a workflow creates an ephemeral volume (no name:, with size: or
annotations:), Fuzzball runs the selection algorithm with ephemeral operation type:
volumes:
scratch:
size: 10GB
annotations:
tier: fast
The selected provisioner must grant ephemeral access to the user’s group.
When a workflow references a persistent volume by name, Fuzzball searches across all provisioners for a volume with that name:
volumes:
data:
name: my-dataset
If the volume exists on exactly one accessible provisioner, that provisioner is selected.
If the same volume name exists on multiple accessible provisioners, Fuzzball returns an
error asking the user to specify the provisioner with use:.
Annotations are most useful when you have multiple provisioners and need workflows to select the right one without hardcoding provisioner names.
work-storage:
driver:
type: nfs
target: "nfs-server:/export/work"
annotations:
purpose: work
ephemeral: all
archive-storage:
driver:
type: nfs
target: "nfs-server:/export/archive"
annotations:
purpose: archive
access: all
Workflows select by purpose:
volumes:
workspace:
size: 50GB
annotations:
purpose: work
results:
name: my-archive
annotations:
purpose: archive
fast-tier:
driver:
type: hostpath
path: /mnt/nvme
local: true
annotations:
tier: fast
ephemeral: all
standard-tier:
driver:
type: nfs
target: "nfs-server:/export/standard"
annotations:
tier: standard
access: all
ephemeral: all
In federated deployments, each cluster has its own set of provisioners. The selection algorithm runs independently on each participating cluster. This means different clusters can have provisioners with the same annotations but different backends:
Cluster A:
fast-storage: hostpath /mnt/nvme (annotations: tier=fast)
Cluster B:
fast-storage: efs fs-12345678 (annotations: tier=fast)
A workflow requesting tier: fast will match the appropriate provisioner on whichever
cluster it runs on, even though the underlying backends are different.