存储之PV与PVC
一.概述
PersistentVolume子系统为用户和管理员提供的一组API,将存储如何供应的细节从其如何被使用中抽象出来,为了实现这一点,引入了两个新的API资源
- 持久卷(PersistentVolume,PV):集群中的一块存储,可以由管理员事先供应,或者使用存储类(storage class)来动态供应,持久卷是集群资源,就像节点也是集群资源一样。
- PV持久卷和普通Volume一样,也是使用卷插件来实现的,只是他们拥有独立于任何使用PV的Pod的生命周期
- 对存储资源创建和使用的抽象,使得存储作为集中的资源进行管理
- 持久卷的申领(PersistentVolumeClaim,PVC):表达的是用户对存储的请求。概念上与Pod类似。用户无需关心具体的volume实现细节
- Pod会耗用节点资源,而PVC申领会耗用PV资源
- Pod可以请求特定数量的资源(CPU、内存),同样PVC申领也可以请求特定大小和访问模式
二.静态PV/PVC的创建和使用
创建PV
apiVersion: v1 kind: PersistentVolume metadata: name: game-pv namespace: volume # 指定默认在default命名空间 spec: capacity: storage: 5Gi # 此处的5Gi并不是真正只能使用5Gi,而是为了创建pvc是能匹配到这块pv accessModes: - ReadWriteMany nfs: path: /ifs/kubernetes/game-pv server: 192.168.11.130
# 查案pv状态 [root@k8s-master volume]# kubectl get pv -n volume NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE game-pv 5Gi RWX Retain Available 3s # 查看pv的详细状态 [root@k8s-master volume]# kubectl describe pv game-pv Name: game-pv Labels: <none> Annotations: <none> Finalizers: [kubernetes.io/pv-protection] StorageClass: Status: Available Claim: Reclaim Policy: Retain Access Modes: RWX VolumeMode: Filesystem Capacity: 5Gi Node Affinity: <none> Message: Source: Type: NFS (an NFS mount that lasts the lifetime of a pod) Server: 192.168.11.130 Path: /ifs/kubernetes/game-pv ReadOnly: false Events: <none>
创建pvc
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: wot-pvc namespace: volume spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi # 如果集群中刚好有5Gi的一块pv,则绑定这块 如果刚好没有,但是有8Gi和10Gi的两块pv,则匹配到8Gi这块(向上接近),而不会匹配给10Gi,如果都没有,则会一直处于pending状态
# 查看pvc状态 [root@k8s-master volume]# kubectl get pvc -n volume NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE wot-pvc Bound game-pv 5Gi RWX 10s # 查看pvc的详细状态 [root@k8s-master volume]# kubectl describe pvc wot-pvc -n volume Name: wot-pvc Namespace: volume StorageClass: Status: Bound Volume: game-pv Labels: <none> Annotations: pv.kubernetes.io/bind-completed: yes pv.kubernetes.io/bound-by-controller: yes Finalizers: [kubernetes.io/pvc-protection] Capacity: 5Gi Access Modes: RWX VolumeMode: Filesystem Mounted By: <none> Events: <none> # 此时查看pv,显示已经绑定到刚才创建的pvc了 [root@k8s-master volume]# kubectl get pv -n volume NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE game-pv 5Gi RWX Retain Bound volume/wot-pvc 6m7s
应用程序使用pvc
apiVersion: v1 kind: Pod metadata: name: nginx-pod namespace: volume spec: containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: - mountPath: "/usr/share/nginx/html" name: www volumes: - name: www persistentVolumeClaim: claimName: wot-pvc # pvc的name
三.访问模式
AccessModes是用来对PV进行访问模式的设置,用于描述应用程序对存储资源的访问权限,包括以下几种模式:
- ReadWriteOnce(RWO):读写权限,但只能被单个节点挂载 应用场景:mysql的数据目录持久化
- ReadOnlyMany(ROX):只读权限,可以被多个节点挂载 应用场景:多个应用程序共享配置文件
- ReadWriteMany(RWX):读写权限,可以被多个节点挂载 应用场景:日志目录
四.回收策略
当PVC被删除时,对物理磁盘上的数据的处理策略。目前PV支持三种策略
- Retain(保留):默认策略 表示删除PVC的时候,PV不会一起删除,而是变成Released状态等待管理员手动清理;
- Recycle(回收):表示删除PVC的时候,清除PV中的数据,效果相当于rm -rf /ifs/kubernetes/* 与PVC解绑,Status重新变为Available
- Delete(删除):与PV相连的后端存储同时删除
目前,仅 NFS 和 HostPath 支持回收(Recycle)。 AWS EBS、GCE PD、Azure Disk 和 Cinder 卷都支持删除(Delete)。
Delete的优缺点:
- 优点:实现数据卷的全生命周期管理,应用删除PVC会自动删除后端云盘。能有效避免出现大量闲置云盘没有删除的情况
- 缺点:删除PVC时候一起把后端云盘一起删除,如果不小心误删pvc,会出现后端数据丢失;
Retain的优缺点:
- 优点:后端云盘需要手动清理,所以出现误删的可能性小
- 缺点:没有实现数据卷生命周期管理,常常会造成pvc、pv删除后,后端云盘闲置未清理,长此以往导致大量磁盘浪费
[root@k8s-master ~]# kubectl get pv
NAME CAPACITY ACCESSMODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
game-pv 5Gi RWX Recycle Available 58s
不过需要注意的是,目前只有 NFS 和 HostPath 两种类型支持回收策略。当然一般来说还是设置为 Retain 这种策略保险一点。
四.状态
一个 PV 的生命周期中,可能会处于4中不同的阶段:
- Available(可用):表示可用状态,还未被任何 PVC 绑定
- Bound(已绑定):表示 PV 已经被 PVC 绑定
- Released(已释放):PVC 被删除,但是资源还未被集群重新声明
- Failed(失败): 表示该 PV 的自动回收失败
如果有海量项目,pv维护成本增高,所以引入storage class对象动态供给
五.动态供给(StorageClass)
动态卷供给允许按需创建存储卷。如果没有动态供给,集群管理员必须手动联系他们的存储提供商来创建新的存储卷,然后在kubernetes集群创建PersistentVolume对象来表示这些卷。 动态供给功能消除了集群管理员预先配置存储的需要。相反,他在用户请求时自动供给存储
动态供给的实现基于storage.k8s.ioAPI组中的StorageClass对象。
集群管理员可以根据需求定义多个storageClass对象,每个对象指定一个卷插件(又名provisioner),卷插件向卷供应商提供在创建卷时需要的数据卷信息级相关参数
每个StorageClass都有一个卷插件(Provisioner),用来决定使用哪个卷插件创建PV,该字段必须指定
支持动态供给的卷插件: https://kubernetes.io/zh/docs/concepts/storage/storage-classes/
github上提供了外部制备器的插件:https://github.com/kubernetes-retired/external-storage
六.基于NFS卷插件实现动态供给
部署NFS实现自动创建PV插件:
git clone https://github.com/kubernetes-incubator/external-storage
cd nfs-client/deploy
kubectl apply -f rbac.yaml # 授权访问apiserver
kubectl apply -f deployment.yaml # 部署插件,需修改里面NFS服务器地址与共享目录
kubectl apply -f class.yaml # 创建存储类
创建PVC
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: storageclass-pvc namespace: volume spec: storageClassName: "managed-nfs-storage" # 声明存储类 accessModes: - ReadWriteMany resources: requests: storage: 20Gi
查看存储类 [root@k8s-master volume]# kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE managed-nfs-storage fuseim.pri/ifs Delete Immediate false 33m # pvc中storageClassName就是这个NAME # 查看pv和pvc [root@k8s-master volume]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE 22h pvc-176eb69c-546b-4de6-9e4a-fc3ac6ab0a02 20Gi RWX Delete Bound volume/storageclass-pvc managed-nfs-storage 3m49s # 回收策略是Delete,此策略由class.yaml的archiveOnDelete: "true"定义的 ,true表示删除PVC时,归档pvc后面的物理存储(集群中已删除,实际存储卷上绑我们改名归档了)
[root@k8s-master volume]# kubectl get pvc -n volume NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE storageclass-pvc Bound pvc-176eb69c-546b-4de6-9e4a-fc3ac6ab0a02 20Gi RWX managed-nfs-storage 4m11s
应用程序使用pvc
apiVersion: v1 kind: Pod metadata: name: nginx-storageclass namespace: volume spec: containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: - mountPath: "/usr/share/nginx/html" name: rootdir volumes: - name: rootdir persistentVolumeClaim: claimName: storageclass-pvc
转载请注明出处:http://www.cnblogs.com/lichunke/