Target Data Persistent Volumes
May 18, 2026 ยท View on GitHub
The operator manages Persistent Volume Claims (PVCs) for target Pods that bind to existing PVs. AIStore storage PVs are created outside the scope of an AIS cluster and are not managed by the operator.
PVC Templating
The operator defines PVCs based on the AIStore custom resource spec, specifically spec.targetSpec.mounts.
The name for the PVC template is based on the configured mounts in the AIS spec. Each mount defines a separate path. The operator uses the configured mount paths to define a volume claim template for every mount. This template is used to generate PVCs for each Pod in the target StatefulSet. The name for the actual PVCs created for each Pod follows this pattern:
<cluster name><sanitized path>-<cluster name>-target-<target ordinal>
Paths are sanitized by replacing all / with -.
For example, the path /ais/nvme0n1 with a cluster named ais produces a PVC named ais-ais-nvme0n1-ais-target-0 for Pod ais-target-0.
For simple creation of static, local HostPath-type PVs, we provide the create-pv Helm chart.
PV Requirements
Existing PVs must have the following for AIStore PVCs to bind:
accessModesfield includesReadWriteOncestorageClassNamematches specmount.storageClass- This can be a simple string label with no defined storage class or provisioner, e.g.
"ais-local-storage".
- This can be a simple string label with no defined storage class or provisioner, e.g.
capacity.storagemust be at least themount.sizefrom spec- A pre-configured filesystem (XFS recommended)
- This may be created by the provisioner
To pin a PVC to a specific PV, set claimRef on the PV to match the expected PVC name and namespace (see naming convention above).
For local PVs, also set nodeAffinity so the Pod gets scheduled on the node that holds the disk.
mount.selector in the AIStore resource is propagated onto the PVC's spec.selector and only filters the candidate PVs by labels.
It can be used alongside claimRef but is not currently required.
The AIS Helm chart does not expose mount.selector.
Instead, each path gets its own label selector injected based on mount.path:
selector:
matchLabels:
mpath: pv-{{ .path | replace "/" "-" | trimPrefix "-" }}
End-to-End Example
The following examples use the provided create-pv Helm chart.
Sample PV
Below is a PV as created by the create-pv chart, where the K8s node name is the IP shown:
Name: 10.49.42.56-pv-ais-nvme0n1
Labels: cluster=ais
mpath=pv-ais-nvme0n1
target-index=16
type=local
Annotations: <none>
Finalizers: [kubernetes.io/pv-protection]
StorageClass: ais-local-storage
Status: Bound
Claim: ais/ais-ais-nvme0n1-ais-target-16
Reclaim Policy: Retain
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 6816972092211200m
Node Affinity:
Required Terms:
Term 0: kubernetes.io/hostname in [10.49.42.56]
Message:
Source:
Type: HostPath (bare host directory volume)
Path: /ais/nvme0n1
HostPathType:
Bound PVC:
Name: ais-ais-nvme0n1-ais-target-16
Namespace: ais
StorageClass: ais-local-storage
Status: Bound
Volume: 10.49.42.56-pv-ais-nvme0n1
Labels: app=ais
app.kubernetes.io/component=target
app.kubernetes.io/name=ais
component=target
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 6816972092211200m
Access Modes: RWO
VolumeMode: Filesystem
Used By: ais-target-16
AIS Helm Values
mpathInfo:
storageClass: "ais-local-storage"
size: 6.2Ti
mounts:
- path: /ais/nvme0n1
- path: /ais/nvme1n1
- path: /ais/nvme2n1
AIS Resource spec.targetSpec.mounts
The following shows the mounts as templated by Helm into the AIStore custom resource spec:
- path: /ais/nvme0n1
selector:
matchLabels:
mpath: pv-ais-nvme0n1
size: 6.2Ti
storageClass: ais-local-storage
- path: /ais/nvme1n1
selector:
matchLabels:
mpath: pv-ais-nvme1n1
size: 6.2Ti
storageClass: ais-local-storage
- path: /ais/nvme2n1
selector:
matchLabels:
mpath: pv-ais-nvme2n1
size: 6.2Ti
storageClass: ais-local-storage
HostPath Option
If a mount has the useHostPath field set to true, the operator will create a host path volume at <mount.path>/<namespace>/<cluster name>/target and map it directly into the Pod, bypassing PVs and PVCs entirely.
This can be used in deployments that wish to avoid PV management entirely and accept the security implications of host path mounts.