---
title: Configuring local storage by using the hostpath provisioner
---

# Configuring local storage by using the hostpath provisioner {#virt-configuring-local-storage-with-hpp}

You can configure local storage for virtual machines by using the hostpath provisioner (HPP).

When you install the OpenShift Virtualization Operator, the Hostpath Provisioner Operator is automatically installed. HPP is a local storage provisioner designed for OpenShift Virtualization that is created by the Hostpath Provisioner Operator. To use HPP, you create an HPP custom resource (CR) with a basic storage pool.

## Creating a hostpath provisioner with a basic storage pool {#virt-creating-hpp-basic-storage-pool_virt-configuring-local-storage-with-hpp}

You configure a hostpath provisioner (HPP) with a basic storage pool by creating an HPP custom resource (CR) with a `storagePools` stanza. The storage pool specifies the name and path used by the CSI driver.

> [!IMPORTANT]
> Do not create storage pools in the same partition as the operating system. Otherwise, the operating system partition might become filled to capacity, which will impact performance or cause the node to become unstable or unusable.

**Prerequisites**

- The directories specified in `spec.storagePools.path` must have read/write access.
- You have installed the OpenShift CLI (`oc`).

**Procedure**

1. Create an `hpp_cr.yaml` file with a `storagePools` stanza as in the following example:

   ```yaml
   apiVersion: hostpathprovisioner.kubevirt.io/v1beta1
   kind: HostPathProvisioner
   metadata:
     name: hostpath-provisioner
   spec:
     imagePullPolicy: IfNotPresent
     storagePools:
     - name: any_name
       path: "/var/myvolumes"
     workload:
       nodeSelector:
         kubernetes.io/os: linux
   ```

   - `spec.storagePools.name` defines the name to identify the source to use. It must be the same as the `storagePools` name in the `StorageClass.yaml`.
   - `spec.storagePools.path` defines the storage pool directories under this node path. Ensure that the path `/var/myvolumes` value specifies a directory that exists on each worker node.
2. Save the file and exit.
3. Create the HPP by running the following command:

   ```terminal
   $ oc create -f hpp_cr.yaml
   ```

### About creating storage classes {#virt-about-creating-storage-classes_virt-configuring-local-storage-with-hpp}

When you create a storage class, you set parameters that affect the dynamic provisioning of persistent volumes (PVs) that belong to that storage class. You cannot update a `StorageClass` object’s parameters after you create it.

To use the hostpath provisioner (HPP) you must create an associated storage class for the CSI driver with the `storagePools` stanza.

> [!NOTE]
> Virtual machines use data volumes that are based on local PVs. Local PVs are bound to specific nodes. While the disk image is prepared for consumption by the virtual machine, it is possible that the virtual machine cannot be scheduled to the node where the local storage PV was previously pinned.
>
> To solve this problem, use the Kubernetes pod scheduler to bind the persistent volume claim (PVC) to a PV on the correct node. By using the `StorageClass` value with `volumeBindingMode` parameter set to `WaitForFirstConsumer`, the binding and provisioning of the PV is delayed until a pod is created using the PVC.

### Creating a storage class for the CSI driver with the storagePools stanza {#virt-creating-storage-class-csi-driver_virt-configuring-local-storage-with-hpp}

To use the hostpath provisioner (HPP) you must create an associated storage class for the Container Storage Interface (CSI) driver.

When you create a storage class, you set parameters that affect the dynamic provisioning of persistent volumes (PVs) that belong to that storage class. You cannot update a `StorageClass` object’s parameters after you create it.

**Procedure**

1. Create a `storageclass_csi.yaml` file to define the storage class:

   ```yaml
   apiVersion: storage.k8s.io/v1
   kind: StorageClass
   metadata:
     name: hostpath-csi
   provisioner: kubevirt.io.hostpath-provisioner
   reclaimPolicy: Delete
   volumeBindingMode: WaitForFirstConsumer
   parameters:
     storagePool: my-storage-pool
   ```

   - `reclaimPolicy` defines whether the underlying storage is deleted or retained when a user deletes a PVC. The two possible `reclaimPolicy` values are `Delete` and `Retain`. If you do not specify a value, the default value is `Delete`.
   - `volumeBindingMode` defines the timing of PV creation. In this example, the `WaitForFirstConsumer` configuration delays PV creation until the scheduler assigns a pod to a specific node.

     > [!NOTE]
     > Virtual machines use data volumes based on local PVs, which reside on specific nodes. When the system prepares a disk image for the virtual machine, the scheduler might not place the virtual machine on the node where it pinned the local storage PV. + To solve this problem, use the Kubernetes pod scheduler to bind the persistent volume claim (PVC) to a PV on the correct node. Setting the `volumeBindingMode` parameter of the `StorageClass` to `WaitForFirstConsumer` delays PV binding and provisioning until you create a pod that uses the PVC.
   - `parameters.storagePool` defines the name of the storage pool defined in the HPP custom resource (CR).
