将 PersistentVolume 的访问模式更改为 ReadWriteOncePod

本文演示了如何将现有 PersistentVolume 的访问模式更改为使用 ReadWriteOncePod

准备开始

你必须拥有一个 Kubernetes 的集群,且必须配置 kubectl 命令行工具让其与你的集群通信。 建议运行本教程的集群至少有两个节点,且这两个节点不能作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:

你的 Kubernetes 服务器版本必须不低于版本 v1.22. 要获知版本信息,请输入 kubectl version.

说明:

ReadWriteOncePod 访问模式在 Kubernetes v1.29 版本中已进阶至 Stable。 如果你运行的 Kubernetes 版本早于 v1.29,你可能需要启用一个特性门控。 请查阅你所用 Kubernetes 版本的文档。

说明:

ReadWriteOncePod 访问模式仅支持 CSI 卷。 要使用这种卷访问模式,你需要更新以下 CSI 边车至下述版本或更高版本:

我为什么要使用 ReadWriteOncePod

在 Kubernetes v1.22 之前,ReadWriteOnce 访问模式通常用于限制需要单个写者存储访问模式的工作负载对 PersistentVolume 的访问。 然而,这种访问模式有一个限制:它要求只能从单个节点上访问卷,但允许同一节点上的多个 Pod 同时读写同一个卷。 对于需要严格遵循单个写者访问模式以确保数据安全的应用,这种模式可能形成风险。

如果确保单个写者访问模式对于你的工作负载至关重要,请考虑将你的卷迁移到 ReadWriteOncePod

迁移现有 PersistentVolume

如果你有一些 PersistentVolume,可以将它们迁移为使用 ReadWriteOncePod。 系统仅支持从 ReadWriteOnce 迁移到 ReadWriteOncePod

在此示例中,已经有一个 ReadWriteOnce 的 “cat-pictures-pvc” PersistentVolumeClaim 被绑定到了 “cat-pictures-pv” PersistentVolume,还有一个使用此 PersistentVolumeClaim 的 “cat-pictures-writer” Deployment。

说明:

如果你的存储插件支持动态制备, 系统将为你创建 “cat-pictures-pv”,但其名称可能不同。 要获取你的 PersistentVolume 的名称,请运行以下命令:

  1. kubectl get pvc cat-pictures-pvc -o jsonpath='{.spec.volumeName}'

你可以在进行更改之前查看 PVC。你可以在本地查看清单, 或运行 kubectl get pvc <PVC 名称> -o yaml。这条命令的输出类似于:

  1. # cat-pictures-pvc.yaml
  2. kind: PersistentVolumeClaim
  3. apiVersion: v1
  4. metadata:
  5. name: cat-pictures-pvc
  6. spec:
  7. accessModes:
  8. - ReadWriteOnce
  9. resources:
  10. requests:
  11. storage: 1Gi

以下是一个依赖于此 PersistentVolumeClaim 的 Deployment 示例:

  1. # cat-pictures-writer-deployment.yaml
  2. apiVersion: apps/v1
  3. kind: Deployment
  4. metadata:
  5. name: cat-pictures-writer
  6. spec:
  7. replicas: 3
  8. selector:
  9. matchLabels:
  10. app: cat-pictures-writer
  11. template:
  12. metadata:
  13. labels:
  14. app: cat-pictures-writer
  15. spec:
  16. containers:
  17. - name: nginx
  18. image: nginx:1.14.2
  19. ports:
  20. - containerPort: 80
  21. volumeMounts:
  22. - name: cat-pictures
  23. mountPath: /mnt
  24. volumes:
  25. - name: cat-pictures
  26. persistentVolumeClaim:
  27. claimName: cat-pictures-pvc
  28. readOnly: false

第一步,你需要编辑 PersistentVolume 的 spec.persistentVolumeReclaimPolicy 并将其设置为 Retain。此字段确保你在删除相应的 PersistentVolumeClaim 时不会删除 PersistentVolume:

  1. kubectl patch pv cat-pictures-pv -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

接下来,你需要停止正在使用绑定到你要迁移的这个 PersistentVolume 上的 PersistentVolumeClaim 的所有工作负载,然后删除该 PersistentVolumeClaim。 在迁移完成之前,不要对 PersistentVolumeClaim 进行任何其他更改,例如调整卷的大小。

完成后,你需要清除 PersistentVolume 的 spec.claimRef.uid 以确保在重新创建时 PersistentVolumeClaim 能够绑定到它:

  1. kubectl scale --replicas=0 deployment cat-pictures-writer
  2. kubectl delete pvc cat-pictures-pvc
  3. kubectl patch pv cat-pictures-pv -p '{"spec":{"claimRef":{"uid":""}}}'

之后,将 PersistentVolume 的有效访问模式列表替换为(仅)ReadWriteOncePod

  1. kubectl patch pv cat-pictures-pv -p '{"spec":{"accessModes":["ReadWriteOncePod"]}}'

说明:

ReadWriteOncePod 访问模式不能与其他访问模式结合使用。 你要确保在更新时 ReadWriteOncePod 是 PersistentVolume 上的唯一访问模式,否则请求将失败。

接下来,你需要修改 PersistentVolumeClaim,将 ReadWriteOncePod 设置为唯一的访问模式。 你还应将 PersistentVolumeClaim 的 spec.volumeName 设置为 PersistentVolume 的名称, 以确保其绑定到特定的 PersistentVolume。

完成后,你可以重新创建你的 PersistentVolumeClaim 并启动你的工作负载:

  1. # 重要提示:在 apply 操作之前必须编辑在 cat-pictures-pvc.yaml 中的 PVC。你需要:
  2. # - 将 ReadWriteOncePod 设置为唯一的访问模式
  3. # - 将 spec.volumeName 设置为 "cat-pictures-pv"
  4. kubectl apply -f cat-pictures-pvc.yaml
  5. kubectl apply -f cat-pictures-writer-deployment.yaml

最后,你可以编辑 PersistentVolume 的 spec.persistentVolumeReclaimPolicy 并将其设置回 Delete, 如果你之前更改了这个字段的话。

  1. kubectl patch pv cat-pictures-pv -p '{"spec":{"persistentVolumeReclaimPolicy":"Delete"}}'

接下来