2021 年 12 月 17 日更新。

管理用于实现有状态集解决方案的存储是与管理计算实例不同的问题。

🎿 0a。引擎盖下是什么

“only one lost ski”没有表情符号,所以作者将在文章的这个_theoretical_部分使用一个通用图标。 ☃️

在 Kubernetes 术语中,PersistentVolume子系统为用户和管理员提供了一个 API,它从如何使用存储中提取了存储如何提供的详细信息。为此,K8s 团队引入了两个 API 资源:PersistentVolumePersistentVolumeClaim

PersistentVolume(PV) 是集群中的一块存储,由管理员配置或使用Storage Classes动态配置。它是集群中的资源,就像节点是集群资源一样。 PV 是与 Volumes 类似的卷插件,但其生命周期独立于使用 PV 的任何单个 pod。此 API 对象捕获存储实现的详细信息,无论是 NFS、iSCSI 还是特定于云提供商的存储系统。从 K8s 版本 1.11bPersistentVolumes 甚至可以将配置为可扩展。

[PV 基础知识](https://res.cloudinary.com/practicaldev/image/fetch/s--Jtu-XBrd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to-uploads.s3.amazonaws.com/uploads/articles/fu8i88mxc22sy6kbikhn.png)

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

让我们看看 3(三)种方法来使 PV + PVC 对彼此牢固地绑定在一起。

🎿 I. 卷名:是的,我们再次需要对 GKE 进行 hack

而最简单的大约是volumeName!

有些情况 当您的 GKE 环境中已经有一个永久磁盘(比如命名为pd-name),并且,让我们想象一下,显然您想严格使用这个磁盘并且不想创建一个新磁盘。

下面的清单文件描述了您的集群可以使用的相应PersistentVolumePersistentVolumeClaim

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-demo
spec:
  storageClassName: ""
  capacity:
    storage: 50G
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    pdName: pd-name
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-claim-demo
spec:
  storageClassName: ""
  volumeName: pv-demo
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50G

进入全屏模式 退出全屏模式

⚠️ 注意:必须将""指定为storageClassName,这样就不会使用默认存储类。

现在您可以使用上述的kubectl apply -f existing-pd.yaml命令来创建PersistentVolumePersistentVolumeClaim

Pod 通过将声明用作卷来访问存储。 Claims 必须与使用该声明的 pod 存在于同一命名空间中。 集群在 pod 的命名空间中找到该声明并使用它来获取支持该声明的PersistentVolume。然后将卷挂载到主机和 Pod 中。

在集群中存在PersistentVolumePersistentVolumeClaim之后,您可以通过指定容器的volumeMounts.mountPathvolumeMounts.name的值来授予 Pod 的容器对卷的访问权限,如下例所示:

kind: Pod
apiVersion: v1
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
       claimName: pv-claim-demo
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

进入全屏模式 退出全屏模式

这样,当您将此清单应用到集群时,就会创建 Pod,并且task-pv-container容器可以访问其/usr/share/nginx/html/目录中的卷。

🎿 0b。手续很重要!我们必须知道我们想做什么

在 GKE 中,要让容器访问您预先存在的永久性磁盘,您需要来执行以下:

  • 将现有永久磁盘配置为PersistentVolume

  • PersistentVolume绑定到PersistentVolumeClaim

  • 让 Pod 中的容器访问PersistentVolume

您可能已经猜到了,有几种方法可以将PersistentVolumeClaim绑定到特定的PersistentVolume。例如,以下 YAML 清单创建新的PersistentVolumePersistentVolumeClaim,然后使用claimRef将声明绑定到卷(见下文),这确保了PersistentVolume只能绑定到PersistentVolumeClaim

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

☑️ 如果您确切知道希望PersistentVolumeClaim绑定到哪个PersistentVolume,则可以使用volumeName字段在 PVC 中指定 PV。此方法_skips_正常的匹配和绑定过程。 PVC 将只能绑定到与volumeName中指定的同名的 PV。如果存在具有volumeName且为Available的 PV,则 PV 和 PVC 将被绑定_无论 PV 是否满足 PVC 的标签选择器,访问模式和资源请求。

要将PersistentVolume绑定到PersistentVolumeClaim,两个资源的storageClassName以及容量accessModesvolumeMode必须匹配。

⚠️ 再次请注意,storageClassName可以省略,但必须指定""以防止 Kubernetes 使用默认的StorageClass

storageClassName不需要引用现有的 StorageClass 对象。如果您只需要将声明绑定到卷,则可以使用任何您想要的名称。但是,如果您需要 StorageClass 配置的额外功能,例如调整卷大小,则storageClassName必须引用现有的 StorageClass object

🎿 二。轮盘赌还是扑克?魔术声明参考

重要的是要了解应用程序开发人员可以为 Pod 和PersistentVolumeClaim对象创建清单,而无需了解应用程序将在其上运行的基础架构的任何信息。同样,集群管理员可以预先配置一组不同大小的存储卷,而无需对将使用它们的应用程序了解太多。您可能会在下面看到有关此过程内部结构的一些示意图。

Kubernetes可以操作不同的网络文件系统,当然不仅仅是 NFS。

[PV + PVC + 集群管理员](https://res.cloudinary.com/practicaldev/image/fetch/s--coVvTTym--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// dev-to-uploads.s3.amazonaws.com/uploads/articles/z1oc30m5dgye12o1e4ix.png)

您可能还希望您的集群管理员_“保留”卷_仅用于您的声明,以便其他人的声明可以在您的声明之前绑定到它。在这种情况下,管理员可以使用claimRef字段指定 PV 中的 PVC。

apiVersion: "v1"
kind: "PersistentVolumeClaim"
metadata:
  name: "claim1"
spec:
  accessModes:
    - "ReadWriteOnce"
  resources:
    requests:
      storage: "1Gi"
  volumeName: "pv0001"

进入全屏模式 退出全屏模式

PV 只能绑定到claimRef中指定的具有相同名称和命名空间的 PVC。PVC 的访问模式和资源请求仍然必须满足才能绑定 PV 和 PVC,尽管标签选择器被忽略.具有claimRef示例的持久卷对象定义如下所示:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  nfs:
    path: /tmp
    server: 172.17.0.2
  persistentVolumeReclaimPolicy: Recycle
  claimRef:
    name: claim1
    namespace: default

进入全屏模式 退出全屏模式

在你的 PVC 中指定volumeName不会阻止不同的 PVC 在你之前绑定到指定的 PV。在 PV 为Available之前,您的索赔将保持为Pending

☑️ 应该记住,在 PV 中指定claimRef不会阻止_指定的 PVC 被绑定到不同的 PV! PVC 可以按照正常的绑定过程自由选择另一个 PV 进行绑定。因此,为避免_这些情况并_确保_您的声明被绑定_您想要的卷,您必须_确保_指定_volumeNameclaimRef

您可以通过检查BoundPV 和 PVC 对的pv.kubernetes.io/bound-by-controller:注释来判断您的volumeName和/或claimRef设置影响了匹配和绑定过程。您自己设置volumeName和/或claimRef的 PV 和 PVC 将没有此类注释,但普通 PV 和 PVC 会将其设置为“yes”。有关这种情况,请参阅 GitLab 的文章。

当 PV 将其claimRef设置为某个 PVC 名称和命名空间,并根据 Retain 或 Recycle 回收策略进行回收时,即使 PVC 或整个命名空间不再存在,它的claimRef仍将设置为相同的 PVC 名称和命名空间。

⚠️ 设置claimRefs 的能力是所述用例的临时解决方法。限制谁可以声明某个卷的长期解决方案正在开发中。集群管理员应该首先考虑配置选择器标签卷绑定,然后再代表用户设置claimRefs。

🎿 三。选择器和标签,或者等等,我都提前写好了!

因此,有一种更优雅的方法可以通过selectorlabel属性将持久卷声明 (PVC) 绑定到持久卷 (PV)。通过实施选择器和标签,普通用户可以通过集群管理员定义的标识符来定位预置存储。

为什么需要它?在静态配置存储的情况下,寻求持久存储的开发人员需要知道 PV 的一些识别属性才能部署和绑定 PVC。这产生了几个有问题的情况。普通用户可能必须联系集群管理员来部署 PVC 或提供 PV 值。单独的 PV 属性_不传达存储卷的预期用途,也不提供可以对卷进行分组的方法_。

选择器和标签属性可用于_从用户那里抽象出 PV 详细信息_,同时为集群管理员提供一种通过描述性和可定制标签识别卷的方法。通过 selector-label 绑定方法,用户_只需要知道管理员定义了哪些标签。让我们看一下带标签的持久卷示例:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: gluster-volume
  labels: 
    storage-tier: gold
    aws-availability-zone: us-east-1
spec:
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteMany
  glusterfs:
    endpoints: glusterfs-cluster 
    path: myVol1
    readOnly: false
  persistentVolumeReclaimPolicy: Retain

进入全屏模式 退出全屏模式

使用 labels 来识别卷之间共享的公共属性或特征。在本例中,我们将Gluster卷定义为具有名为storage-tier的自定义属性(键),并分配了值gold。索赔将能够选择具有storage-tier=gold的 PV 来匹配此 PV。

作为下一步,我们需要编写一个声明,一个带有选择器的持久卷声明。带有 selector 节的声明(参见下面的示例)尝试匹配现有的、未声明的和非预绑定的 PV。 PVC 选择器的存在_忽略_一个 PV 的_容量。但是,matching 标准中仍然_考虑了accessModes

⚠️ 重要的是要注意声明必须匹配其选择器节中包含的所有键值对。如果没有 PV 与声明匹配,则 PVC 将保持未绑定 (Pending)。随后可以创建 PV,并且声明将自动_检查标签匹配_。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gluster-claim
spec:
  accessModes:
  - ReadWriteMany
  resources:
     requests:
       storage: 1Gi
  selector: 
    matchLabels:
      storage-tier: gold
      aws-availability-zone: us-east-1

进入全屏模式 退出全屏模式

🎿 四。如果我们不想产生无用的实体怎么办?

现实生活中常常有惊喜。如果您无法从使用 PersistentVolume 的 Pod 中恢复数据,或者您正在寻找安全删除 Pod 而又不影响存储在 PV 中的存储的方法,该怎么办?

[GCP GKE PV 编辑按钮](https://res.cloudinary.com/practicaldev/image/fetch/s--bOeEXV7H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to-uploads.s3.amazonaws.com/uploads/articles/42ihjq5oe6y19k0qkkxg.png)

⚠️ 确保 PersistentVolumeReclaimPolicy设置为到Retain。对于动态配置的 PersistentVolume,默认回收策略是Delete。这意味着当用户删除相应的 PersistentVolumeClaim 时,会自动删除动态配置的卷。这种自动行为_如果卷包含宝贵的数据_可能是不合适的。

如果ReclaimPolicy当前设置为Delete,这是 GKE 中用于 pod 的常见逻辑(查看 YAML 中的spec.persistentVolumeReclaimPolicy: Delete),您可以通过发出命令来修补 PV:

kubectl patch pv <your-pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

进入全屏模式 退出全屏模式

接下来,继续删除正在使用该 PV 的资源。删除 PVC/Pod 保留后,PV 的STATUS将变为Released

在 Released 状态下,编辑 PV 并删除spec.claimRef块:

apiVersion: v1
kind: PersistentVolume
...
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 20Gi
  claimRef:
...

进入全屏模式 退出全屏模式

删除spec.claimRef块后,PersistentVolume 将可用。您将能够继续重新添加涉及我们上面讨论的 PV 的应用程序。

如何检查我们所做的一切

kubectl get pvkubectl get pvc命令可用于查看为应用程序定义的PersistentVolumePersistentVolumeClaim。如果STATUSBound,则应用程序_do have_访问必要的存储。kubectl describe pv命令可用于查看有关应用程序使用的持久卷的详细信息。

kubectl describe pv命令用于查看应用程序使用的 Persistent Volume 的详细信息。一个示例(感谢IBM)如下所示:

# kubectl describe pv
NAME                  CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                             STORAGECLASS   REASON    AGE
powerai-vision-data   40Gi       RWX            Retain           Bound     default/powerai-vision-data-pvc                            48d
[root@dlf01 ~]# /opt/powerai-vision/bin/kubectl.sh describe pv
Name:            powerai-vision-data
Labels:          assign-to=powerai-vision-data
                 type=local
Annotations:     pv.kubernetes.io/bound-by-controller=yes
StorageClass:    
Status:          Bound
Claim:           default/powerai-vision-data-pvc
Reclaim Policy:  Retain
Access Modes:    RWX
Capacity:        40Gi
Message:         
Source:
    Type:  HostPath (bare host directory volume)
    Path:  /opt/powerai-vision/volume/
Events:    <none>

进入全屏模式 退出全屏模式

kubectl describe pvc命令用于查看有关应用程序的 Persistent Volume Claim 的详细信息。

# kubectl describe pvc

Name:          powerai-vision-data-pvc
Namespace:     default
StorageClass:  
Status:        Bound
Volume:        powerai-vision-data
Labels:        app=powerai-vision
               chart=ibm-powerai-vision-prod-1.1.0
               heritage=Tiller
               release=vision
Annotations:   pv.kubernetes.io/bind-completed=yes
               pv.kubernetes.io/bound-by-controller=yes
Capacity:      40Gi
Access Modes:  RWX
Events:        <none>

进入全屏模式 退出全屏模式

上述输出分别显示了有关应用程序使用的持久卷声明的更多详细信息。Volume部分引用底层 Persistent Volume,如果已成功分配给应用程序,则STATUS应该是Bound。事件部分将显示持久卷声明是否存在问题。

此外,作者对 Utku Özdemir 的pv-migrate感到非常兴奋,这是一个 CLI 工具/kubectl插件,可以轻松地将一个 KubernetesPersistentVolume[Claim]的内容迁移到另一个。

可以在此处找到(感谢 DevOpsCube 团队)具有持久卷的 GKE Pod 的 YAML 示例。

[平谷喜欢滑雪!](https://res.cloudinary.com/practicaldev/image/fetch/s--_mKk2VTs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to-uploads.s3.amazonaws.com/uploads/articles/z9enban60vm0rz0b3gao.jpeg)

来源:RedHat、loft.sh、K8s 文档、GitLab、GitHub、Letsdoclod.com,作者 Erick Gubi

📖 Marko Lukša 的“Kubernetes In Action”,ISBN9781617293726

Logo

CI/CD社区为您提供最前沿的新闻资讯和知识内容

更多推荐