Kubernetes — 持久卷
Persistent Volume
介绍
管理存储是管理计算的独特问题。 PersistentVolume子系统为用户和管理员提供了一个API,其中提供了如何从如何使用存储提供存储的详细信息。为此,我们介绍两种新的API资源:PersistentVolume和PersistentVolumeClaim。
PersistentVolume(PV)是由管理员配置的集群中的一段存储。它是集群中的一种资源就像一个节点是一个集群的资源。 PV是类似Volumes的卷插件,但是具有独立于使用PV的任何单个pod的生命周期。该API对象捕获存储的实现细节,即NFS,iSCSI或云提供商特定的存储系统。
PersistentVolumeClaim(PVC)是用户存储的请求。它类似于pod。 Pod消耗节点资源,PVC消耗PV资源。Pods可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,一次读写或者多次只读)。
虽然PersistentVolumeClaims允许用户使用抽象存储资源,但是常见的是,用户需要具有不同属性(如性能)的PersistentVolumes,用于不同的问题。 集群管理员需要能够提供多种彼此不同的PersistentVolumes,而不仅仅是大小和访问模式,而不会使用户了解这些卷的实现细节。 对于这些需求,有一个StorageClass资源。
StorageClass为管理员提供了一种描述他们提供的存储的“类”的方法。 不同的类可能映射到服务质量级别,或备份策略,或者由群集管理员确定的任意策略。 Kubernetes本身对于什么类别代表是不言而喻的。 这个概念有时在其他存储系统中称为“配置文件”。
请参阅详细演练与工作示例。
存储和声明的生命周期
PVs是集群中的资源;PVCs是对这种资源的声明,同时也扮演者对资源声明的检查。PVs和PVCs之前的交互遵循生命周期:供应、绑定、使用中、重新申请。
集群管理员创建多个PV。它们携带可供集群用户使用的真实存储的详细信息。它们存在于Kubernetes API中,可用于消费。
供应(Provisioning)
PVs会以两种方式供应:静态和动态。
静态
集群管理员创建多个PV。 它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API中,可被使用。
动态
当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试为PVC指定动态配置卷。 此配置基于StorageClasses:PVC必须指定一个类,并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置。
绑定(Binding)
当用户创建、或已经创建了一个PersistenVolumenClaim并指定大小和访问类型。Master中的控制循环会检测新的PVC,找到一个匹配的PV(如果可能的话),并将它们绑定在一起。如果一个PV被动态地供应某个PVC,循环将总是把这个PV和该PVC绑定。否则,用户总是至少得到他们要求的内容,但是卷可能超出了要求。一旦绑定,PersistentVolumeClaim绑定是排他的,不管用于绑定它们的模式。
如果匹配的卷不存在,请求将无限期地保持。 随着匹配卷变得可用,请求将被绑定。 例如,提供许多50Gi PV的集群将不匹配要求100Gi的PVC。 当集群中添加100Gi PV时,可以绑定PVC。
使用(使用)
PODs把PVC当做volume使用。集群检查声明以找到绑定的卷并为POD挂载该卷。 对于支持多种访问模式的卷,用户在将其声明用作pod中的卷时指定所需的模式。
一旦用户有声明并且该声明被绑定,绑定的PV属于用户,只要他们需要它。 用户通过在其Pod的卷块中包含persistentVolumeClaim来安排Pods并访问其声明的PV。 请参阅下面的语法详细信息:
kind: Pod
apiVersion: v1
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: dockerfile/nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
回收(Reclaiming)
当用户使用完volume,可以通过请求允许回收资源的API来删除该PVC对象。PersistentVolume的回收策略告诉集群如何处理当声明释放PV后。目前,卷可以被保留,回收或删除。
保留(Retaining)
保留回收策略允许手动回收资源。 当PersistentVolumeClaim被删除时,PersistentVolume仍然存在,并且该卷被认为是“释放的”。 但是,由于上一个声明者的数据仍保留在卷上,因此尚不可用于其他声明。 管理员可以通过以下步骤手动回收卷。
- 删除PersistentVolume。 删除PV后,外部基础设施(如AWS EBS,GCE PD,Azure Disk或Cinder卷)中的关联存储资产仍然存在。
- 相应地手动清理相关存储资产上的数据。
- 手动删除关联的存储资产,或者如果要重用相同的存储资产,请使用存储资产定义创建一个新的PersistentVolume。
回收(Recycling)
如果受相应的卷插件支持,回收将对卷执行基本的擦除(rm -rf / thevolume / *),并使其再次可用于新的声明。 但是,管理员可以使用Kubernetes控制器管理器命令行参数来配置自定义的回收器pod模板,如这里所述。 定制回收站模板必须包含卷规范,如下例所示:
apiVersion: v1
kind: Pod
metadata:
name: pv-recycler-
namespace: default
spec:
restartPolicy: Never
volumes:
- name: vol
hostPath:
path: /any/path/it/will/be/replaced
containers:
- name: pv-recycler
image: "gcr.io/google_containers/busybox"
command: ["/bin/sh", "-c", "test -e /scrub && rm -rf /scrub/..?* /scrub/.[!.]* /scrub/* && test -z \"$(ls -A /scrub)\" || exit 1"]
volumeMounts:
- name: vol
mountPath: /scrub
但是,卷部分中的自定义回收器pod模板中指定的特定路径将替换为正在回收的卷的特定路径。
删除(Deleting)
对于支持“删除回收”策略的卷插件,删除将从Kubernetes中删除PersistentVolume对象,并删除外部基础架构(如AWS EBS,GCE PD,Azure Disk或Cinder卷)中关联的存储资产。 动态配置的卷始终被删除。 如果不希望这样做,目前唯一的选择是在创建PV之后编辑或修补PV。 请参阅更改PersistentVolume的回收策略。
Persistent Volume的类型
- GCEPersistentDisk
- AWSElasticBlockStore
- AzureFile
- AzureDisk
- FC (Fibre Channel)
- FlexVolume
- Flocker
- NFS
- iSCSI
- RBD (Ceph Block Device)
- CephFS
- Cinder (OpenStack block storage)
- Glusterfs
- VsphereVolume
- Quobyte Volumes
- HostPath (single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
- VMware Photon
- Portworx Volumes
- ScaleIO Volumes
- StorageOS
Persistent Volumes
每个PV都包含规格和状态,这是规格和状态。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: slow
nfs:
path: /tmp
server: 172.17.0.2
容量
通常,PV将具有特定的存储容量。这是使用PV的capacity
属性设置的。看到Kubernetes的资源模型,以了解容量使用的单位。
目前,存储大小是唯一可以设置或请求的资源。未来的属性可能包括IOPS,吞吐量等。
访问模式
PersistentVolume可以以资源提供者支持的任何方式安装在主机上。 如下表所示,提供者将具有不同的特性,每个PV的访问模式都被设置为该特定卷支持的特定模式。 例如,NFS可以支持多个读/写客户端,但是特定的NFS PV可能会以只读方式在服务器上导出。 每个PV都有自己的一组访问模式来描述具体的PV功能。
访问模式:
- ReadWriteOnce - 卷可以由单个节点作为读写装载
- ReadOnlyMany - 许多节点可以只读容量
- ReadWriteMany - 卷可以通过许多节点的读写装载
在CLI中,访问模式缩写为:
- RWO - ReadWriteOnce
- ROX - ReadOnlyMany
- RWX - ReadWriteMany
重要!一个卷只能一次使用一种访问模式进行挂载,即使它支持很多。例如,GCEPersistentDisk可以由单个节点挂载为ReadWriteOnce或多个节点挂载为ReadOnlyMany,但不能同时使用两种。
Volume插件 | 单节点读写 | 多个节点只读 | 多个节点读写 |
---|---|---|---|
AWSElasticBlockStore | ✓ | - | - |
AzureFile | ✓ | ✓ | ✓ |
AzureDisk | ✓ | - | - |
CephFS | ✓ | ✓ | ✓ |
Cinder | ✓ | - | - |
FC | ✓ | ✓ | - |
FlexVolume | ✓ | ✓ | - |
Flocker | ✓ | - | - |
GCEPersistentDisk | ✓ | ✓ | - |
Glusterfs | ✓ | ✓ | ✓ |
HostPath | ✓ | - | - |
iSCSI | ✓ | ✓ | - |
PhotonPersistentDisk | ✓ | - | - |
Quobyte | ✓ | ✓ | ✓ |
NFS | ✓ | ✓ | ✓ |
RBD | ✓ | ✓ | - |
VsphereVolume | ✓ | - | - |
PortworxVolume | ✓ | - | ✓ |
ScaleIO | ✓ | ✓ | - |
StorageOS | ✓ | - | - |
类型
PV可以有一个类型,通过将storageClassName属性设置为StorageClass的名称来指定。 特定类型的PV只能绑定到请求该类型的PVC。 没有storageClassName的PV没有类型,只能绑定到不需要特定类型的PVC。 在过去,使用了注释volume.beta.kubernetes.io/storage-class而不是storageClassName属性。 该注释仍然可以工作,但将来Kubernetes版本将不再适用。
回收策略
目前的回收策略是:
- Retain - 手动回收
- Recycle - 基本擦洗(“rm -rf / thevolume / *”)
- Delete - 相关联的存储资产,如AWS EBS,GCE PD,Azure Disk或OpenStack Cinder卷被删除
目前,只有NFS和HostPath支持回收。 AWS EBS,GCE PD,Azure Disk和Cinder卷支持删除。
阶段
卷将处于以下阶段之一:
- Available 可用 - 一个尚未绑定到索赔的免费资源
- Bound 绑定 - 音量必须是声明
- Released 释放 - 声明已被删除,但资源尚未被集群回收
- Failed 失败 - 卷自动回收失败
CLI将显示绑定到PV的PVC的名称。
挂载选项
Kubernetes管理员可以指定在一个节点上挂载一个持久卷时的其他挂载选项。
您可以通过使用持久卷上的注释volume.beta.kubernetes.io/mount-options来指定安装选项。
例如:
apiVersion: "v1"
kind: "PersistentVolume"
metadata:
name: gce-disk-1
annotations:
volume.beta.kubernetes.io/mount-options: "discard"
spec:
capacity:
storage: "10Gi"
accessModes:
- "ReadWriteOnce"
gcePersistentDisk:
fsType: "ext4"
pdName: "gce-disk-1"
安装选项是一个字符串,在将卷安装到磁盘时将被累积地连接和使用。
请注意,并非所有Persistent卷类型都支持挂载选项。 在Kubernetes 1.6版中,以下卷类型支持挂载选项。
- GCEPersistentDisk
- AWSElasticBlockStore
- AzureFile
- AzureDisk
- NFS
- iSCSI
- RBD (Ceph Block Device)
- CephFS
- Cinder (OpenStack block storage)
- Glusterfs
- VsphereVolume
- Quobyte Volumes
- VMware Photon
PersistentVolumeClaims
每个PVC包含规格和状态,这是声明的规范和状态。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
storageClassName: slow
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: environment, operator: In, values: [dev]}
访问模式
当请求具有特定访问模式的存储时,声明使用与卷相同的约定。
资源
声明(就像pods)可以请求特定数量的资源。 在这种情况下,请求用于存储。 相同的资源模型适用于卷和声明。
选择器
声明可以指定标签选择器以进一步过滤Volumes集。 只有标签与选择器匹配的卷才能绑定到声明。 选择器可以由两个字段组成:
- matchLabels - 卷必须具有带此值的标签
- matchExpressions - 通过指定关键字和值的关键字,值列表和运算符所做的要求列表。 有效运算符包括In,NotIn,Exists和DoesNotExist。
所有来自matchLabels和matchExpressions的要求是组合在一起的,所有这些要求都必须满足才能匹配。
类型
声明可以通过使用属性storageClassName指定StorageClass的名称来请求特定的类型。只有所请求的类型的PV,与PVC相同的storageClassName的PV可以绑定到PVC。
PVC不一定要求一个类型。 它的storageClassName设置为等于“”的PVC总是被解释为请求没有类型的PV,因此它只能绑定到没有类型的PV(没有注释或一个等于“”)。 没有storageClassName的PVC不完全相同,并且根据是否启用了DefaultStorageClass admission插件,集群的处理方式不同。
- 如果admission插件已打开,则管理员可以指定默认的StorageClass。 没有storageClassName的所有PVC只能绑定到该默认的PV。 通过将StorageClass对象中的注解storageclass.kubernetes.io/is-default-class设置为“true”来指定默认的StorageClass。 如果管理员没有指定默认值,则集群会对PVC创建做出响应,就像admission插件被关闭一样。 如果指定了多个默认值,则admission插件禁止创建所有PVC。
- 如果admission插件已关闭,则不存在默认StorageClass的概念。 没有
storageClassName
的所有PVC只能绑定到没有类的PV。 在这种情况下,没有storageClassName
的PVC的处理方式与将其storageClassName
设置为“”的PVC相同。
根据挂载方法,挂载过程中可以通过addon manager在Kubernetes群集中部署默认的StorageClass
。
当PVC指定一个选择器,除了请求一个StorageClass
之外,这些要求被AND组合在一起:只有所请求的类和所请求的标签的PV可能被绑定到PVC。 请注意,当前,具有非空选择器的PVC不能为其动态配置PV。
在过去,使用了注解volume.beta.kubernetes.io/storage-class
,而不是storageClassName
属性。 该注解仍然可以工作,但在未来的Kubernetes版本中它将不被支持。
Claims VS Volumes
Pods通过将声明用作卷来访问存储。 声明必须存在于与使用声明的pod相同的命名空间中。 集群在pod的命名空间中查找声明,并使用它来获取支持声明的PersistentVolume
。 然后将卷挂载到主机并进入pod。
kind: Pod
apiVersion: v1
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: dockerfile/nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
关于命名空间的注意
PersistentVolumes
绑定是独占的,并且由于PersistentVolumeClaims
是命名空间对象,因此只能在一个命名空间内挂载“many”模式(ROX,RWX)的声明。
StorageClasses
每个StorageClass
包含字段provisioninger
和parameter
,当属于类型的PersistentVolume
需要动态配置时使用。
StorageClass
对象的名称很重要,用户可以如何请求特定的类。 管理员在首次创建StorageClass
对象时设置类的名称和其他参数,并且在创建对象后无法更新对象。
管理员可以仅为不要求任何特定类绑定的PVC指定默认的StorageClass:有关详细信息,请参阅PersistentVolumeClaim部分。
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
供应者(Provisioner)
存储类有一个供应者,它确定用于配置PV的卷插件。必须指定此字段。
Volume Plugin | Internal Provisioner | Config Example |
---|---|---|
AWSElasticBlockStore | ✓ | AWS |
AzureFile | ✓ | Azure File |
AzureDisk | ✓ | Azure Disk |
CephFS | - | - |
Cinder | ✓ | OpenStack Cinder |
FC | - | - |
FlexVolume | - | - |
Flocker | ✓ | - |
GCEPersistentDisk | ✓ | GCE |
Glusterfs | ✓ | Glusterfs |
iSCSI | - | - |
PhotonPersistentDisk | ✓ | - |
Quobyte | ✓ | Quobyte |
NFS | - | - |
RBD | ✓ | Ceph RBD |
VsphereVolume | ✓ | vSphere |
PortworxVolume | ✓ | Portworx Volume |
ScaleIO | ✓ | ScaleIO |
你不限于指定此处列出的“internal”供应者(其名称前缀为“kubernetes.io”并与Kubernetes一起发送)。 你还可以运行和指定外部提供程序,它们是遵循Kubernetes定义的规范的独立程序。 外部提供者的作者对代码的生命周期,供应商的运输状况,运行状况以及使用的卷插件(包括Flex)等都有充分的自主权。存储库kubernetes-incubator /外部存储库包含一个库 用于编写实施大部分规范的外部提供者以及各种社区维护的外部提供者。
例如,NFS不提供内部提供程序,但可以使用外部提供程序。 一些外部提供者列在存储库kubernetes-incubator/external-storage中。 还有第三方存储供应商提供自己的外部供应商的情况。
回收策略
由存储类动态创建的持久卷将具有delete
的回收策略。 如果不希望这样做,唯一的当前选项是在创建PV之后编辑PV。
通过存储类手动创建和管理的持久卷将具有在创建时分配的任何回收策略。
参数
存储类型具有描述属于存储类型的卷的参数。 取决于供应者,可以接受不同的参数。 例如,参数类型的值io1和参数iopsPerGB特定于EBS。 当省略参数时,使用一些默认值。