前言
Volume 提供了十分好的数据长久化计划,不过在可管理性上还有有余。拿后面示例能够看出,要应用 Volume,Pod 必须当时晓得如下信息:
- 以后 Volume 来自来哪里及具体位置 Local、网络。
- 存储卷的类型, 并晓得每种类型卷的配置应用办法, 通过 kubectl explain pods.spec.volumes 能够看到 kubernetes 反对卷的类型十分的多
Pod 通常是由利用的开发人员保护,而 Volume 则通常是由存储系统的管理员保护。开发人员要取得下面的信息:要么询问管理员 要么本人就是管理员。
这样就带来一个治理上的问题:利用开发人员和系统管理员的职责耦合在一起了。如果零碎规模较小或者对于开发环境这样的状况还能够承受。但当集群规模变大,特地是对于生成环境,思考到效率和安全性,这就成了必须要解决的问题。
Kubernetes 给出的解决方案是 PersistentVolume 和 PersistentVolumeClaim。
PersistentVolume (PV) 是内部存储系统中的一块存储空间,由管理员创立和保护。与 Volume 一样,PV 具备持久性,生命周期独立于 Pod。
PersistentVolumeClaim (PVC) 是对 PV 的申请 (Claim)。PVC 通常由普通用户创立和保护。须要为 Pod 调配存储资源时,用户能够创立一个 PVC,指明存储资源的容量大小和拜访模式(比方只读)等信息,Kubernetes 会查找并提供满足条件的 PV。
有了 PersistentVolumeClaim,用户只须要通知 Kubernetes 须要什么样的存储资源,而不用关怀真正的空间从哪里调配,如何拜访等底层细节信息。这些 Storage Provider 的底层信息交给管理员来解决,只有管理员才应该关怀创立 PersistentVolume 的细节信息。
PVC 和 PV 简介
- 是由管理员设置的存储,它是群集的一部分。就像节点是集群中的资源一样,PV 也是集群中的资源。PV 是 Volume 之类的卷插件,但具备独立于应用 PV 的 Pod 的生命周期。此 API 对象蕴含存储实现的细节,即 NFS、iSCSI 或特定于云供应商的存储系统
- PV、PVC: 将存储生产,存储创立的职能拆散开来,
- PV: Persistent Volume,长久卷,可被 PVC 绑定; 而 PV 肯定要与某个真正的存储空间 (个别是网络存储服务上的存储空间) 对应起来,能力真正存储数据。由集群管理员负责管理。集群级别资源; 将真正的存储设备上的一段存储空间形象成的 k8s 的对象
- PVC: Persistent Volume Claim 长久卷申请,简称 PVC;k8s 上规范的资源类型之一; 名称空间级别; 由用户定义出存储生产需要,而后依据需要条件与现有各 PV 进行匹配检测,找出一个最佳的应用。
Pod 应用这类存储的步骤:
- Admin: 创立好 PV;
- User: 按需创立 PVC,而后创立 Pod,在 Pod 调用 persistentVolumeClaim 类型的存储卷插件调用同一个名称空间的 PVC 资源;
PV 字段介绍:
除了存储卷插件之外,PersistentVolume 资源标准 Spec 字段次要反对嵌套以下几个通用字段,它们用于定义 PV 的容量、拜访模式和回收策略等属性
- capacity <map[string]string>: 指定 PV 的容量; 目前 Capacity 仅反对存储容量设定,未来还应该能够指定 IOPS 和吞吐量(throughput)。
- accessModes <[]string>: 指定以后 PV 反对拜访模式; 存储系统反对存取能力大体可分为 ReadWriteOnce(单路读写)、ReadOnlyWlany(多路只读)和 ReadwriteMany(多路读写)三种类型, 某个特定的存储系统可能会反对其中的局部或全副的能力。
- persistentVolumeReclaimPolicy <string> ∶PV 空间被开释时的解决机制; 可用类型仅为 Retain(默认)、Recycle(已废除)或 Delete(k8s 主动发明默认抉择)。目前,仅 nfs 和 hostPath 反对 Recycle 策略,也仅有局部存储系统反对 Delete 策略。
- volumenode <string>: 该 PV 的卷模型,用于指定此存储卷被格式化为文件系统应用还是间接应用裸格局的块设施; 默认值为 Filesystem,仅块设施接口的存储系统反对该性能。
- storageClassName <string>: 以后 PV 所属的 StorageClass 资源的名称,指定的存储类须要当时存在; 默认为空值,即不属于任何存储类。
- mountOptions <string>: 挂载选项组成的列表,例如 ro、soft 和 hard 等。
- nodeAffinity <Object>: 节点亲和性,用于限度可能拜访该 PV 的节点,进而会影响到应用与该 PV 关联的 PVC 的 Pod 的调度后果。
PVC 字段介绍:
定义 PVC 时,用户可通过拜访模式(accessModes)、数据期(dataSource)、存储资源空间需要和限度(resources)、存储类、标签选择器、卷模型和卷名称等匹配规范来筛选集群上的 PV 资源,其中,resources 和 accessModes 是最重的筛选规范。PVC 的 Spec 字段的可嵌套字段有如下几个。
- accessModes <[]string>: PVC 的拜访模式; 它同样反对 RWO、RWX 和 ROX 三种模式;
- dataSrouces <Object>: 用于从指定的数据源复原该 PVC 卷,它目前反对的数据源包含一个当初卷快照对象 (snapshot.storage.k8s.io/VolumeSnapshot)、一个既有 PVC 对象(PersistentVolumeClaim) 或一个既有的用于数据转存的自定义资源对象(resource/object) ;
- resources <Object>: 申明应用的存储空间的最小值和最大值; 目前,PVC 的资源限定仅反对空间大小一个维度;
- selector <Object>: 筛选 PV 时额定应用的标签选择器 (matchLabels) 或匹配条件表达式, (matchExpressions) ;
- storageClassName <string>: 该 PVC 资源附属的存储类资源名称; 指定了存储类资源的 PVC 仅能在同一个存储类下筛选 PV 资源,否则,就只能从所有不具备存储类的 PI 中进行筛选;
- volumeMode <string>∶卷模型,用于指定此卷可被用作文件系统还是裸格局的块设施; 默认值为 Filesystem;
- volumeName <string>: 间接指定要绑定的 PV 咨源的名称
资源标准:
spec:
volumes :
- name <string> #存储卷名称标识,仅可应用 DNS 标签格局的字符,在以后 Pod 中必须唯
vOL_TYPE <0bject> #存储卷插件及具体的指标存储供给方的相干配置
containers:
- name: ...
image: ...
volumeMounts:
- name <string> #要挂载的存储卷的名称,必须匹配存储卷列表中某项的定义
mountPath <string> #容器文件系统上的挂载点门路
readOnly <boolean> #是否挂载为只读模式,默认为“否”subPath <string> #挂载存储卷上的一个子目录至指定的挂载点
subPathExpr <string> #挂载由指定的模式匹配到的存储卷的文件或目录至挂载点
示例 1: NFS 网络存储、PV、PVC、POD 创立与援用
- 1、创立 NFS 服务共享目录
[root@nfs ~]# mkdir /data/redis00{1,2,3,4,5}
[root@nfs ~]# chmod -R 1010 /data/
[root@nfs ~]# cat /etc/exports
/data/redis 192.168.4.0/24(rw)
/data/redis001 192.168.4.0/24(rw)
/data/redis002 192.168.4.0/24(rw)
/data/redis003 192.168.4.0/24(rw)
/data/redis004 192.168.4.0/24(rw)
/data/redis005 192.168.4.0/24(rw)
[root@nfs ~]# systemctl restart nfs
[root@k8s-node1 ~]# showmount -e 192.168.4.100
Export list for 192.168.4.100:
/data/redis005 192.168.4.0/24
/data/redis004 192.168.4.0/24
/data/redis003 192.168.4.0/24
/data/redis002 192.168.4.0/24
/data/redis001 192.168.4.0/24
/data/redis 192.168.4.0/24
2、创立 3 种不同类型的 PV 别离为
- 5G 多路读写
- 10G 多路读
- 1G 单路读写
[root@k8s-master storage]# cat pv-nfs-demo001.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-demo001
spec:
capacity:
storage: 5Gi #容量
volumeMode: Filesystem #文件系统
accessModes:
- ReadWriteMany #多路读写
persistentVolumeReclaimPolicy: Retain #回收策略
mountOptions:
- hard
- nfsvers=4.1
nfs :
path: "/data/redis001"
server: 192.168.4.100 #nfs 存储地址与门路
[root@k8s-master storage]# cat pv-nfs-demo002.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-demo002
spec:
capacity:
storage: 10Gi #容量
volumeMode: Filesystem
accessModes:
- ReadWriteMany #多路读
persistentVolumeReclaimPolicy: Retain
mountOptions:
- hard
- nfsvers=4.1
nfs :
path: "/data/redis002"
server: 192.168.4.100 #nfs 存储地址与门路
[root@k8s-master storage]# cat pv-nfs-demo003.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-demo003
spec:
capacity:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce #单路读写
persistentVolumeReclaimPolicy: Retain
mountOptions:
- hard
- nfsvers=4.1
nfs :
path: "/data/redis002"
server: 192.168.4.100
[root@k8s-master storage]# kubectl apply -f pv-nfs-demo001.yaml -f pv-nfs-demo002.yaml -f pv-nfs-demo003.yaml #创立 3 个不同属性的 PV 卷
persistentvolume/pv-nfs-demo001 created
persistentvolume/pv-nfs-demo002 created
persistentvolume/pv-nfs-demo003 created
[root@k8s-master storage]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-demo001 5Gi(容量) RWX(多路读写) Retain(回收策略) Available 33s
pv-nfs-demo002 10Gi RWX Retain Available 33s
pv-nfs-demo003 1Gi RWO(单路读写) Retain Available
3、创立 2 个不同属性 PVC 需要
- 3G-10G 多路读写
- 2G-5G 单路读写
[root@k8s-master storage]# cat pvc-demo-0001.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo-0001
namespace: default
spec:
accessModes: ["ReadWriteMany"] #多路读写
volumeMode: Filesystem
resources:
requests:
storage: 3Gi #最小容量
limits:
storage: 10Gi #最大容量
[root@k8s-master storage]# cat pvc-demo-0002.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-demo-0002
spec:
accessModes: ["ReadWriteOnce"] #单路读写
volumeMode: Filesystem
resources:
requests:
storage: 2Gi #要求最小容量 2G-5G 之间
limits:
storage: 5Gi #要求最大容量
selector: #应用标签匹配
matchLabels:
usedof : "redisdata"
- PVC 依据须要会主动与 PV 匹配并绑定
[root@k8s-master storage]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-demo-0001 Bound pv-nfs-demo001 5Gi RWX 13h
pvc-demo-0002 Pending 2m40s #没有匹配卷 挂起
[root@k8s-master storage]# kubectl describe pvc pvc-demo-0002
Name: pvc-demo-0002
Namespace: default
StorageClass:
Status: Pending
Volume:
Labels: <none>
Annotations: <none>
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Mounted By: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal FailedBinding 7s (x3 over 34s) persistentvolume-controller no persistent volumes available for this claim and no storage class is set #没有匹配标签的 PV 挂起
[root@k8s-master storage]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-demo001 5Gi RWX Retain Bound default/pvc-demo-0001 13h
pv-nfs-demo002 10Gi RWX Retain Available 13h
pv-nfs-demo003 1Gi RWO Retain Available 13h
- 4、Pod 的创立绑定 PVC
[root@k8s-master storage]# cat volumes-pvc-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: volumes-pvc-demo
namespace: default
spec:
containers:
- name: redis
image: redis:alpine
imagePullPolicy: IfNotPresent
securityContext:
runAsUser: 1010
ports:
- containerPort: 6379
name: redisport
volumeMounts:
- mountPath: /data
name: redis-rbd-vol
volumes:
- name: redis-rbd-vol
persistentVolumeClaim:
claimName: pvc-demo-0001 #挂载 PVC 指定名称
[root@k8s-master storage]# kubectl apply -f volumes-pvc-demo.yaml
pod/volumes-pvc-demo created
[root@k8s-master storage]# kubectl get pod
NAME READY STATUS RESTARTS AGE
centos-deployment-66d8cd5f8b-fkhft 1/1 Running 0 27h
my-grafana-7d788c5479-8bx6k 1/1 Running 0 4h24m
volumes-nfs-demo 1/1 Running 0 4h25m
volumes-pvc-demo 1/1 Running 0 4s
[root@k8s-master ~]# kubectl get pvc #能够看到 PVC 绑定已胜利
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-demo-0001 Bound pv-nfs-demo001 5Gi RWX 52m
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
centos-deployment-66d8cd5f8b-fkhft 1/1 Running 0 27h
my-grafana-7d788c5479-8bx6k 1/1 Running 0 5h19m
volumes-hostpath-demo 1/1 Running 0 48m
volumes-nfs-demo 1/1 Running 0 5h20m
volumes-pvc-demo 1/1 Running 0 4m
[root@k8s-master ~]# kubectl exec volumes-pvc-demo -it -- /bin/sh #挂载 PVC 写入数据
/data $ redis-cli
127.0.0.1:6379> set mykey2 "taobao"
OK
127.0.0.1:6379> get mykey2
"taobao"
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> exit
/data $ ls
dump.rdb
/data $
[root@nfs redis001]# ls /data/redis001/ #nfs 服务器上查看数据
dump.rdb
示例 2: 通过 PVC 实现共享数据
这里只是演示不同的 Pod 能够挂载同一个 PVC 共享数据, 但对于一些有状态的服务, 数据的实时读写和服务、存储类型都有关系
[root@k8s-master storage]# cat volumes-pvc2.demo.yaml #新建 redis 2
apiVersion: v1
kind: Pod
metadata:
name: volumes-pvc2-demo
namespace: default
spec:
containers:
- name: redis
image: redis:alpine
imagePullPolicy: IfNotPresent
securityContext:
runAsUser: 1010
ports:
- containerPort: 6379
name: redisport
volumeMounts:
- mountPath: /data
name: redis-rbd-vol
volumes:
- name: redis-rbd-vol
persistentVolumeClaim:
claimName: pvc-demo-0001 #应用雷同的 PVC
[root@k8s-master storage]# kubectl exec volumes-pvc2-demo -it -- /bin/sh #在别一个 Pod 上查看数据
/data $ redis-cli
127.0.0.1:6379> get mykey
"baidu.com"
127.0.0.1:6379> exit
/data $ exit
示例 3: 删除 Pod、PVC、PV 后复原数据
- 所有数据的复原都须要回收策略为 Retain 的状况下
- 删除 Pod 及 PVC
[root@k8s-master storage]# kubectl delete pod volumes-pvc-demo
pod "volumes-pvc-demo" deleted
[root@k8s-master storage]# kubectl delete pod volumes-pvc2-demo #删除之前两个 Pod
pod "volumes-pvc2-demo" deleted
[root@k8s-master storage]# kubectl get pvc #删除 Pod 不影响 PVC 及数据
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-demo-0001 Bound pv-nfs-demo001 5Gi RWX 14h
pvc-demo-0002 Pending 33m
[root@k8s-master storage]# kubectl delete pvc pvc-demo-0001 #删除 PVC
persistentvolumeclaim "pvc-demo-0001" deleted
[root@k8s-master storage]# kubectl get pv #因为回收策略为 Retain 所以 PV 不会主动删除 变为 Released 状态
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-demo001 5Gi RWX Retain Released default/pvc-demo-0001 14h
pv-nfs-demo002 10Gi RWX Retain Available 14h
pv-nfs-demo003 1Gi RWO Retain Available 14h
[root@k8s-master storage]# kubectl apply -f pvc-demo-0001.yaml #最次创立 PVC 看是否能绑定原来的 PV
persistentvolumeclaim/pvc-demo-0001 created
[root@k8s-master storage]# kubectl get pv #绑定到的新的 PV 原来的 PV 还是为 Released 状态
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-demo001 5Gi RWX Retain Released default/pvc-demo-0001 14h
pv-nfs-demo002 10Gi RWX Retain Bound default/pvc-demo-0001 14h
pv-nfs-demo003 1Gi RWO Retain Available 14h
[root@k8s-master storage]# kubectl delete -f pvc-demo-0001.yaml #删除 Pod
persistentvolumeclaim "pvc-demo-0001" deleted
[root@k8s-master storage]# kubectl get pv #当初两个 PV 都为 Released
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-demo001 5Gi RWX Retain Released default/pvc-demo-0001 14h
pv-nfs-demo002 10Gi RWX Retain Released default/pvc-demo-0001 14h
pv-nfs-demo003 1Gi RWO Retain Available 14h
- 批改 PVC 让 PVC 复原为 Available 状态 从新绑定
[root@k8s-master storage]# kubectl edit pv pv-nfs-demo001 #批改 PV 让状态变为 Available 能够从新绑定
...
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 5Gi
claimRef: #删除 claimRef: 字段所有内容
apiVersion: v1
kind: PersistentVolumeClaim
name: pvc-demo-0001
namespace: default
resourceVersion: "6371169"
uid: f8a9ba0b-e15e-44ea-bccf-6b40f0d46390
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /data/redis001
server: 192.168.4.100
persistentVolumeReclaimPolicy: Retain
volumeMode: Filesystem
status:
phase: Released
...
[root@k8s-master storage]# kubectl edit pv pv-nfs-demo002 #pv-nfs-demo002 也做雷同操作
persistentvolume/pv-nfs-demo002 edited
[root@k8s-master storage]# kubectl get pv #复原 Available 状态
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-demo001 5Gi RWX Retain Available 14h
pv-nfs-demo002 10Gi RWX Retain Available 14h
pv-nfs-demo003 1Gi RWO Retain Available
14h
[root@k8s-master storage]# kubectl apply -f pvc-demo-0001.yaml #新建 PVC
persistentvolumeclaim/pvc-demo-0001 created
[root@k8s-master storage]# kubectl get pv #查看 PV 绑定到原来的 PV 胜利
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-demo001 5Gi RWX Retain Bound default/pvc-demo-0001 14h
pv-nfs-demo002 10Gi RWX Retain Available 14h
pv-nfs-demo003 1Gi RWO Retain Available 14h
[root@k8s-master storage]# kubectl apply -f volumes-pvc-demo.yaml #从新创立 Pod
pod/volumes-pvc-demo created
[root@k8s-master storage]# kubectl get pod
NAME READY STATUS RESTARTS AGE
centos-deployment-66d8cd5f8b-fkhft 1/1 Running 0 41h
my-grafana-7d788c5479-8bx6k 1/1 Running 0 19h
volumes-hostpath-demo 1/1 Running 0 14h
volumes-nfs-demo 1/1 Running 0 19h
volumes-pvc-demo 1/1 Running 0 3s
[root@k8s-master storage]# kubectl exec volumes-pvc-demo -it -- /bin/sh #查看之前数据
/data $ ls
dump.rdb
/data $ redis-cli
127.0.0.1:6379> get mykey2
"taobao"
127.0.0.1:6379> exit
/data $ exit
[root@k8s-master storage]#
[root@k8s-master storage]# kubectl delete pod volumes-pvc-demo #删除 Pod
pod "volumes-pvc-demo" deleted
[root@k8s-master storage]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pvc-demo-0001 Bound pv-nfs-demo001 5Gi RWX 6m34s
pvc-demo-0002 Pending 79m
[root@k8s-master storage]# kubectl delete pvc pvc-demo-0001 #删除 PVC
persistentvolumeclaim "pvc-demo-0001" deleted
[root@k8s-master storage]# kubectl delete pv pv-nfs-demo001 #删除 PV
persistentvolume "pv-nfs-demo001" deleted
[root@k8s-master storage]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs-demo002 10Gi RWX Retain Available 14h
pv-nfs-demo003 1Gi RWO Retain Available 14h
[root@nfs ~]# ls /data/redis001/ #NFS 服务查看数据文件 仍然存在
dump.rdb
PVC、PV 总结:
- 删除 Pod、PVC 在回收策略为 Retain 状况下, 数据不会失落
- PV 的删除数据是否会失落与存储类型无关, 上述测试的 NFS 不会失落不代表所有的 PV 删除都不会失落,PV 删除需谨慎