¶Kubernetes存储卷
默认情况下容器的数据都是非持久化的,在容器消亡以后数据也跟着丢失,所以Docker提供了Volume机制以便将数据持久化存储。类似的,Kubernetes提供了更强大的Volume机制和丰富的插件,解决了容器数据持久化和容器间共享数据的问题。
与Docker不同,Kubernetes Volume的生命周期与Pod绑定
- 容器挂掉后Kubelet再次重启容器时,Volume的数据依然还在
- 而Pod删除时,Volume才会清理。数据是否丢失取决于具体的Volume类型,比如emptyDir的数据会丢失,而PV的数据不会丢失
- Volume类型
目前,Kubernetes支持以下Volume类型:
- emptyDir
- hostPath
- gcePersistentDisk
- awsElasticBlokStore
- nfs
- iscsi
- flocker
- glusterfs
- rbd
- cephfs
- gitRepo
- secret
- persistentVolumeClaim
- downwardAPI
- azureFileVolume
- vsphereVolume
- Quobyte
- PortworxVolume
- ScaleIO
- FlexVolume
- StorageOS
- local
这些Volume并非全部都是持久化的,emptyDir与hostPath数据节点级别的卷类型,emptyDir的生命周期与Pod资源相同,而使用hostPath卷的Pod一旦被重新调度至其他节点,那么它将无法再使用此前的数据。
再如,Secret和ConfigMap算得上是两种特殊的卷类型。
-
Secret用于向Pod传递敏感信息、如密码、私钥、证书文件等,这些信息如果直接定义在镜像中很容易导致泄露,有了Secret资源,用户可以将这些信息存储于集群中而后再由Pod进行挂载,从而实现将敏感数据与系统解耦。
-
ConfigMap资源则用于向Pod注入非敏感数据,使用时,用户将数据直接存储于ConfigMap对象中,而后直接在Pod中使用ConfigMap卷引用它即可,它可以帮助实现容器配置文件集中化定义和管理。
因此,类似于emptyDir、hostPath、secret、gitRepo等,这些Volume会随着Pod的消亡而消失。
- Volume的使用
在Pod中定义Volume由两部分组成:一是.spec.valumes
,用于支持不同的Volume类型;二是.spec.containers.volumeMounts
,用于定义挂载列表。
在Pod级别定义Volume,.spec.volumes
字段可以定义多个Volume,例如下面定义了emptyDir类型和gitRepo类型,
1 | spec: |
定义好的Volume可以共享。当Pod中只有一个容器时,使用存储卷通常用于数据持久化。
.spec.containers.volumeMounts
字段定义了Volume的挂载列表。它的挂载格式是固定的,如下,
1 | spec: |
其中,
- name
:指定要挂载的存储的名称,必选 - mountPath
:挂载点路径,容器文件系统上的路径,必选 - readOnly
:是否挂载为只读 - subPath
:子路径,即mountPath指定的路径下的一个字路径
例如,容器myapp将logdata存储卷挂载在/var/log/myapp,将example挂载到/webdata/example目录,
1 | spec: |
- emptyDir
emptyDir,如果Pod设置了emptyDir类型Volume,Pod被分配到Node上时候,会创建emptyDir,只要Pod运行在Node上,emptyDir都会存在(容器挂掉不会导致emptyDir丢失数据),但是如果Pod从Node上被删除(Pod被删除,或者Pod发生迁移),emptyDir也会被删除,并且永久丢失。
.spec.volumes.emptyDir
嵌套字段包含有,
- medium:存储介质的类型,默认为default,表示为使用节点默认存储介质;另一种是Memory,表示使用RAM的临时文件系统tmpfs,空间受限于内存,但性能非常好,通常用于作为缓存。
- sizeLimit:当前Volume的空间限额,默认为nil,表示不限制;不过如果medium字段值为Memory时建议定义限额。
1 | apiVersion: v1 |
容器pagegen每隔10秒向Volume上的index.html文件追加一行信息,
1 | kubectl describe pods vol-emptydir-pod |
创建Service或直接在集群访问Pod的信息,可看到,
边车(sidecar)容器pagegen每隔10秒生成一行信息追加到Volume上的index.html文件。另外emptyDir存储卷可以基于RAM创建tmpfs文件系统的存储卷,常用于缓存,
1 | volumes: |
- gitRepo
gitRepo存储卷是emptyDir的实际应用,它看做是将一份Git仓储中的数据克隆(clone)到创建的空目录(emptyDir),而后再创建容器并挂载该存储卷。
gitRepo存储卷自Kubernetes1.12开始已经废弃,所以这里不再陈述。
- hostPath
hostPath运行挂载Node上的文件系统到Pod里面去。如果Pod需要使用Node上的文件,可以使用hostPath。因为它独立于Pod资源的生命周期,因而具有持久性。
1 | apiVersion: v1 |
这类Pod资源通常受控于daemonset类型的Pod控制器,它运行于集群中的每个工作节点之上,负责收集工作节点上系统级的相关数据,因此使用hostPath存储卷。这里的filebeat应用架构中,通过Redis进行资源收集,这些收集的日志信息会发往ELK进行统计展示。
hostPath上如果是不受控于Daemonset的无状态应用,重新调度节点运行时,无法确保此前创建的文件或目录是否存在。因此,hostPath虽能持久化数据,但对调度器来说并不适用,这时需要用到独立于集群节点的持久化存储卷,即网络存储卷。
网络存储卷,就是类似于NAS或SAN设备、分布式存储(GlusterFS、RBD)、云端存储(gcePersistentDisk、azureDisk、cinder和awsElasticBlockStore)以及构建在各类存储系统之上的抽象管理层(flocker、portworx Volume和vsphere Volume)等这类网络服务存储。
- NFS
NFS,即Network File System,网络文件系统。Kubernetes中通过简单配置可以挂在NFS到Pod中,而NFS中的数据是可以永久保存的,同时NFS支持同时写操作。
1 | apiVersion: v1 |
- RBD
Ceph RBD1是一个分布式、弹性可扩展的、高可靠的、性能优异的存储系统平台。要配置Pod资源使用RBD存储卷,前提条件要满足:
- Ceph RBD存储集群,
- Ceph RBD集群中创建有满足Pod资源数据用到的存储image
- Kubernetes集群内各个节点需要安装Ceph客户端程序包(ceph-common)
它的字段信息有,
monitors<[]string>
:Ceph存储监视器,逗号分隔的字符串列表;必选字段image<string>
:rados image的名称,必选字段pool<string>
:rados存储池名称,默认为RBDuser<string>
:rados用户名,默认为adminkeyring<string>
:RBD用户认证时使用的keyring文件路径,默认为/etc/ceph/keyring
secretRef<Object>
:RBD用户认证时使用的保存有相应认证信息的Secret对象,会覆盖由keyring字段提供的密钥信息readOnly<boolean>
:是否以只读的方式进行访问fsType
:要挂载的存储卷的文件系统类型,至少应该是节点操作系统支持的文件系统,如ext4、xfs、ntf等,默认为ext4
下面是使用RBD存储卷的Pod资源示例,
1 | apiVersion: v1 |
该示例依赖于事先存在的一个Ceph存储集群,这里假设其监视器的地址为192.168.50.32、192.168.50.33、192.168.50.34三个主机,并且集群上的存储池kube中存在创建好的映像Redis,此映像拥有xfs文件系统。Ceph客户端访问集群时需要事先完成认证之后才能进行后续访问操作,认证信息保存于名为ceph-secret的Secret资源对象中。
更多关于reph的配置方式,参考这里。
- GlusterFS 存储卷
GlusterFS(Gluster File System)是一个开源的分布式文件系统,是水平扩展存储解决方案Gluster的核心,具有强大的横向扩展能力,GlusterFS通过扩展能够支持数PB存储容量和处理数千客户端。要配置Pod资源使用GlusterFS存储卷,需要事先满足以下前提条件。
- 存在某个可用集群,
- 在GlusterFS集群创建了Pod需要使用的Volume,
- Kubernetes集群各个节点安装GlusterFS客户端程序包(glusterfs和glusterfs-fuse),
Pod定义GlusterFS类型Volume,包含的字段有,
endpoint<string>
:访问入口,必选字段,path<string>
:用到GlusterFS集群的卷路径,readOnly<boolean>
:是否为只读卷,
下面是一个定义在vol-glusterfs.yaml配置文件中的Pod资源示例,它使用了GlusterFS存储卷持久保存应用数据。
1 | apiVersion: v1 |
另外创建Endpoints资源glusterfs-endpoints,以用于Pod资源访问,