翻译自Introducing Single Pod Access Mode for PersistentVolumes

访问模式及重要意义

当使用持久化储存时,对于存储有多种模式进行访问使用。

例如,存储系统中的网络文件可以同时被多个用户进行读写数据。在另一种场景下,也许每个用户允许进行读而不具备写的权限。对于高敏数据,可能只允许一个用户用户进行读写操作而不是所有的用户。

Kubernetes 的世界中,access mode就是我们定义持久化存储如何使用的方式。这些访问方式作为 PVsPVCsspec 描述的一部分内容。

1
2
3
4
5
6
7
8
9
10
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: shared-cache
spec:
accessModes:
- ReadWriteMany # Allow many pods to access shared-cache simultaneously.
resources:
requests:
storage: 1Gi

v1.22 版本之前, KubernetesPVsPVCs提供如下三种访问模式:

  • ReadWriteOnce - volume 只允许被单个 node 进行读写
  • ReadOnlyMany - volume 允许被多个 node 进行读操作
  • ReadWriteMany - volume 允许被多个 node 进行读写操作

这些访问模式通过 Kubernetes 组件如 kube-controller-managerkubelet 来保证相应的 Pods 能够访问所应用的 PersistentVolume.

新的访问模式及运行原理

Kubernetes v1.22 介绍了 PVsPVCs 的第四种访问模式:

  • ReadWriteOncePod - volume 允许单个 Pod 进行读写操作

如果你对使用了 PVCPod 配置了 ReadWriteOncePod 的访问模式,Kubernetes 将确保此 Pod 是集群中唯一能够对此 PVC 进行读写的唯一 Pod.

如果你将另一个 Pod 对同一个 PVC 进行配置关联且也是配置了此访问模式,那么此 Pod 将无法启动,因为此 PVC 已经被另一个 Pod 使用了。例如:

1
2
3
4
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 1s default-scheduler 0/1 nodes are available: 1 node has pod using PersistentVolumeClaim with the same name and ReadWriteOncePod access mode.

此访问模式与 ReadWriteOnce 的区别?

ReadWriteOnce 访问模式约束 volume 对应单个 node,这意味着在同一个节点上的多个 Pods 能够读写通过一个 volume。对于某些应用此访问模式可能是个潜在的重大问题,尤其是对那些要求至多要求保证只有一个数据写入而言。

PVC 设置 ReadWriteOncePod 访问策略,那么 Kubernetes 将保证只有一个 Pod 能够进行访问。

如何使用?

ReadWriteOncePod 访问模式在 v1.22 版本中是 alpha 版本,并且支持 CSI volume。首先你得在 kube-apiserver, kube-scheduler, kubelet 中开启对 ReadWriteOncePod特性。你可以通过设置如下命令行参数进行配置:

1
2
3
4
5
6
--feature-gates="...,ReadWriteOncePod=true"

另外你的将如下 `CSI sidecars` 升级到如下版本或更高:
- [csi-provisioner:v3.0.0+](https://github.com/kubernetes-csi/external-provisioner/releases/tag/v3.0.0)
- [csi-attacher:v3.3.0+](https://github.com/kubernetes-csi/external-attacher/releases/tag/v3.3.0)
- [csi-resizer:v1.3.0+](https://github.com/kubernetes-csi/external-resizer/releases/tag/v1.3.0)

创建 PersistentVolumeClaim

PVsPVCs 使用 ReadWriteOncePod 访问模式,你需创建一个新的 PVC 配置如下的访问模式:

1
2
3
4
5
6
7
8
9
10
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: single-writer-only
spec:
accessModes:
- ReadWriteOncePod # Allow only a single pod to access single-writer-only.
resources:
requests:
storage: 1Gi

如果你的存储插件支持 dynamic provisioning,新的 PersistentVolumes 将会应用ReadWriteOncePod访问模式。

迁移已有的 PersistentVolumes

如果你已经有了存在的 PersistentVolumes,也可以将它们迁移使用 ReadWriteOncePod 访问模式。

在此例子中,我们已经拥有了与 cat-pictures-pv 绑定的 cat-pictures-pvc PersistentVolumeClaim,另外 cat-pictures-writer Deployment 已经使用了此 PersistentVolumeClaim

第一步,你需要编辑你的 PersistentVolume 中的 spec.persistentVolumeReclaimPolicy 将其改为 **Retain**。这是为了保证当我们相关 PersistentVolumeClaim 的时候 PersistentVolume 将不会被删除。

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

下一步你需要停止那些使用了你想做迁移的 PersistentVolume 想关联的 PersistentVolumeClaim 的工作平面,同事删除这些 PersistentVolumeClaim

一旦如上步骤已经完成,你需要清除与你相关的 PersistenVolume 相关的 spec.claimRef.uid 字段内容,以便确保 PersistentVolumeClaims 能够在再次创建过程中能够被绑定。

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

结束之后你需要将 PersistentVolume 的访问模式替换为 ReadWriteOncePod

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

NoteReadWriteOncePod 访问模式无法与其他的访问模式进行结合使用。确保在更新 PersistentVolume 的时候 ReadWriteOncePod是唯一的访问模式,否则将会放生请求失败。

下一步你的得将你的 PersistentVolumeClaim 修改为 ReadWriteOncePod 作为唯一的访问模式。同时你还得将配置 PersistentVolumeClaim 中的 spec.volumeName 对应到你的 PersistentVolume

一旦以上步骤都已经完成,你可以重新创建你的 PersistenVolumeClaim 并且启动你的工作平面:

1
2
3
4
5
6
# IMPORTANT: Make sure to edit your PVC in cat-pictures-pvc.yaml before applying. You need to:
# - Set ReadWriteOncePod as the only access mode
# - Set spec.volumeName to "cat-pictures-pv"

kubectl apply -f cat-pictures-pvc.yaml
kubectl apply -f cat-pictures-writer-deployment.yaml

最后你可能需要编辑的你的 PersistentVolumespec.persistentVolumeReclaimPolicy 字段并将其配置为 Delete 如果你确实改动过它:

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

你可以阅读Configure a Pod to Use a PersistentVolume for Storage了解更多的细节。