<p>When using <a href="https://github.com/helm/charts/tree/master/stable/nfs-server-provisioner" rel="nofollow noreferrer">nfs-server-provisioner</a> is it possible to set a specific persistent volume for the NFS provisioner?</p>
<p>At present, I'm setting the Storage Class to use via helm:</p>
<pre><code>helm install stable/nfs-server-provisioner \
--namespace &lt;chart-name&gt;-helm \
--name &lt;chart-name&gt;-nfs \
--set persistence.enabled=true \
--set persistence.storageClass=slow \
--set persistence.size=25Gi \
--set storageClass.name=&lt;chart-name&gt;-nfs \
--set storageClass.reclaimPolicy=Retain
</code></pre>
<p>and the Storage Class is built via:</p>
<pre><code>apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
reclaimPolicy: Retain
allowVolumeExpansion: true
parameters:
  type: pd-standard
  replication-type: none
</code></pre>
<p>This then generates the PV dynamically when requested by a PVC.</p>
<p>I'm using the PV to store files for a Stateful CMS, using NFS allows for multiple pods to connect to the same file store.</p>
<p>What I'd like to do now is move all those images to a new set of pods on a new cluster. Rather than backing them up and going through the process of dynamically generating a PV and restoring the files to it, is it possible to retain the current PV and then connect the new PVC to it?</p>

<blockquote>
<p>When using nfs-server-provisioner is it possible to set a specific persistent volume for the NFS provisioner?</p>
</blockquote>
<p>If we are talking if it's possible to retain the data from existing old PV which was the storage for the old NFS server and then use it with new NFS server, the answer is yes.</p>
<p>I've managed to find a way to do it. Please remember that this is only a <strong>workaround</strong>.</p>
<p>Steps:</p>
<ul>
<li>Create a snapshot out of existing old nfs server storage.</li>
<li>Create a new disk where the source is previously created snapshot</li>
<li>Create a PV and PVC for newly created nfs-server</li>
<li>Pull the nfs-server-provisioner helm chart and edit it</li>
<li>Spawn edited nfs-server-provisioner helm chart</li>
<li>Create new PV's and PVC's with nfs-server-provisioner storageClass</li>
<li>Attach newly created PVC's to workload</li>
</ul>
<p>Please remember that this solution is showing the way to create PV's and PVC's for a new workload manually.</p>
<p>I've included the whole process below.</p>
<hr />
<h3>Create a snapshot out of existing old nfs server storage.</h3>
<p>Assuming that you created your old <code>nfs-server</code> with the <code>gce-pd</code>, you can access this disk via GCP Cloud Console to make a snapshot of it.</p>
<p>I've included here more safer approach which consists of creating a copy of the <code>gce-pd</code> with data inside of old nfs-server. This copy will be used in new <code>nfs-server</code>.</p>
<p>There is also a possibility to change the <code>persistentVolumeReclaimPolicy</code> on existing old PV to not be deleted when the <code>PVC</code> of old nfs-server is deleted. In this way, you could reuse existing disk in new nfs-server.</p>
<p>Please refer to official documentation how to create a snapshot out of persistent disks in GCP:</p>
<ul>
<li><em><a href="https://cloud.google.com/compute/docs/disks/create-snapshots" rel="nofollow noreferrer">Cloud.google.com: Compute: Disks: Create snapshot</a></em></li>
</ul>
<hr />
<h3>Create a new disk where the source is previously created snapshot</h3>
<p>You will need to create a new <code>gce-pd</code> disk for your new <code>nfs-server</code>. The earlier created snapshot will be the source for your new disk.</p>
<p>Please refer to official documentation on how to create a new disk from existing snapshot:</p>
<ul>
<li><em><a href="https://cloud.google.com/compute/docs/disks/restore-and-delete-snapshots#console" rel="nofollow noreferrer">Cloud.google.com: Compute: Disks: Restore and delete snapshots</a></em></li>
</ul>
<hr />
<h3>Create a PV and PVC for newly created nfs-server</h3>
<p>To ensure that the <code>GCP</code>'s disk will be bound to the newly created nfs-server you will need to create a PV and a PVC. You can use example below but please change it accordingly to your use case:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: PersistentVolume
metadata:
  name: data-disk
