<p>We re-organise our namespaces in Kubernetes. We want to move our Persistent volume Claims created by a storageclass from one namespace to another.</p>
<p>(Our backup tool don't help).</p>

<h2>Option 1: use a backup tool</h2>
<p>The easiest and safest option to migrate a pvc/pv to a new namespace is to use a backup tool (like <a href="https://velero.io/docs/v1.5/restore-reference/#restoring-into-a-different-namespace" rel="nofollow noreferrer">velero</a>)</p>
<h2>Option 2: no backup tool (by hand)</h2>
<p>This is undocumented.</p>
<p>In this exemple, we use VMware storage provider, but it should work with any storageClass.</p>
<h2>Prepare</h2>
<p>Make a * <strong>Backup</strong> * <strong>Backup</strong> * <strong>Backup</strong> * <strong>Backup</strong> * <strong>Backup</strong> * !!!</p>
<p>well, if you do have a backup tool for kubernetes (like <a href="https://velero.io/docs/v1.5/restore-reference/#restoring-into-a-different-namespace" rel="nofollow noreferrer">velero</a>) you can restore directly in the target namespace, otherwise use <code>kubectl cp</code> as explained in <a href="https://stackoverflow.com/q/52407277/1260896">How to copy files from kubernetes Pods to local system</a></p>
<p>Let's set some environment variable and backup the existing PV and PVC ressources</p>
<pre><code>NAMESPACE1=XXX
NAMESPACE2=XXX
PVC=mypvc

kubectl get pvc -n $NAMESPACE1 $PVC -o yaml | tee /tmp/pvc.yaml

PV=pvc-XXXXXXXXXXXXX-XXXXXXXXXXXX

kubectl get pv  $PV -o yaml | tee /tmp/pv.yaml
</code></pre>
<h1>Change ReclaimPolicy for PV</h1>
<p>If your persistent volume (or storage provider) has persistentVolumeReclaimPolicy=Delete, make sure to change it to &quot;Retain&quot; to avoid data loss when removing the PVC below.</p>
<p>Run this:</p>
<pre><code>kubectl patch pv &quot;$PV&quot; -p '{&quot;spec&quot;:{&quot;persistentVolumeReclaimPolicy&quot;:&quot;Retain&quot;}}'
</code></pre>
<p>Then check:</p>
<pre><code>kubectl describe pv &quot;$PV&quot; | grep -e Reclaim
</code></pre>
<h2>Remove the PVC</h2>
<p>Manually delete the Persistent volume claim (you have a copy, right?).</p>
<pre><code>kubectl delete -n &quot;$NAMESPACE1&quot; &quot;$PVC&quot;
</code></pre>
<h2>Modify the Persistent Volume (PV)</h2>
<p>A PV is attached to a namespace when it's first used by a PVC. Furthermore, the PV become &quot;attached&quot; to the PVC (by it's <code>uid:</code>, not by it's name).</p>
<p>Change the namespace of the PV. Temporarily use PVC &quot;name&quot; to &quot;lock&quot; the PV for that PVC (rather than PVC uid).</p>
<pre><code>&quot;kubectl patch pv &quot;$PV&quot; -p '{&quot;spec&quot;:{&quot;claimRef&quot;:{&quot;namespace&quot;:&quot;'$NAMESPACE2'&quot;,&quot;name&quot;:&quot;'$PVC'&quot;,&quot;uid&quot;:null}}}'
</code></pre>
<p>Check what we have now:</p>
<pre><code>kubectl get pv &quot;$PV&quot; -o yaml | grep -e Reclaim -e namespace -e uid: -e name: -e claimRef | grep -v &quot; f:&quot;
</code></pre>
<h2>Create the new PVC</h2>
<p>Create a PVC in the new namespace. Make sure to explicitly choose the PV to use (don't use StorageClass to provision the volume). Typically, you can copy the original PVC YAML, but drop <code>namespace:</code>, <code>selfLink:</code>, <code>uid:</code> in the section <code>metadata:</code>.</p>
<p>This command should work (it re-use the previous PVC), but you can use your own <code>kubectl apply</code> command.</p>
<pre><code>grep -v -e &quot;uid:&quot; -e &quot;resourceVersion:&quot; -e &quot;namespace:&quot; -e &quot;selfLink:&quot;  /tmp/pvc.yml | kubectl -n &quot;$NAMESPACE2&quot; apply -f -
</code></pre>
<h2>Assign PVC to PV</h2>
<p>At this point, the PV is bounded to the former PVC's name (but it may not work, and it is not the standard configuration). Running <code>kubectl describe -n &quot;$NAMESPACE2&quot; pvc &quot;$PVC&quot;</code>will complain with <code>Status:        Lost</code> and/or <code>Warning  ClaimMisbound</code>. So let's fix the problem:</p>
<p>Retrieve the new PVC's uid:</p>
<pre><code>PVCUID=$( kubectl get -n &quot;$NAMESPACE2&quot; pvc &quot;$PVC&quot; -o custom-columns=UID:.metadata.uid --no-headers )
</code></pre>
<p>Then update the PV accordingly :</p>
<pre><code>kubectl patch pv &quot;$PV&quot; -p '{&quot;spec&quot;:{&quot;claimRef&quot;:{&quot;uid&quot;:&quot;'$PVCUID'&quot;,&quot;name&quot;:null}}}'
</code></pre>
<p>After a few seconds the PV should be <code>Status:  Bound</code>.</p>
<h2>Restore PV ReclaimPolicy=Delete</h2>
<p>(This step is optional. Needed to ensure PV is deleted when user delete the PVC)</p>
<p>Once the PV is in <code>Bound</code> state again, you can restore the reclaim policy if you want to preserve the original behaviour (i.e removing the PV when the PVC is removed) :</p>
<pre><code>kubectl patch pv &quot;$PV&quot; -p '{&quot;spec&quot;:{&quot;persistentVolumeReclaimPolicy&quot;:&quot;Delete&quot;}}'

## Check :
kubectl get pv $PV -o yaml | grep -e Reclaim -e namespace
</code></pre>
<p>Voilà</p>