2. Save the file and exit.
3. Create the `StorageClass` object by running the following command:

   ```terminal
   $ oc create -f storageclass_csi.yaml
   ```

## About storage pools created with PVC templates {#virt-about-storage-pools-pvc-templates_virt-configuring-local-storage-with-hpp}

If you have a single, large persistent volume (PV), you can create a storage pool by defining a PVC template in the hostpath provisioner (HPP) custom resource (CR).

A storage pool created with a PVC template can contain multiple HPP volumes. Splitting a PV into smaller volumes provides greater flexibility for data allocation.

The PVC template is based on the `spec` stanza of the `PersistentVolumeClaim` object:

```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: iso-pvc
spec:
  volumeMode: Block
  storageClassName: my-storage-class
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
```

The `spec.volumeMode` value is only required for block volume mode PVs.

You define a storage pool by using a `pvcTemplate` specification in the HPP CR. The Operator creates a PVC from the `pvcTemplate` specification for each node containing the HPP CSI driver. The PVC created from the PVC template consumes the single large PV, allowing the HPP to create smaller dynamic volumes.

You can combine basic storage pools with storage pools created from PVC templates.

### Creating a storage pool with a PVC template {#virt-creating-storage-pool-pvc-template_virt-configuring-local-storage-with-hpp}

You can create a storage pool for multiple hostpath provisioner (HPP) volumes by specifying a persistent volume claim (PVC) template in the HPP custom resource (CR).

> [!IMPORTANT]
> Do not create storage pools in the same partition as the operating system. Otherwise, the operating system partition might become filled to capacity, which will impact performance or cause the node to become unstable or unusable.

**Prerequisites**

- The directories specified in `spec.storagePools.path` must have read/write access.
- You have installed the OpenShift CLI (`oc`).

**Procedure**

1. Create an `hpp_pvc_template_pool.yaml` file for the HPP CR that specifies a PVC template in the `storagePools` stanza according to the following example:

   ```yaml
   apiVersion: hostpathprovisioner.kubevirt.io/v1beta1
   kind: HostPathProvisioner
   metadata:
     name: hostpath-provisioner
   spec:
     imagePullPolicy: IfNotPresent
     storagePools:
     - name: my-storage-pool
       path: "/var/myvolumes"
       pvcTemplate:
         volumeMode: Block
         storageClassName: my-storage-class
         accessModes:
         - ReadWriteOnce
         resources:
           requests:
             storage: 5Gi
     workload:
       nodeSelector:
         kubernetes.io/os: linux
   ```

   - `spec.storagePools` defines an array that can contain both basic and PVC template storage pools.
   - `spec.storagePools.path` defines the storage pool directories under this node path.
   - `spec.storagePools.pvcTemplate.volumeMode` is an optional parameter, which can be either `Block` or `Filesystem` if it matches the provisioned volume format. If no value is specified, the default is `Filesystem`. If the `volumeMode` is `Block`, the mounting pod creates an XFS file system on the block volume before mounting it.
   - `spec.storagePools.pvcTemplate.storageClassName` specifies if the `storageClassName` parameter is omitted, the default storage class is used to create PVCs. If you omit `storageClassName`, ensure that the HPP storage class is not the default storage class.
   - `spec.storagePools.pvcTemplate.resources.requests.storage` defines the storage request for statically or dynamically provisioned storage. Ensure the requested storage size is appropriate for the volume you want to virtually divide or the PVC cannot be bound to the large PV. If the storage class uses dynamically provisioned storage, pick an allocation size that matches the size of a typical request.
2. Save the file and exit.
3. Create the HPP with a storage pool by running the following command:

   ```terminal
   $ oc create -f hpp_pvc_template_pool.yaml
   ```