spec:
  storageClassName: standard
  capacity:
    storage: 25G
  accessModes:
    - ReadWriteOnce
  claimRef:
    namespace: default
    name: data-disk-pvc # reference to the PVC below
  gcePersistentDisk:
    pdName: old-data-disk # name of the disk created from snapshot in GCP
    fsType: ext4 
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-disk-pvc # reference to the PV above
spec:
  storageClassName: standard
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 25G
</code></pre>
<p>The way that this nfs-server works is that it creates a disk in the <code>GCP</code> infrastructure to store all the data saved on the nfs-server. Further creation of <code>PV</code>'s and <code>PVC</code>'s with nfs <code>storageClass</code> will result in creation of a folder in the <code>/export</code> directory inside of a nfs-server pod.</p>
<hr />
<h3>Pull the nfs-server-provisioner helm chart and edit it</h3>
<p>You will need to pull the Helm chart of the <code>nfs-server-provisioner</code> as it requires a reconfiguration. You can do it by invoking below command:</p>
<ul>
<li><code>$ helm pull --untar stable/nfs-server-provisioner</code></li>
</ul>
<p>The changes are following in the <code>templates/statefulset.yaml</code> file:</p>
<ul>
<li><strong>Delete</strong> the parts responsible for handling persistence <code>.Values.persistence.enabled</code> (on the bottom). This parts are responsible for creating storage which you already have.</li>
</ul>
<pre class="lang-yaml prettyprint-override"><code>      {{- if not .Values.persistence.enabled }}
      volumes:
        - name: data
          emptyDir: {}
      {{- end }}

  {{- if .Values.persistence.enabled }}
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ {{ .Values.persistence.accessMode | quote }} ]
        {{- if .Values.persistence.storageClass }}
        {{- if (eq &quot;-&quot; .Values.persistence.storageClass) }}
        storageClassName: &quot;&quot;
        {{- else }}
        storageClassName: {{ .Values.persistence.storageClass | quote }}
        {{- end }}
        {{- end }}
        resources:
          requests:
            storage: {{ .Values.persistence.size | quote }}
  {{- end }}

</code></pre>
<ul>
<li>Add the volume definition to use previously created disk with the nfs data to the <code>spec.template.spec</code> part like here: <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#create-a-pod" rel="nofollow noreferrer">Kubernetes.io: Configure persistent volume storage: Create a pod</a></li>
</ul>
<pre class="lang-yaml prettyprint-override"><code>      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: data-disk-pvc # name of the pvc created from the disk
</code></pre>
<hr />
<h3>Spawn edited nfs-server-provisioner helm chart</h3>
<p>You will need to run this Helm chart from local storage instead of running it from the web. The command to run it will be following:</p>
<ul>
<li><code>$ helm install kruk-nfs . --set storageClass.name=kruk-nfs --set storageClass.reclaimPolicy=Retain</code></li>
</ul>
<blockquote>
<p>This syntax is specific to Helm3</p>
</blockquote>
<p>Above parameters are necessary to specify the name of the <code>storageClass</code> as well it's <code>reclaimPolicy</code>.</p>
<hr />
<h3>Create new PV's and PVC's with nfs-server-provisioner storageClass</h3>
<p>Example to create a PVC linked to the existing folder in nfs-server.</p>
<p>Assuming that the <code>/export</code> directory looks like this:</p>
<pre class="lang-sh prettyprint-override"><code>bash-5.0# ls                 
ganesha.log
lost+found  
nfs-provisioner.identity  
pvc-2c16cccb-da67-41da-9986-a15f3f9e68cf # folder we will create a PV and PVC for
v4old  
v4recov  
vfs.conf
</code></pre>
<blockquote>
<p>A tip!
When you create a <code>PVC</code> with a <code>storageClass</code> of this nfs-server it will create a folder with the name of this <code>PVC</code>.</p>
</blockquote>
<p>You will need to create a <code>PV</code> for your share:</p>
<pre class="lang-sh prettyprint-override"><code>apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-example
spec:
  storageClassName: kruk-nfs
  capacity:
    storage: 100Mi
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  nfs:
    path: /export/pvc-2c16cccb-da67-41da-9986-a15f3f9e68cf # directory to mount pv
    server: 10.73.4.71  # clusterIP of nfs-server-pod service
</code></pre>
<p>And <code>PVC</code> for your <code>PV</code>:</p>
<pre class="lang-sh prettyprint-override"><code>apiVersion: &quot;v1&quot;
kind: &quot;PersistentVolumeClaim&quot;
metadata:
  name: pv-example-claim
spec:
  storageClassName: kruk-nfs
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
  volumeName: pv-example # name of the PV created for a folder
</code></pre>
<h3>Attach newly created PVC's to workload</h3>
<p>Above manifests will create a <code>PVC</code> with the name of pv-example-claim that will have the contents of the <code>pvc-2c16cccb-da67-41da-9986-a15f3f9e68cf</code> directory available for usage. You can mount this <code>PVC</code> to a pod by following this example:</p>
<pre class="lang-yaml prettyprint-override"><code>piVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: storage-mounting
      persistentVolumeClaim:
        claimName: pv-example-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: &quot;http-server&quot;
      volumeMounts:
        - mountPath: &quot;/storage&quot;
          name: storage-mounting
</code></pre>
<p>After that you should be able to check if you have the data in the folder specified in above manifest:</p>
<pre class="lang-sh prettyprint-override"><code>$ kubectl exec -it task-pv-pod -- cat /storage/hello                                                                      
hello there
</code></pre>
