<p>I have what seems like a straightforward PV and PVC:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: www-pvc
spec:
  storageClassName: &quot;&quot;
  volumeName: www-pv
  accessModes:
    - ReadOnlyMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: www-pv
spec:
  storageClassName: &quot;&quot;
  claimRef:
    name: www-pvc
  capacity:
    storage: 1Mi
  accessModes:
    - ReadOnlyMany
  nfs:
    server: 192.168.1.100
    path: &quot;/www&quot;
</code></pre>
<p>For some reason these do not bind to each other and the PVC stays &quot;pending&quot; forever:</p>
<pre><code>$ kubectl get pv,pvc
NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM      STORAGECLASS   REASON   AGE
persistentvolume/www-pv   1Mi        ROX            Retain           Available   /www-pvc                           107m

NAME                            STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/www-pvc   Pending   www-pv   0                                        107m
</code></pre>
<p>How can I debug the matching? Which service does the matching in k3s? Would I be looking in the log of the k3s binary (running as a service under Debian)?</p>

<p>In Kubernetes documentation about <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" rel="nofollow noreferrer">Persistent Volumes</a> you can find information that :</p>
<blockquote>
<p>A <code>PersistentVolume</code> (PV) is a piece of storage in the cluster that has been provisioned by an administrator or dynamically provisioned using <code>Storage Classes</code>.</p>
<p>A <code>PersistentVolumeClaim</code> (PVC) is a request for storage by a user. It is similar to a Pod. Pods consume node resources and PVCs consume PV resources.</p>
</blockquote>
<p>In <a href="https://docs.openshift.com/container-platform/3.3/dev_guide/persistent_volumes.html" rel="nofollow noreferrer">Binding</a> section you have information :</p>
<blockquote>
<p>Claims will remain unbound indefinitely if a matching volume does not exist. Claims will be bound as matching volumes become available. <strong>For example, a cluster provisioned with many 50Gi PVs would not match a PVC requesting 100Gi.</strong> The PVC can be bound when a 100Gi PV is added to the cluster.</p>
</blockquote>
<p>In <a href="https://docs.openshift.com/container-platform/3.3/dev_guide/persistent_volumes.html#persistent-volumes-volumes-and-claim-prebinding" rel="nofollow noreferrer">Openshift Documentation - Volume and Claim Pre-binding</a> you can find information that when you are using <code>pre-binding</code> you are skipping some matchings.</p>
<blockquote>
<p>If you know exactly what PersistentVolume you want your PersistentVolumeClaim to bind to, you can specify the PV in your PVC using the volumeName field. This method skips the normal matching and binding process. The PVC will only be able to bind to a PV that has the same name specified in volumeName. If such a PV with that name exists and is Available, the PV and PVC will be bound regardless of whether the PV satisfies the PVC’s label selector, access modes, and resource requests.</p>
</blockquote>
<p><strong>Issue 1</strong></p>
<p>In your <code>PV</code> configuration you set</p>
<pre><code>  capacity:
    storage: 1Mi
</code></pre>
<p>which means that you have storage with 1Mi which is ~ 1.04 MB.</p>
<p>Your <code>PVC</code> was configured to request 1Gi which is ~ 1.07GB.</p>
<pre><code>  resources:
    requests:
      storage: 1Gi
</code></pre>
<p>Your <code>PV</code> didn't fulfill your <code>PVC</code> request.</p>
<p>You can have many <code>PV</code> with example <code>5Gi</code> storage but none of them will be bound if <code>PVC</code> request is higher than <code>5Gi</code>, like <code>6Gi</code>. But if <code>PV</code> storage is higher <code>6Gi</code> and <code>PVC</code> request is lower, like <code>5Gi</code> it will be bounded, however <code>1Gi</code> will be wasted.</p>
<p><strong>Issue 2</strong></p>
<p>If you will describe your <code>PVC</code> you will find <code>Warning</code> below:</p>
<pre><code>Events:
  Type     Reason         Age               From                         Message
  ----     ------         ----              ----                         -------
  Warning  FailedBinding  2s (x2 over 17s)  persistentvolume-controller  volume &quot;www-pv&quot; already bound to a different claim.
</code></pre>
<p>In your configuration you are using something called <code>Pre-Binding</code> as you have specified <code>volumeName</code> in <code>PVC</code> and <code>claimRef</code> in <code>PV</code>.</p>
<p>This example is well described in <a href="https://docs.openshift.com/container-platform/3.3/dev_guide/persistent_volumes.html" rel="nofollow noreferrer">OpenShift Documentation - Using Persistent Volumes</a>. In your current setup you've used <code>claimRef.name</code> but you didn't specify <code>claimRef.namespace</code>.</p>
<pre><code>$ kubectl get pv,pvc
NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM      STORAGECLASS   REASON   AGE
persistentvolume/www-pv   1Gi        ROX            Retain           Available   /www-pvc                           4m28s

NAME                            STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/www-pvc   Pending   www-pv   0                                        4m28s
</code></pre>
<p>But when you add <code>claimRef.namespace</code> it will work.</p>
<pre><code>$ kubectl get pv,pvc
NAME                      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
persistentvolume/www-pv   1Gi        ROX            Retain           Bound    default/www-pvc                           7m3s

NAME                            STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/www-pvc   Bound    www-pv   1Gi        ROX                           7m3s
</code></pre>
<p>You should specify <code>PVC's</code> namespace in your <code>PV's spec.claimRef.namespace</code> as <code>PVC</code> is <code>namespaced</code> resource.</p>
<pre><code>$ kubectl api-resources | grep pv
persistentvolumeclaims            pvc                                         true         PersistentVolumeClaim
persistentvolumes                 pv                                          false        PersistentVolume
</code></pre>
<h2>Solution</h2>
<p>In your <code>PV</code> change <code>spec.capacity.storage</code> to <code>1Gi</code>.</p>
<p>In your <code>PV</code> add <code>spec.claimRef.namespace: default</code> like on the example below:</p>
<pre><code>spec:
  storageClassName: &quot;&quot;
  claimRef:
    name: www-pvc
    namespace: default        # adding namespace: defaults
  capacity:
    storage: 1Gi              # changed storage size
</code></pre>
<p>Please let me know if you were able to bind <code>PV</code> and <code>PVC</code>.</p>
