在Kubernetes之上,在节点级提供一个存储卷的方式来持久存储数据的逻辑,这种只具备一定程度上的持久性。为了实现更强大的持久性,应该使用脱离节点而存在的共享存储设备。 为此Kubernetes提供了不同类型的存储卷。
大多数和数据存储服务相关的应用,和有状态应用几乎都是需要持久存储数据的。容器本身是有生命周期的,为了使容器终结后可以将其删除,或者编排至其他节点上去运行。意味着数据不能存储在容器本地。一旦Pod故障就会触发重构。如果将数据放置在Pod自有的容器内名称空间中,数据随着Pod终结而结束。为了突破Pod生命周期的限制,需要将数据放置在Pod自有文件系统之外的地方。
存储卷
对Kubernetes来讲,存储卷不属于容器,而属于Pod。因此,在Kubernetes中同一个Pod内的多个容器可共享访问同一组存储卷。
Pod底部有一个基础容器, ==pause
==,但是不会启动。pause是基础架构容器。创建Pod时pause时Pod的根,所有Pod,包括网络命名空间等分配都是分配给pause的。在Pod中运行的容器是pause的网络名称空间的。容器在挂载存储卷时,实际上是复制pause的存储卷。
因此为了真的实现持久性,存储卷应为宿主机挂载的外部存储设备的存储卷。如果需要实现跨节点持久,一般而言需要使用脱离节点本地的网络存储设备(ceph、glusterfs、nfs)来实现。节点如果需要使用此种存储的话,需要可以驱动相应存储设备才可以(在节点级可以访问相应网络存储设备)。
k8s之上可使用的存储卷
Kubernetes支持的存储卷类型
- empryDir:只在节点本地使用的,用于做临时目录,或当缓存使用。一旦Pod删除,存储卷一并被删除。empryDir背后关联的宿主机目录可以使宿主机的内存。
- hostPath:使宿主机目录与容器建立关联关系。
- 网络存储
- 传统的SAN(iSCSI,FC)NAS(常见用法协议 NFS,cifs,http)设备所构建的网络存储设备。
- 分布式存储(分机系统或块级别),glusterfs,ceph(rbd ceph的块接口存储),cephfs等。
- 云存储:EBS(弹性块存储)亚马逊 ,Azure Disk 微软。此模型只适用于Kubernetes集群托管在其公有云之上的场景。
使用kubectl explain pod.spec.volumes
查看Kubernetes所支持的存储类型。
emptyDir
语法
emptyDir
medium
媒介类型 empty string (disk 默认) or memorysizeLimit
空间上限
定义完存储卷之后,需要在container
当中使用volumeMounts
指明挂载哪个或哪些个存储卷
|
|
|
|
在Kubernetes中 $()是变量引用
gitRepo
将git仓库当做存储卷来使用,其实并不是Pod将git仓库当存储卷来使用。只不过是在Pod创建时,会自动连接到git仓库之上(此链连接依赖于宿主机上有git命令来完成),由宿主机驱动,将git仓库中的内容clone到本地来,并且将其作为存储卷挂载至Pod之上。
==gitRepo是建立在emptyDir之上==。所不同的在于,将所指定仓库的内容clone下来并放至空目录中。因此主容器将此目录当做服务于用户的数据来源。需要注意的是,在此处做的修改是不会同步到git仓库中去的。
如果git仓库在Pod运行过程中内容发生改变,Pod之内的存储卷内容是不会随之改变的。
gitRepo 卷示例:
|
|
查看Pod内容器挂载的目录
|
|
hostPath
hostPath 将Pod所在宿主机之上、脱离Pod中容器名称空间之外的宿主机的文件系统的某一目录与Pod建立关联关系。在Pod被删除时,此存储卷是不会被删除的。
hostPath在一定程度上拥有持久的特性,但这种持久只是节点级的持久,在被跨节点调度时,这些数据还是会丢失的。
type
DirectoryOrCreate
挂载路径在宿主机上是已存在的目录,如目录不存在则创建此目录。Directory
挂载路径在宿主机上必须已存在的目录。FileOrCreate
文件或创建新的空文件。File
必须存在此文件,将其挂载至容器中。Socket
必须是socket类型的文件。CharDevice
必须是一个字符类型的设备文件。BlockDevice
块类型的设备文件。
hostPath 卷示例:
|
|
NFS,对于nfs存储卷来讲
- path -required- nfs服务器导出路径,
- readOnly 只读 true or false 默认false
- server [required] 服务器地址
|
|
PVC使用逻辑
在Pod中只需定义存储卷,定义时只需指定使用存储卷大小,这个存储卷叫PVC类型的存储卷。PVC存储卷必须与当前名称空间中的PVC建立直接绑定关系,而PVC必须与PV建立绑定关系,而PV是某个真实存储设备上的存储空间。所以PV和PVC是kubernetes系统之上的抽象的标准资源。PV和PVC之间的关系,在PVC不被调用时是空载的。
对于PV类型的资源的使用
PVC语法
PVC是标准K8S资源,也有自己所属的属组。
kubectl explain pvc
|
|
PVC选择的模式
- 使用存储卷名称,一对一绑定了(精确选择),
- 选择器选定
- 如不指定名称,会从大量符合条件的PV选一个。
- 类型限制,volumeMode,那一类型的PV可以被当前claim所使用。
在Pod中使用当前名称空间已经存在的PVC
exportfs -arv
kubectl explain pods.spec.volumes.persistentVolumeClaim
,PV和PVC的关联是一对一的,一旦被使用(状态为banding)
|
|
定义PV时一定不要加名称空间,PV是集群级别的,不属于名称空间,但==PVC是属于名称空间级别==的。PVC并不属于节点(node),PVC是标准的Kubernetes资源,它存储在etcd当中。只有Pod才需要运行在节点之上,所有其他资源基本都是保存在集群状态存储(apiserver的存储)etcd当中。
在Kubernetes新版本中,只要PV还被PVC绑定,就不支持删除。
定义accessMode时需要注意存储设备,有些存储设备不支持多路读写与多路只读,只支持单路读写。
- accessMode []string accessMode可定义多个参数
ReadWriteOnce
单路读写,可简写为RWOReadOnlyMany
多路只读,ROXReadWriteMany
多路读写操作 RWX
- capacity 用来指定存储空间的大小,需要使用资源访问模型来定义。
- persistentVolumeReclaimPolicy 回收策略 Persistent Volumes
Retain
保留。Recycle
回收,将数据删除,并且把PV置为空闲状态可以让其他设备绑定。delete
删除PV
|
|
PVC
- spec
accessModes
PVC也需要定义accessModes,此accessModes模式要求一定是PV的accessModes的子集才可以被匹配到。resources
如指定,PV一定要满足(大于、等于)PVC此值才能被使用。requests
[]map此处是与PV不一样之处,需要要求有多大空间
PVC的使用
|
|
查看PV和PVC
|
|
StorageClass
在PVC申请时,未必就有现成的PV能正好符合PVC在申请中指定的条件,为此Kubernetes设计了一种工作逻辑,能够让PVC在申请PV时不针对某个PV进行。可以针对某个存储类(Kubernetes之上的标准资源之一)StorageClass
,借助此资源层,来完成资源分配的。
StorageClass
可以理解为,事先把众多的存储设备当中所提供好的现有可用存储空间(尚未做成PV的存储空间)进行分类(根据综合服务质量、IO性能等)。定义好存储类之后,当PVC再去申请PV时,不针对某个PV直接进行,而是针对存储了进行。必须让存储设备支持Restful风格的请求创建接口,用户可以通过Restful风格的请求1.在磁盘上划分刚好符合PVC大小的分区。2 编辑/etc/export
文件,将分区挂载至本地某个目录上。3. 动态创建PV去绑定之前动态导出的空间。
nfs 动态
external-storage/nfs-client at master · kubernetes-incubator/external-storage · GitHub
Docker(二十九)k8s 创建动态存储,基于nfs 的storageclass-洒脱,是云谈风轻的态度-51CTO博客