解决方案
PV + PVC 是我们早期最常用的方法,也是我们入门时学习使用的数据持久化方法;
持久化数据存储:Persistent Volume
PV 是集群内的资源,没有命名空间;PVC 则是命名空间内的资源;
使用步骤如下:
1)PV 非命名空间资源,因此需要集群管理员定义 PV 资源,它是对存储的抽象;
2)然后,开发者通过 PVC 资源来引用该 PV 资源,
3)最后,在 Pod 的 Volumes 中引用 PVC 资源;
注意事项:
1)如果使用 PVC 资源,则必须定义 PV 资源;
2)PVC 与 PV 是对应绑定的。如果已经有 PVC 绑定到 PV 对象,则其他 PVC 对象不能再绑定到该 PV 对象;
3)虽然 PV 不能共享,但是多个 POD 能够绑定到同个 PVC 以实现存储空间共享;
--- apiVersion: v1 kind: PersistentVolume metadata: name: task-pv-volume labels: type: local spec: storageClassName: manual capacity: storage: 10Gi accessModes: - ReadWriteOnce hostPath: path: "/mnt/data" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: task-pv-claim spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 3Gi --- apiVersion: v1 kind: Pod metadata: name: task-pv-pod spec: volumes: - name: task-pv-storage persistentVolumeClaim: claimName: task-pv-claim containers: - name: task-pv-container image: nginx ports: - containerPort: 80 name: "http-server" volumeMounts: - mountPath: "/usr/share/nginx/html" name: task-pv-storage # 以只读方式挂载 readOnly: true
场景:重新使用 PV(已使用且释放)
A private cloud – all for myself » How to reuse a PersistentVolume/PV in Kubernetes
如果 PV 已经使用(已被 PVC 引用),即使删除 PVC 以后,也无法再继续使用该 PV 资源;
解决方法:
1)首先,修改 PV/persistentVolumeReclaimPolicy 为 Retain 以保存数据;
2)然后,删除 PVC/POD 资源,查看 PV 状态,应为 Released 状态;
3)最后,删除 PV/claimRef 属性,此时 PV 状态应为 Avaiable 状态;
场景:将 PVC 资源绑定特定 PV 资源
kubernetes – Can a PVC be bound to a specific PV? – Stack Overflow
Using Persistent Volumes | Developer Guide | OpenShift Container Platform 3.11
通常 PVC 所使用的 PV 是按需绑定的,由调度器负责分配;
但是,我们可以配置 PVC 资源绑定到特定 PV 资源,这需要我们同时设置 pvc/volumeName 以及 pv/claimRef 属性:
1)单纯设置 PVC/volumeName 不能防止 PV 被其他 PVC“抢占”;
2)单纯设置 PV/claimRef 不能防止 PVC 被绑定到其他 PV 资源;
如下示例 YAML 配置文件:
apiVersion: v1 kind: PersistentVolume metadata: name: nfs-storage-share spec: capacity: storage: 50Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain claimRef: name: nfs-storage-share namespace: default nfs: server: "ip address of the nfs server" path: "/" --- apiVersion: "v1" kind: "PersistentVolumeClaim" metadata: name: "nfs-storage-share" namespace: default spec: accessModes: - "ReadWriteOnce" resources: requests: storage: "50Gi" volumeName: "nfs-storage-share"
hostPath
接下来,要掌握 Minikube 上的数据存储。部署一个有状态的应用程序,例如 MySQL 集群;
创建 hostPath 类型的 PV,并以挂载普通卷的方式将 PV 挂载到容器的文件系统内;
该案例使用 hostPath 类型的 PV,生成环境中不建议使用。应该定义 NFS 或者其他类型支持的网络卷;
分为两步:
1)管理员创建 PV 对象;
2)开发者创建 PVC 对象,以引用该 PV 资源;
1)管理员创建 PV 对象:
kind: PersistentVolume apiVerion: v1 metadatda: name: hostpathpv labels: type: local spec: storageClassName: manual capacity: storage: 1Gi accessModes: - ReadWriteOnce hostPath: path: "/tmp/data" # 当然,前提是这个目录是存在的;
2)开发者创建 PVC 对象,来使用空间:
# 如果要使用 PV,则要先进行 PVC 定义,声明要使用某个持久卷 kind: PersistentVolumeClaim apiVersion: v1 metadata: name: mypvc spec: storageClassName: manual accessModes: - ReadWriteOnce resource: request: # 申请 200Mi 空间 strage: 200Mi
kubectl create -f pvc.yaml
kubectl get pv # 来查看状态
3)在容器中使用该卷:
# ... volume: - name: pvc-claim persistentVolumeClaim: claimName: mypvc
使用 PVC 申请空间:
# data.yaml kind: PersistentVolumnClaim apiVersion: v1 metadata: name: data spec: accessModes: - ReadWriteOnce resource: requests: storage: 1Gi
然后创建该 PVC:kubctl create -f data.yaml
查看状态:kubectl get pv
接下来就是在 Pod 中使用该 PVC:
kind: Pod apiVersion: v1 metadata: name: db spec: container: - name: mysql image: mysql:5.5 volumeMounts: - name: data mountPath: /var/lib/mysql env: - name: MySQL_ROOT_PATH value: root volumns: - name: data persistentVolumeClaim: claimName: data
Access Modes
Persistent Volumes/Access Modes
参考官方文档,以获取详细的使用方法,该部分仅记录我们在实践过程中所遇到的问题;
使用方法
RWO – ReadWriteOnce
ROX – ReadOnlyMany
RWX – ReadWriteMany
RWOP – ReadWriteOncePod
accessModes 虽然是个数组,但是每次仅能使用一个值;
配置案例
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: myclaim spec: accessModes: -------------------------------------------- # 指定 Access Mode 类型; - ReadWriteOnce volumeMode: Filesystem resources: requests: storage: 8Gi storageClassName: slow selector: matchLabels: release: "stable" matchExpressions: - {key: environment, operator: In, values: [dev]}
问题:…Multi-Attach error for volume “xxx” Volume is already used by pod(s) xxx…
Access Mode of ReadWriteOnce does not work as expected · Issue #263
kubernetes persistent volume ReadWriteOnly(RWO) does not work for nfs
accessModes 所指定的属性值,并非强制的,具体行为取决于底层存储的实现。例如,在 NFS 中,即便使用 PVC(accessModes: [ReadWriteOnce]) 资源,依旧能够在多个节点上使用该资源。但是,如果使用 Rook CephFS StorageClass 存储,则无法在多个节点中使用同个 PVC(accessModes: [ReadWriteOnce]) 资源;
AccessModes is meant to be a reflection of the provider’s, in this case EFS’s, capabilities. It is basically a label to ensure that if a user requests RWX storage via a PVC they will get a RWX PV. Or if they are want RWO storage they may get a RWO or RWX PV. It is not meant for enforcement. It is not enforced by Kubernetes, by design, and cannot be inforced by the driver.
The accessModes are dependent upon the storage provider. For NFS they don’t really do anything different, but a HostPath should use the modes correctly.
参考文献
Configure a Pod to Use a PersistentVolume for Storage | Kubernetes