耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。
解耦:Decoupling

理想的情况是,在Kubernetes上部署应用程序的开发人员不需要知道底层使用的是哪种存储技术,同理他们也不需要了解应该使用哪些类型的物理服务器来运行pod,与基础设施相关的交互是集群管理员独有的控制领域。

6.5.1 介绍持久卷和持久卷声明

目的:为了使应用能够正常请求存储资源, 同时避免处理基础设施细节。
image.png

研发人员无须向他们的pod中添加特定技术的卷,而是由集群管理员设置底层存储,然后通过Kubernetes API Server创建PersistentVolume(PV)并注册。在创建PersistentVolume时,管理员可以指定其大小和所支持的访问模式。

当集群用户需要在其pod中使用持久化存储时,他们首先创建PersistentVolumeClaim(PVC)清单(manifest),指定所需要的最低容量要求和访问模式,然后用户将PersistentVolumeClaim清单提交给KubernetesAPI服务器,Kubernetes将找到可匹配的PersistentVolume并将其绑定到PersistentVolumeClaim。

PersistentVolumeClaim可以当作pod中的一个卷来使用,其他用户不能使用相同的PersistentVolume,除非先通过删除绑定的PersistentVolumeClaim来释放。

6.5.2 创建pv

image.png

底层存储使用NFS的PV

  1. cd /root/k8s/
  2. cat >mongodb-pv-gcepd.yaml <<'EOF'
  3. apiVersion: v1
  4. kind: PersistentVolume
  5. metadata:
  6. name: mongodb-pv
  7. spec:
  8. capacity:
  9. storage: 1Gi
  10. accessModes:
  11. - ReadWriteOnce
  12. - ReadOnlyMany
  13. persistentVolumeReclaimPolicy: Retain
  14. nfs:
  15. server: 10.0.0.10
  16. path: /data/mongodb-data/
  17. readOnly: false
  18. EOF
  19. kubectl create -f mongodb-pv-gcepd.yaml

image.png

注意: 持久卷不属于任何命名空间(见图6.7), 它跟节点一样是集群层面的资源。
image.png

6.5.3 通过创建PVC来获取PV

声明一个持久卷和创建一个pod是相对独立的过程,因为即使pod被重新调度(切记,重新调度意味着先前的pod被删除并且重建了一个新的pod),我们也希望相同的持久卷声明保持可用。

创建PVC

image.png
当创建好声明,Kubernetes就会找到适当的pv并将其绑定到pvc,pv容量必须足够大以满足pvc的需求,并且卷的访问模式必须包含声明中指定的访模式。在该示例中,声明请求1GiB的存储空间和ReadWriteOnce访问模式。之前创建的pv符合刚刚声明中的这两个条件,所以它被绑定到对应的声明中。

  1. cd /root/k8s/
  2. cat >mongodb-pvc.yaml <<'EOF'
  3. apiVersion: v1
  4. kind: PersistentVolumeClaim
  5. metadata:
  6. name: mongodb-pvc
  7. spec:
  8. resources:
  9. requests:
  10. storage: 1Gi
  11. accessModes:
  12. - ReadWriteOnce
  13. storageClassName: ""
  14. EOF
  15. kubectl create -f mongodb-pvc.yaml

列出PV、PVC

image.png

请留意access mode的简写:

RWO—ReadWriteOnce—Only a single node can mount the volume for reading and writing.
ROX—ReadOnlyMany—Multiple nodes can mount the volume for reading.
RWX—ReadWriteMany—Multiple nodes can mount the volume for both reading and writing.

PV显示被绑定在default/mongodbpvc的声明上,这个default部分是声明所在的namespace(在默认命名空间中创建的声明)。我们之前有提到过PV是集群范围的,因此不能在特定的命名空间中创建,但是PVC又只能在特定的命名空间创建。

6.5.4 在pod 中使用PVC

PV现在已经可用了,除非先释放掉卷,否则没有人可以声明相同的卷。
image.png

  1. cd /root/k8s/
  2. cat >mongodb-pod-pvc.yaml <<'EOF'
  3. apiVersion: v1
  4. kind: Pod
  5. metadata:
  6. name: mongodb
  7. spec:
  8. containers:
  9. - image: 10.0.0.10:5000/luksa/mongo
  10. name: mongodb
  11. volumeMounts:
  12. - name: mongodb-data
  13. mountPath: /data/db
  14. ports:
  15. - containerPort: 27017
  16. protocol: TCP
  17. volumes:
  18. - name: mongodb-data
  19. persistentVolumeClaim:
  20. claimName: mongodb-pvc
  21. EOF
  22. kubectl create -f mongodb-pod-pvc.yaml

现在检查这个pod是否确实在使用相同的PV和底层NFS。通过再次运行MongoDBshell,应该可以看到之前存储的数据。
image.png

6.5.5 了解使用PV和PVC的好处

image.png
考虑如何使用这种间接方法从基础设施获取存储,对于应用程序开发人员(或者集群用户)来说更加简单。这需要额外的步骤来创建PV和VPC,但是研发人员不需要关心底层实际使用的存储技术。
此外,现在可以在许多不同的Kubernetes集群上使用相同的pod和PVC清单,因为它们不涉及任何特定依赖于基础设施的内容。只有PV与底层存储的类型有关。

6.5.6 回收PV

删除pod和PVC之后,再次创建新的PVC,发现pvc处于Pending状态,即还没有绑定PV。
kubectl delete pod mongodb
kubectl delete pvc mongodb-pvc
kubectl create -f mongodb-pvc.yaml
image.png
image.png
PV的状态是Released,而不是Available。原因在于之前已经使用过这个卷,所以它可能包含前一个声明人的数据。如果集群管理员还没来得及清理,那么不应该将这个卷绑定到新的声明中。此外,通过使用相同的持久卷,新的pod可以读取由前一个pod存放的数据,即使声明和pod是在不同的命名空间中创建的。

手动回收PV

pv.spec.persistentVolumeReclaimPolicy:

  • Retain 表示让Kubernetes可以在PV从PVC中释放后仍然能保留pv和数据内容。

据我所知,手动回收持久卷并使其恢复可用的唯一方法是:
删除和重新创建PV资源,同时你可以决定如何处理底层存储的文件:删除或保留。

#回收PV
kubectl delete pod mongodb
kubectl delete pvc mongodb-pvc
kubectl delete pv mongodb-pv

#在NFS服务上清除数据(或保留)
rm -rf /data/mongodb-data/*

自动回收PV

pv.spec.persistentVolumeReclaimPolicy: (表示释放声明后的操作)

  • Recycle 删除卷的内容(执行rm -rf /thevolume/*),并使卷可用于再次声明。通过这种方式,PV可以被不同的PVC和pod反复使用。如图6.9。
  • Delete 同时删除PV和底层存储(数据?)。

注意:部分底层存储不支持所有的回收策略。比如Recycle需要底层卷插件的支持。

提示:可以在现有的PV上更改PV回收策略。比如,如果最初将其设直为Delete 则可以轻松地将其更改为 Retain,以防止丢失有价值的数据。

#修改现有PV回收策略,可以马上生效:
kubectl edit pv mongodb-pv

image.png