持久卷详解
持久卷(PersistentVolume,PV):持久卷申领 (PersistentVolumeClaim, PVC):该保护机制适用于PV和PVC两种资源:删除PV资源对象,此时与该PV关联的某些外部存储提供商(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 删除之后仍然存在根据情况,手动清除所关联的存储资产上的数据。手工删除后端存储资产。如果希望重用该存
持久卷详解
一.介绍
为了能够屏蔽底层存储实现的细节,让用户方便使用及管理员方便管理,引入了两个新的 API 资源:PersistentVolume 和 PersistentVolumeClaim
持久卷(PersistentVolume,PV):
- 是对存储资源的抽象,将存储定义为一种容器应用可以使用的资源,由管理员事先供应,或者 使用存储类(Storage Class)来动态供应
- 持久卷是集群资源,就像节点也是集群资源一样, 也和普通Volume一样 使用 卷插件来实现的
- 拥有独立于任何使用 PV 的 Pod 的生命周期
持久卷申领 (PersistentVolumeClaim, PVC):
- 是用户对存储资源的一个申请。就像Pod消耗Node的资源一样,PVC消耗PV的资源。
- PVC可以申请存储空间的大小(Size)和访问模式(例如ReadWriteOnce、ReadOnlyMany或ReadWriteMany)
二.PV和PVC的生命周期
1.资源供应
Kubernetes支持两种资源供应模式:静态模式(Static)和动态模式(Dynamic),资源供应的结果就是将合适的PV与 PVC成功绑定
静态模式:
集群管理员创建若干 PV 卷。这些卷对象带有真实存储的细节信息,并且对集群 用户可用(可见)。
PV 卷对象存在于 Kubernetes API 中,可供用户消费(使用)
动态模式:
集群管理员无需预先创建PV,而是通过StorageClass的设置对后端存储资源进行描述,标记存储的类型和特性。
用户通过创建PVC对存储类型进行申请,系统将自动完成PV的创建和PVC的绑定。
如果PVC声明的Class为空“”,则说明PVC不用动态模式、另外Kubernetes支持设置集群范围内默认的StorageClass设置,通过kuber-apiserver开启准入控制器DefaultStorageClass,可以为用户创建PVC设置一个默认的存储类StorageClass。
2.资源绑定
在用户定义好PVC之后,系统将根据PVC对存储资源的请求(存储空间和访问模式),在已经存在的PV中选择一个满足PVC要求的PV,一旦找到,就将该PV和用户定义的PVC绑定,用户的应用就可以使用这个PVC了。
PV一旦与 某个PVC上完成绑定,就会被这个PVC独占,不能再与其它PVC绑定了,PVC与PV的绑定关系是一对一的,不会存在一对多的情况。
如果找不到匹配的 PV 卷,PVC就会无限期处于Pending状态,当与之匹配的 PV 卷可用时,PVC 申领会被绑定。
例如,即使某集群上供应了很多 50 Gi 大小的 PV 卷,也无法与请求 100 Gi 大小的存储的 PVC 匹配。当新的 100 Gi PV 卷被加入到集群时,该 PVC 才有可能被绑定。
如果PVC申请的存储空间比PV拥有的空间少,则整个PV的空间都能为PVC所用,可能造成资源浪费。
3.资源使用
Pod 将 PVC 当做存储卷来使用
Pod需要使用存储资源时,需要在
Volume
的定义中引用PVC类型的卷,将PVC挂载到容器内的某个路径下进行使用。Volume的类型的字段为“persistentVolumeClaim”
Pod在挂载PVC后,就能使用存储资源了。同一个PVC可以被多个Pod同时挂载使用,在这种情况下,应用程序应该处理好多个进程访问同一个存储的问题。
保护使用中的存储对象
存储资源(PV、PVC)相对于容器应用(Pod)都是独立管理的资源,可以单独删除。
在做删除资源操作的时候,系统会检测存储资源当前是否正在被使用,如果仍被使用,则相关资源的删除将被推迟,直到没有被使用才会执行删除操作,这样可以确保资源仍被使用的情况下不会被直接删除而导致数据丢失。这个机制被称为使用中的存储对象的保护机制(Storage Object in Use Protection)
Note: 当使用某 PVC 的 Pod 对象仍然存在时,认为该 PVC 仍被此 Pod 使用。
该保护机制适用于PV和PVC两种资源:
- (1) 对于PVC的删除操作将等到使用它的Pod被删除之后在执行
- (2) 对于PV的删除操作将等到绑定它的PVC被删除之后再执行
4.资源回收
当用户不再使用其存储卷时,他们可以从 API 中将 PVC 对象删除,从而允许 该资源被回收再利用。
PersistentVolume 对象的回收策略告诉集群,当其被 从申领中释放时如何处理该数据卷。 目前,数据卷可以被 Retained(保留)、Recycled(回收)或 Deleted(删除)。
保留(Retain)
Retain策略表示在删除PVC之后,与之绑定的PV不会被删除,仅被标记为已释放(released)。
PV中的数据仍然存在,在清空之前不能被新的PVC使用,需要管理员收到清理之后才能继续使用,清理步骤:
-
删除PV资源对象,此时与该PV关联的某些外部存储提供商(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 删除之后仍然存在
-
根据情况,手动清除所关联的存储资产上的数据。
-
手工删除后端存储资产。
-
如果希望重用该存储资产,则可以创建一个新的PV与之管理
删除(Delete)
对于支持
Delete
回收策略的卷插件,删除动作会将 PersistentVolume 对象从 Kubernetes 中移除,同时也会从外部基础设施(如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)中移除所关联的存储资产。动态供应的卷会继承其 StorageClass 中设置的回收策略,该策略默认 为
Delete
。管理员需要根据用户的期望来配置 StorageClass;否则 PV 卷被创建之后必须要被 编辑或者修补。参阅更改 PV 卷的回收策略.
回收(Recycle)
目前只有HostPort和NFS类型的Volume支持Recycle策略,其实机制为运行 rm -rf /thevolume/*命令,删除Volume目录下的全部文件,使得PV可以继续被新的PVC使用。
此外管理员可以创建一个专门用于回收HostPort 和 NFS类型的PV数据的自定义Pod来实现数据清理工作。
这个Pod的YAML配置文件所在的目录需要通过kube-controller-manager服务的启动参数–pv-recucler-pod-template-filepath-hostpath或–pv-recycle-pod-template-filepath-nfs进行设置(还可以设置相应的timeout参数)
apiVersion: v1
kind: Pod
metadata:
name: pv-recycle
namespace: default
spec:
restartPolicy: Never
volume:
- name: vol
hostPath:
path: <some-path>
containers:
- name: pv-recycler
image: busybox
command: ["/bin/sh", "-c", "test -r /scrub && rm -rf /scrub/..?*/scrub/./[!.]*/scrub* && test -z\"$(ls /scrub\)" || exit 1"]
volumeMounts:
- name: vol
mountPath: /scrub
经过这个自定义的Pod的设置,系统将通过创建这个Pod来完成PV的数据清理工作,完成PV的回收。
但是需要注意的是Recycle策略已被弃用,推荐以动态供应机制管理容器所需的存储资源。
5.资源状态
一个PV的生命周期中,有4个不同的阶段:
- Available(可用): 表示可用状态,还未被任何 PVC 绑定
- Bound(已绑定): 表示 PV 已经被 PVC 绑定
- Released(已释放): 表示 PVC 被删除,但是资源还未被集群重新声明
- Failed(失败): 表示该 PV 的自动回收失败
三.创建持久卷
资源清单:
下面是一个持久卷的声明 YAML 配置文件。
在此配置文件中要求提供
5Gi
的存储空间,存储模式为Filesystem
,访问模式是ReadWriteOnce
,通过Recycle
回收策略进行持久化存储卷的回收,指定存储类为slow
,使用nfs
的插件类型。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0001
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /tmp
server: 172.17.0.2
Note: 在集群中使用持久卷存储通常需要一些特定于具体卷类型的辅助程序。 在这个例子中,PersistentVolume 是 NFS 类型的,因此需要辅助程序
/sbin/mount.nfs
来支持挂载 NFS 文件系统。
清单字段解释:
capacity(容量)
每个 PV 卷都有确定的存储容量 ,
storage
后接容量大小
volumeMode(存储卷模式)
针对 PV 持久卷,Kubernetes 支持两种卷模式(
volumeModes
):Filesystem(文件系统)
和Block(块)
。
volumeMode
是一个可选的 API 参数。 如果该参数被省略,默认的卷模式是Filesystem
volumeMode
属性设置为Filesystem
的卷会被 Pod 挂载(Mount) 到某个目录。如果卷的存储来自某块设备而该设备目前为空,Kuberneretes 会在第一次挂载卷之前 在设备上创建文件系统。
将
volumeMode
设置为Block
,以便将卷作为原始块设备来使用。这类卷以块设备的方式交给 Pod 使用,其上没有任何文件系统。 这种模式对于为 Pod 提供一种使用最快可能方式来访问卷而言很有帮助,Pod 和 卷之间不存在文件系统层。另外,Pod 中运行的应用必须知道如何处理原始块设备。 关于如何在 Pod 中使用
volumeMode: Block
的卷,可参阅 原始块卷支持。
accessModes(访问模式)
PersistentVolume 卷可以用资源提供者所支持的任何方式挂载到宿主系统上。
提供者(驱动)的能力不同,每个 PV 卷的访问模式都会设置为 对应卷所支持的模式值。
例如,NFS 可以支持多个读写客户,但是某个特定的 NFS PV 卷可能在服务器 上以只读的方式导出。每个 PV 卷都会获得自身的访问模式集合,描述的是 特定 PV 卷的能力。
访问模式有:
- ReadWriteOnce:
- 读写权限,只能被单个节点挂载
- 也允许运行在同一节点上的多个 Pod 访问卷
- ReadOnlyMany
- 只读权限,可以被多个节点挂载
- ReadWriteMany
- 读写权限,可以被多个节点挂载
- ReadWriteOncePod
- 读写权限,只能被单个pod挂载
- 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用ReadWriteOncePod 访问模式。
- 这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。
在命令行接口(CLI)中,访问模式也使用以下缩写形式:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
- RWOP - ReadWriteOncePod
重要提醒! 每个卷同一时刻只能以一种访问模式挂载,即使该卷能够支持 多种访问模式。
例如,一个 GCEPersistentDisk 卷可以被某节点以 ReadWriteOnce 模式挂载,或者被多个节点以 ReadOnlyMany 模式挂载,但不可以同时以两种模式 挂载。
persistentVolumeReclaimPolicy(回收策略)
当PV不再被使用了之后,对其的处理方式。目前支持三种策略:
- Retain(保留): 保留数据,需要管理员手工清理数据
- Recycle(回收): 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*
- Delete (删除): 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务
目前,仅 NFS 和 HostPath 支持回收(Recycle)
AWS EBS、GCE PD、Azure Disk 和 Cinder 卷都支持删除(Delete)
storageClassName(存储类)
每个 PV 可以属于某个类(Class),通过将其
storageClassName
属性设置为某个 StorageClass 的名称来指定
- 具有特定类别的PV只能与请求了该类别的PVC进行绑定
- 未设定类别的PV则只能与不请求任何类别的PVC进行绑定
mountOptions(挂在选项)
Kubernetes 管理员可以指定持久卷被挂载到节点上时使用的附加挂载选项
四.持久卷申领
资源清单:
下面是一个名称为
myclaim
的持久卷声明 YAML 配置文件它的访问模式为
ReadWriteOnce
,存储卷模式是Filesystem
,需要的存储空间大小为8Gi
,指定的存储类为slow
,并设置了标签选择器和匹配表达式。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 8Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: environment, operator: In, values: [dev]}
清单字段解释:
accessModes(访问模式)
申领在请求具有特定访问模式的存储时,使用与卷相同的访问模式约定。
volumeMode(存储卷模式)
申领使用与卷相同的约定来表明是将卷作为文件系统还是块设备来使用
resources(资源)
申领和 Pod 一样,也可以请求特定数量的资源。在这个上下文中,请求的资源是存储。 卷和申领都使用相同的 资源模型。
selector (选择运算符)
申领可以设置标签选择算符 来进一步过滤卷集合。只有标签与选择算符相匹配的卷能够绑定到申领上。
选择算符包含两个字段:
matchLabels
- 卷必须包含带有此值的标签matchExpressions
- 通过设定键(key)、值列表和操作符(operator) 来构造的需求。合法的操作符有 In、NotIn、Exists 和 DoesNotExist。
来自
matchLabels
和matchExpressions
的所有需求都按逻辑与的方式组合在一起。 这些需求都必须被满足才被视为匹配
storageClassName(存储类)
申领可以通过为
storageClassName
属性设置 StorageClass 的名称来请求特定的存储类。只有所请求的类的 PV 卷,即
storageClassName
值与 PVC 设置相同的 PV 卷, 才能绑定到 PVC 申领。
PVC 申领不必一定要请求某个类。如果 PVC 的
storageClassName
属性值设置为""
, 则被视为要请求的是没有设置存储类的 PV 卷,因此这一 PVC 申领只能绑定到未设置 存储类的 PV 卷(未设置注解或者注解值为""
的 PersistentVolume(PV)对象在系统中不会被删除,因为这样做可能会引起数据丢失。 未设置storageClassName
的 PVC 与此大不相同,也会被集群作不同处理。 具体筛查方式取决于DefaultStorageClass
准入控制器插件 是否被启用。
- 如果准入控制器插件被启用,则管理员可以设置一个默认的 StorageClass。 所有未设置
storageClassName
的 PVC 都只能绑定到隶属于默认存储类的 PV 卷。 设置默认 StorageClass 的工作是通过将对应 StorageClass 对象的注解storageclass.kubernetes.io/is-default-class
赋值为true
来完成的。 如果管理员未设置默认存储类,集群对 PVC 创建的处理方式与未启用准入控制器插件 时相同。如果设定的默认存储类不止一个,准入控制插件会禁止所有创建 PVC 操作。 - 如果准入控制器插件被关闭,则不存在默认 StorageClass 的说法。 所有未设置
storageClassName
的 PVC 都只能绑定到未设置存储类的 PV 卷。 在这种情况下,未设置storageClassName
的 PVC 与storageClassName
设置未""
的 PVC 的处理方式相同。
Pod使用PVC
Pod 将申领作为卷来使用, 申领必须位于使用它的 Pod 所在的同一名字空间内。
集群在 Pod 的名字空间中查找申领,并使用它来获得申领所使用的 PV 卷。 之后,卷会被挂载到宿主上并挂载到 Pod 中。
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)