官方文档: Persistent Volumes
PersistentVolumes
与管理计算实例相比,管理存储是一个明显的问题。PersistentVolume 子系统为管理员和用户提供了一个 API,该 API 从如何使用存储中抽象出如何提供存储的详细信息。为此,我们引入了两个新的 API 资源: PV(PersistentVolume) 和 PVC(PersistentVolumeClaim)
PersistentVolume 和 PersistentVolumeClaim
PersistentVolume(PV)是集群中的一块存储,由管理员提供或使用存储类动态提供。它是集群中的资源,就像节点是集群资源一样。PV 是类似于 Volumes 的卷插件,但是其生命周期与使用 PV 的任何单个 Pod 无关。此 API 对象捕获 NFS,iSCSI 或特定于云提供商的存储系统的存储实现的详细信息。
PersistentVolumeClaim(PVC) 是用户存储的请求。它类似于 Pod。Pod 会消耗节点资源,PVC 会消耗 PV 资源。Pod 可以请求特定级别的资源(CPU 和内存)。PVC 可以请求特定的容量大小和访问模式(例如,可以将它们挂载为 ReadWriteOnce,ReadOnlyMany 或 ReadWriteMany)。
目前 PV 的提供方式有两种:静态或动态。静态 PV 由管理员提供,动态 PV 无需提前创建,只需要指定 PVC 的 StorageClass 即可。
回收策略
当用户使用完卷时,可以从 API 中删除 PVC 对象,从而允许回收资源。回收策略会告诉 PV 如何处理该卷,目前对卷的策略可以是保留,回收或删除。如下
- Retain: 保留,该策略允许手动回收资源,当删除 PVC 时,PV 仍然存在,volume 被视为已释放,但是它尚不适用于其他 claim,因为前一个 Claim 的数据还保留在卷上。管理员可以手动回收卷;
- Recycle: 回收,如果 volume 插件支持,Recycle 策略会对卷执行
rm -rf /theVolume/*
清理该 PV,并使其可用于下一个新的 PVC,但是本策略不建议使用,建议使用动态配置; - Delete: 删除,如果 Volume 插件支持,删除 PVC 时会同时删除 PV,动态卷默认为 Delete。
创建 PV
在使用持久化时,需要先创建 PV,然后再创建 PVC,PVC 会和匹配的 PV 进行绑定,然后 Pod 即可使用该存储。
创建一个基于 nfs 的PV, nfs-pv.yaml 文件内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0001
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs-slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /data/nfs/k8s-pv
server: 192.168.200.26参数说明:
- capacity: 容量
- accessModes: 访问模式,包括以下三种:
- ReadWriteOnce: 可以被单节点以读写模式挂载,命令行中可以被缩写为 RWO;
- ReadOnlyMany: 可以被多个节点以只读模式挂载,命令行中可以被缩写为 ROX;
- ReadWriteMany: 可以被多个节点以读写模式挂载,命令行中可以被缩写为 RWX;
- storageClassName: PV 的类,一个特定类型的 PV 只能绑定到特定类别的 PVC。
- persistentVolumeReclaimPolicy: 回收策略;
- mountOptions: 非必须项,新版本中已弃用;
- nfs: NFS 服务配置。包括以下两个选项:
- path: NFS 上的目录;
- server: NFS 的 IP 地址;
创建一个基于 hostPath 的 PV,hostpath-pv.yaml 文件内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14apiVersion: v1
kind: PersistentVolume
metadata:
name: hostpath-pv0001
labels:
type: local
spec:
storageClassName: hostpath-slow
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"执行如下命令,创建 pv
1
2
3
4
5# kubectl create -f nfs-pv.yaml
persistentvolume/pv0001 created
# kubectl create -f hostpath-pv.yaml
persistentvolume/hostpath-pv0001 created查看 pv 的状态
1
2
3
4# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
hostpath-pv0001 10Gi RWO Retain Available hostpath-slow 100s
pv0001 5Gi RWO Recycle Available nfs-slow 102mPV 的状态说明
- Available: 可用,没有被 PVC 绑定的空间资源;
- Bound: 已绑定,已经被 PVC 绑定;
- Released: 已释放,PVC 被删除,但是资源还未被重新使用;
- Failed: 失败,自动回收失败
创建 PVC
创建 PVC 需要注意的是,各个方面都符合要求的 PVC 才能和 PV 进行绑定,比如 accessModes,storageClassName,volumeMode 都需要相同才能进行绑定。
基于上述的 hostPath 的 PV 可以使用以下 PVC 进行绑定,storage 可以比 PV 小,但不能比 PV 大:
1
2
3
4
5
6
7
8
9
10
11
12
13
14apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: hostpath-pv-claim
spec:
storageClassName: hostpath-slow
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
selector:
matchLabels:
type: local基于 NFS 的 PV 可以创建如下 PVC 进行绑定
1
2
3
4
5
6
7
8
9
10
11apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
storageClassName: nfs-slow
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi然后创建一个 Deploy 指定 volumes,即可使用这个 PV,如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
generation: 1
labels:
app: nginx
name: nginx
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- name: hostpath-pvc-volume # 挂载的卷的名称
mountPath: /mnt # 挂载到容器中的路径
- name: nfs-pvc-volume # 挂载的卷的名称
mountPath: /opt # 挂载到容器中的路径
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: hostpath-pvc-volume # 挂载后的卷名称
persistentVolumeClaim:
claimName: hostpath-pv-claim # 需要挂载 PVC 的名称
- name: nfs-pvc-volume # 挂载后的卷名称
persistentVolumeClaim:
claimName: nfs-pvc # 需要挂载 PVC 的名称claimName 需要和上述定义的 PVC 的名称 hostpath-pv-claim 和 nfs-pvc 一致。
清理步骤
删除 Pod,PersistentVolumeClaim 和 PersistentVolume 的步骤如下:
先删除使用 PVC 的 Pod,或者 Deploy 或 DS
1
2# kubectl delete deploy nginx
deployment.apps "nginx" deleted删除 pvc
1
2
3
4
5# kubectl delete pvc hostpath-pv-claim
persistentvolumeclaim "hostpath-pv-claim" deleted
# kubectl delete pvc nfs-pvc
persistentvolumeclaim "nfs-pvc" deleted删除 PV
1
2# kubectl delete pv hostpath-pv0001
persistentvolume "hostpath-pv0001" deleted
创建 PVC 需要注意的事项
很多情况下,创建 PVC 之后,一只绑定不上 PV,原因可能如下:
- PVC 申请的空间大于 PV 的大小;
- PVC 的 storageClassName 没有和 pv 的一致;
- PVC 的 accessModes 和 PV 的一致;
创建挂载了 PVC 的 Pod 之后,一直处于 Pending 状态,原因可能如下:
- PVC 没有创建成功,或者被创建;
- PVC 和 Pod 不在同一个 Namespace 中;
StorageClass
官方文档地址 Storage Classes
StorageClass 为管理员提供了一种描述存储 “类” 的方法,可以满足用户不同的服务质量级别,备份策略和任意策略要求的存储需求,一般动态 PV 都会通过 StorageClass 来定义。
每个 StorageClass 包含字段 provisioner,parameters 和 reclaimPolicy,StorageClass 对象的名称很重要,管理员在首次创建 StorageClass 对象时设置的类的名称和其他参数,在被创建对象后无法再更新这些对象。
定义一个 StorageClass 的示例如下:
1 | apiVersion: storage.k8s.io/v1 |
参数说明
Provisioner,用于指定配置 PV 的卷的类型,必须指定此字段,目前支持的卷插件如下表
Volume Plugin Internal Provisioner Config Example AWSElasticBlockStore √ AWS EBS AzureFile √ Azure File AzureDisk √ Azure Disk CephFS - - Cinder √ OpenStack Cinder FC - - FlexVolume - - Flocker √ - GCEPersistentDisk √ GCE PD GlusterFS √ GlusterFS iSCSI - - Quobyte √ Quobyte NFS - - RBD √ Ceph RBD VsphereVolume √ vSphere PortworxVolume √ Portworx Volume ScaleIO √ ScaleIO StorageOS √ StorageOS Local - Local provisioner 不仅限于此处列出的内部 provisioner,还可以运行和指定外部供应商。例如,NFS 不提供内部配置程序,但是可以使用外部配置程序,外部配置方式参考网址: 外部配置方式
ReclaimPolicy,回收策略,可以是 Delete,Retain,默认是 Delete;
MountOptions,通过 StorageClass 动态创建的 PV可以使用 mountOptions 指定挂载参数。如果指定的卷插件不支持指定的挂载选项,就不会被创建成功,因此在设置时需要进行确认;
parameters,PVC 具有描述属于 StorageClass 卷的参数,根据具体情况,取决于 provisioner,可以接受不同类型的参数。比如,type 为 io1 和 特定参数 iopsPerGB 是 EBS 所具有的的。如果省略配置参数,将采用默认值;
allowVolumeExpansion,配置 PV 是否可扩展,设置为 true 时,允许用户通过编辑相应的 PVC 对象来调整卷的大小。当基础 StorageClass 的字段 allowVolumeExpansion 设置为 true 时,以下类型的卷支持卷扩展
Volume type Required Kubernetes version gcePersistentDisk 1.11 awsElasticBlockStore 1.11 Cinder 1.11 GlusterFS 1.11 RBD 1.11 Azure File 1.11 Azure Disk 1.11 Portworx 1.11 FlexVolume 1.13 CSI 1.14(alpha), 1.16(beta)
定义 StorageClass
StorageClass 一般用于定义动态存储卷,只需要在 Pod 上指定 StorageClass 的名字即可自动创建对应的 PV,无需再手工创建。以下为常用的 StorageClass 定义方式
AWS EBS
1
2
3
4
5
6
7
8
9apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "10"
fsType: ext4参数说明:
- type: 类型,可以设置为 io1, gp2, sc1, st1,默认值为 gp2。详细信息可以参考 AWS docs;
- zone: 区域,不建议使用,AWS区域。如果既未指定区域又未指定区域,则通常会在 Kubernetes 集群具有节点的所有活动区域之间进行卷巡查。 zone 和zones 参数不能同时使用;
- zones: 区域,不建议使用。以逗号分隔的AWS区域列表。如果既未指定区域又未指定区域,则通常会在Kubernetes集群具有节点的所有活动区域之间进行卷巡查。 zone 和 zones 参数不能同时使用;
- iopsPerGB: 仅适用于 io1 卷。每秒每GiB的 I/O 操作数。 AWS 卷插件将此值乘以请求卷的大小即可计算出该卷的IOPS,并将其上限为 20,000 IOPS(AWS支持的最大值,请参阅AWS文档)。此处应为字符串,即 “10”,而不是 10;
- fsType: 文件类型,kubernetes 支持的 fsType。默认值为 “ext4”;
- encrypted: 加密,表示是否加密 EBS 卷。有效值为 “true” 或 “false”。这里需要一个字符串,即 “true” 而不是 true;
- kmsKeyId:可选。加密卷时使用密钥的完整 Amazon 资源名称。如果未提供任何内容但加密为 true,则 AWS 会生成一个密钥。有关有效的 ARN 值,请参阅AWS文档。
注意,不建议使用 zone 和 zones 参数,可以使用 allowedTopologies 代替;
GCE PD
1 | apiVersion: storage.k8s.io/v1 |