为啥匹配的持久卷不绑定到匹配的持久卷声明(使用 k3s)?

Posted

技术标签:

【中文标题】为啥匹配的持久卷不绑定到匹配的持久卷声明(使用 k3s)?【英文标题】:Why does a match Persistent Volume not bind to a match Persistent Volume Claim (using k3s)?为什么匹配的持久卷不绑定到匹配的持久卷声明(使用 k3s)? 【发布时间】:2021-05-08 13:05:18 【问题描述】:

我有一个看似简单的 PV 和 PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: www-pvc
spec:
  storageClassName: ""
  volumeName: www-pv
  accessModes:
    - ReadOnlyMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: www-pv
spec:
  storageClassName: ""
  claimRef:
    name: www-pvc
  capacity:
    storage: 1Mi
  accessModes:
    - ReadOnlyMany
  nfs:
    server: 192.168.1.100
    path: "/www"

由于某种原因,它们不会相互绑定,PVC 会永远“挂起”:

$ 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

如何调试匹配? k3s中匹配的是哪个服务?我会查看 k3s 二进制文件的日志(在 Debian 下作为服务运行)吗?

【问题讨论】:

如果您的 PVC 大小为 1 Gb 而 PV 为 1 MB,请更改它。你可以 PVC 1 MB 和 PV 1 GB PV 尺寸不能小于 PVC 尺寸。 您的 Yamls 有 2 个问题。第一个是存储,第二个是Object Definition with claimRef / Pre-Binding。我会在答案中解释。 【参考方案1】:

我认为问题在于PVC 试图获得大小为1GiPV,但您的PV 大小为1M

所以,绑定失败了。您可以通过增大PV 大小或减小PVC 大小来解决此问题。

使用kubectl describe pvc 获取有关事件和失败原因的更多信息。

为了进一步澄清,PVC 是对存储的请求,因此如果您在声明中说您需要 1G 的存储但您只提供了实际存储的 1M,则 PVC 将保留在 @ 987654332@ 州。基于此,PVC 中定义的大小应始终小于或等于PV 大小。

【讨论】:

【参考方案2】:

PV 尺寸不能小于 PVC 尺寸。

in otherwords

PVC 1 GB 大小不能大于 PV 1 MB 大小。

请更新 PV 和 PVC 尺寸。

【讨论】:

【参考方案3】:

在有关 Persistent Volumes 的 Kubernetes 文档中,您可以找到相关信息

PersistentVolume (PV) 是集群中的一块存储,由管理员配置或使用 Storage Classes 动态配置。

PersistentVolumeClaim (PVC) 是用户的存储请求。它类似于 Pod。 Pod 消耗节点资源,PVC 消耗 PV 资源。

在Binding 部分您有信息

如果不存在匹配的卷,则声明将无限期保持不受约束。当匹配的数量可用时,索赔将受到约束。 例如,配置了许多 50Gi PV 的集群将无法匹配请求 100Gi 的 PVC。 将 100Gi PV 添加到集群时可以绑定 PVC。

在Openshift Documentation - Volume and Claim Pre-binding 中,您可以找到在使用pre-binding 时会跳过一些匹配项的信息。

如果您确切知道希望 PersistentVolumeClaim 绑定到哪个 PersistentVolume,则可以使用 volumeName 字段在 PVC 中指定 PV。此方法跳过正常的匹配和绑定过程。 PVC 将只能绑定到具有在 volumeName 中指定的相同名称的 PV。如果这样一个同名的 PV 存在并且可用,那么无论 PV 是否满足 PVC 的标签选择器、访问方式和资源请求,PV 和 PVC 都会被绑定。

问题 1

在您设置的PV 配置中

  capacity:
    storage: 1Mi

这意味着您有 1Mi 的存储空间,约为 1.04 MB。

您的 PVC 被配置为请求 1Gi,即 ~ 1.07GB。

  resources:
    requests:
      storage: 1Gi

您的PV 没有满足您的PVC 请求。

您可以拥有多个PV,例如5Gi 存储,但如果PVC 请求高于5Gi,则它们都不会被绑定,例如6Gi。但是如果PV 存储空间较高,6GiPVC 请求较低,比如5Gi 它将是有限的,但是1Gi 将被浪费。

问题 2

如果你要描述你的PVC,你会在下面找到Warning

Events:
  Type     Reason         Age               From                         Message
  ----     ------         ----              ----                         -------
  Warning  FailedBinding  2s (x2 over 17s)  persistentvolume-controller  volume "www-pv" already bound to a different claim.

在您的配置中,您使用的是 Pre-Binding,正如您在 PV 中指定的 volumeName 和在 PVC 中指定的 claimRef

这个例子在OpenShift Documentation - Using Persistent Volumes中有很好的描述。在您当前的设置中,您使用了claimRef.name,但没有指定claimRef.namespace

$ 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

但是当你添加 claimRef.namespace 时它会起作用。

$ 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

您应该在PV's spec.claimRef.namespace 中指定PVC's 命名空间,因为PVCnamespaced 资源。

$ kubectl api-resources | grep pv
persistentvolumeclaims            pvc                                         true         PersistentVolumeClaim
persistentvolumes                 pv                                          false        PersistentVolume

解决方案

在您的PV 中将spec.capacity.storage 更改为1Gi

在您的PV 中添加spec.claimRef.namespace: default,如下例所示:

spec:
  storageClassName: ""
  claimRef:
    name: www-pvc
    namespace: default        # adding namespace: defaults
  capacity:
    storage: 1Gi              # changed storage size

如果您能够绑定PVPVC,请告诉我。

【讨论】:

@tibbe 你的 PV 和 PVC 仍有问题吗?【参考方案4】:

这是对上面提供的答案的补充,(pv/pvc 尺寸校正)

你应该确保你已经安装了nfs-common 包并且你可以在节点本身挂载那个 nfs 导出。

由于您的定义中 storageClassName 是空的 - 我可以建议调查一下 https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

【讨论】:

以上是关于为啥匹配的持久卷不绑定到匹配的持久卷声明(使用 k3s)?的主要内容,如果未能解决你的问题,请参考以下文章

如何识别持久卷声明中剩余的存储空间?

k8sk8s存储之持久卷(pv)持久卷声明(pvc)nfs持久化存储示例

k8sk8s存储之持久卷(pv)持久卷声明(pvc)nfs持久化存储示例

POD崩溃时持久卷声明中的容器数据

为啥我的主机路径持久卷可以从所有 pod 访问?

如何将一个持久卷声明的数据与另一个隔离