<p>I have created a persistent volume:</p>
<pre><code>apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: &quot;C:/Users/xxx/Desktop/pv&quot;
</code></pre>
<p>And want to make save mysql statefulset pods things on it.
So, I wrote the volumeclaimtemplate:</p>
<pre><code>  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [&quot;ReadWriteOnce&quot;]
      resources:
        requests:
          storage: 1Gi
</code></pre>
<p>Thinking this would request the persistent storage from the only persistent volume I have. Instead, this is what happens:
<a href="https://i.stack.imgur.com/D5dCR.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/D5dCR.png" alt="persistent volumes" /></a></p>

<p>StatefulSets requires you to use storage classes in order to bind the correct PVs with the correct PVCs.</p>
<p>The correct way to make StatefulSets mount local storage is by using local type of volumes, take a look at the procedure below.</p>
<hr />
<p><strong>First</strong>, you create a storage class for the local volumes. Something like the following:</p>
<pre><code>apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
</code></pre>
<p>It has <strong>no-provisioner</strong> so it will not be able to automatically provision PVs, you'll need to create them manually, but that's exactly what you want for local storage.</p>
<p><strong>Second</strong>, you create your local PV, something as the following:</p>
<pre><code>apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-volume
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: &quot;C:/Users/xxx/Desktop/pv&quot;
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - the-node-hostname-on-which-the-storage-is-located
</code></pre>
<p>This definition tells the local path on the node, but also forces the PV to be used on a specific node (which match the <code>nodeSelectorTerms</code>).</p>
<p>It also <code>links</code> this PV to the storage class created earlier. This means that now, if a StatefulSets requires a storage with that storage class, it will receive this disk (if the space required is less or equal, of course)</p>
<p><strong>Third</strong>, you can now link the StatefulSet:</p>
<pre><code>volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ &quot;ReadWriteOnce&quot; ]
      storageClassName: &quot;local-storage&quot;
      resources:
        requests:
          storage: 5Gi
</code></pre>
<hr />
<p>When the StatefulSet Pod will need to be scheduled for the first time, the following will happen:</p>
<ul>
<li>A PVC will be created and it will go Bound with the PV you just created</li>
<li>The Pod will be scheduled to run on the node on which the bounded PV is restricted to run</li>
</ul>
<hr />
<p><strong>UPDATE</strong>:</p>
<p>In case you want to use <code>hostPath</code> storage instead of local storage (because for example you are on <code>minikube</code> and that is supported out of the box directly, so it's more easy) you need to change the PV declaration a bit, something like the following:</p>
<pre><code>apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-volume
spec:
  storageClassName: local-storage
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 5Gi
  hostPath:
    path: /data/pv0001/
</code></pre>
<p>Now, the <code>/data</code> directory and all its content is persisted on the host (so if minikube gets restarted, it's still there) but if you want to mount specific directories of your host, you need to use minikube mount, for example:</p>
<pre><code>minikube mount &lt;source directory&gt;:&lt;target directory&gt;
</code></pre>
<p>For example, you could do:</p>
<p>minikube mount C:/Users/xxx/Desktop/pv:/host/my-special-pv</p>
<p>and then you could use <code>/host/my-special-pv</code> as the <code>hostPath</code> inside the PV declaration.</p>
<p>More info can be read in the <a href="https://minikube.sigs.k8s.io/docs/handbook/mount/" rel="nofollow noreferrer">docs</a>.</p>
