存储卷概述
对于有数据存储需求的容器应用来说,数据脱离容器生命周期,而持久化存储的需求是必需的,如mysql,redis等数据库应用。
docker提供了容器主机级别和网络级的存储机制,使得容器可以使用节点上,或网络共享存储系统上的存储空间,使得数据可以脱离容器生命周期,节点,而存在,且网络存储系统一般是高可用的。
kubernetes同样为pod提供了存储卷,实现数据持久存储的能力,同样支持节点级、网络存储级的存储卷,节点级如emptydir和hostpath只适合实验,生产中需要采用高可用的网络存储卷。
k8s支持的存储卷类型
k8s支持节点本地存储、网络共享存储、云厂商存储产品等多种存储卷:还有特殊存储卷configmap、secret;分别用于提供非敏感、敏感的配置信息,实现配置与应用的解耦;
此外:k8s还提供了pv和pvc,将存储抽象为k8s集群资源,使得存储卷使用更方便,存储集群可由专门的存储运维;
存储卷定义使用格式
- 先用spec.volumes定义存储卷列表,每个存储卷都有唯一的名称
- 每个类型支持不同的配置参数,如nfs,cephfs都是不同的参数
- 在容器的volumesMounts字段引用上面定义的存储卷,
- 用名称引用
- 可定义读写权限
- 容器中的挂载点
语法:
[root@client k8s_yaml]# kubectl explain pods.spec.
...
volumes <[]Object>
List of volumes that can be mounted by containers belonging to the pod.
More info: https://kubernetes.io/docs/concepts/storage/volumes
# volumes下级,是各种类型的存储卷
[root@client k8s_yaml]# kubectl explain pods.spec.volumes.
KIND: Pod
VERSION: v1
RESOURCE: volumes <[]Object>
DESCRIPTION:
List of volumes that can be mounted by containers belonging to the pod.
More info: https://kubernetes.io/docs/concepts/storage/volumes
Volume represents a named volume in a pod that may be accessed by any
container in the pod.
FIELDS:
awsElasticBlockStore <Object>
AWSElasticBlockStore represents an AWS Disk resource that is attached to a
kubelet's host machine and then exposed to the pod. More info:
https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore
azureDisk <Object>
AzureDisk represents an Azure Data Disk mount on the host and bind mount to
the pod.
azureFile <Object>
AzureFile represents an Azure File Service mount on the host and bind mount
to the pod.
cephfs <Object>
CephFS represents a Ceph FS mount on the host that shares a pod's lifetime
cinder <Object>
...
[root@client k8s_yaml]# kubectl explain pods.spec.containers
...
volumeMounts <[]Object>
Pod volumes to mount into the container's filesystem. Cannot be updated.
workingDir <string>
Container's working directory. If not specified, the container runtime's
default will be used, which might be configured in the container image.
Cannot be updated.
临时存储卷
emptydir和gitrepo属于临时存储卷
emptydir
和pod的生命周期一致,适合做缓存数据的存储空间,
[root@client k8s_yaml]# kubectl explain pods.spec.volumes.emptyDir
2个字段:
medium 存储介质,memory或空字符串(表示和节点存储介质一样)
sizeLimit 存储空间的大小上限
示例:
[root@client volumes]# cat emptydir.yml
apiVersion: v1
kind: Pod
metadata:
name: pod-emptydir
spec:
volumes:
- name: html
emptyDir:
medium:
sizeLimit: 10Mi
containers:
- name: nginx
image: nginx:1.12-alpine
volumeMounts:
- name: html
mountPath: /usr/share/html/nginx/
- name: alpine
image: alpine
volumeMounts:
- name: html
mountPath: /root/
command: ["/bin/sh","-c"]
args:
- while true; do
echo $(hostname) $(date) >> /root/index.html;
sleep 4;
done
首先定义了名为html的存储卷
然后再pod中的2个容器中都引用挂载,
其中alpine向其中不停向主页文件追加内容,另一个nginx容器也可以看到,因为是相同的存储卷
图示:
gitRepo
gitrepo基于emptydir,其工作逻辑:
- pod运行的节点,具有git客户端,首先根据gitrepo中定义的仓库地址,将库中数据拉取到本地目录;
- 然后将本地节点的目录作为挂载卷,挂载到容器当中
gitrepo在k8s1.12后已经废弃,建议采用initcontainer将主容器需要的数据复制到主容器中,而不再用gitrepo
节点存储卷hostPath
节点级别的存储卷是hostPath,将节点上的目录提供给pod做存储卷,适合的pod类型:每个节点都运行的系统级pod,即ds控制的pod,如收集日志、监控等类型的应用;
示例:
apiVersion: v1
kind: Pod
metadata:
name: pod-hostPath
spec:
volumes:
- name: log
hostPath:
path: /var/log
- name: socket
hostPath
path: /var/run/docker.sock
containers:
- name: filebeat
image: filebeat:5.8-alpine
volumeMounts:
- name: log
mountPath: /var/log
- name: socket
mountPath: /var/run/docker.sock
网络存储卷
生产中,对于非ds的pod,更常用的还是网络存储卷,
- san或nas,如nfs,fc,iscsi
- 分布式存储系统,如glusterfs,ceph
- 云存储:aws,azure,gce的产品
how-to使用不同的存储卷
- spec.volumes字段定义不同类型的存储卷即可
- 不同类型的存储卷支持的参数不同
- 参数一般包含后端存储集群的连接、认证信息等
- kubectl explain pods.spec.volumes.[nfs|ceph|glusterfs|...]
- 不同类型的存储卷支持的参数不同
- spec.containres.volumesMount字段引用上步定义好的存储卷即可
- 用上步存储卷名引用
- mountPath定义挂到容器的那个目录即可
nfs存储卷
nfs是类Unix系统内核级别提供的网络共享文件系统;使用nfs存储卷需要pod所在节点能够访问、并挂载nfs开放出的目录;
1、配置nfs服务,允许集群所有节点可访问挂载,(因pod可能调度到任何一个节点)
配置nfs服务
[root@client ~]# yum install -y nfs-utils
2、定义pod,容器采用pod,其中volums字段定义的是nfs类型的存储卷,并在volumeMounts引用
3、应用pod文件,生成pod对象
4、连入容器,写入数据,然后删除pod
5、再次应用pod文件,连入容器,查看数据是否还在
rbd存储卷
rbd是ceph存储系统提供的三大存储接口之一:
- rbd块设备接口
- fs文件系统接口
- api接口
图示:
1、搭建并配置好一个ceph集群,启用rbd存储
2、ceph集群中配置一个能供pod使用的存储映像image
3、参照rbd存储卷定义语法,填充ceph集群访问相关的字段,主要是ceph集群的访问认证信息,敏感信息要定义为secret
语法:
4、将ceph集群访问认证信息定义为secret,在定义rbd存储卷中secretRef引用
5、集群各个节点安装访问ceph集群的客户端包ceph-common
6、应用pod定义文件,查看效果
pod文件示例:
glusterfs存储卷
- 搭建可以用的glusterfs集群
- 在glusterfs集群上创建供pod使用的卷
- 集群各个node节点安装glusterfs客户端包:glusterfs和glusterfs-fuse
- 根据语法,定义glusterfs类型的volumes
- 示例
- 定义访问glusterfs集群所需的endpoint资源
- 示例
- 先应用endpoints定义文件,再应用pod定义文件
- 查看效果
cinder存储卷
cinder为openstack项目中为vm虚拟机提供持久存储的项目,但k8s也支持cinder提供的存储卷,尤其k8s部署与openstack的IAAS环境中时,可以直接使用openstack的cinder存储
语法:
示例:
持久存储卷
what`s pv and pvc
创建pv
nfs类型pv
rbd类型pv
pv的状态
创建pvc
在pod中使用pvc
storageClass存储类动态供给
实现存储类动态供给pv的步骤:
- 需要有支持动态供给pv的后端存储系统
- 定义storageClass字段,其中指明了后端存储的参数,如连接、认证信息;本存储类的默认存储类型,回收策略等;
- 用户在需要时,直接定义pvc,pvc指定调用哪个存储类接口
- 创建为pvc对象后,pvc会调用存储类直接生成对应的pv对象,然后进行绑定
定义存储类-依据某一特定后端存储
动态pv供给
1、用户根据需求直接定义pvc即可,定义中指定使用哪个存储类动态创建,
2、指定存储类的方式有2种
- 注解
- 指定存储类的名称
ps:
所有支持pv动态供给的存储系统,都可以定义为存储类之后,用户通过定义pvc来直接调用存储类动态的创建pv,生产中pv的数量,pv的空间大小无法事先预估,因此采用存储类动态供给更适合,但并非所有存储系统都支持动态供给pv;
pv和pvc的生命周期
pv和pvc是一对一的关系,其共有3个阶段:
- 存储供给
- 存储绑定
- 存储回收
存储供给
存储绑定
存储回收
存储卷扩容
downwardAPI存储卷
环境变量注入元数据
存储卷注入元数据
downwardAPI类型的存储卷,可以实现将外部的环境信息,注入到容器内部,适合非原生开发的应用程序,在不做代码改造的情况下,通过挂载downwardAPI卷注入其需要的配置信息
方法:
- 定义volumes字段时,定义downwardAPI类型的卷,其中:采用fieladref或resourcefileref从pod的属性信息中引入变量
- 再在容器的volumeMounts字段引用downwardAPI存储卷的名称即可
小结:
- 临时存储卷:emptydir和gitrepo类型存储卷,生命周期和pod相等,gitrepo可以通过引用外部git仓库数据实现数据持久性
- 节点存储卷:hostpath,提供节点级数据持久能力,常用ds控制器类型的节点级pod应用
- 网络存储卷:ceph,glusterfs,nfs可以提供分布式网络共享存储
- 云存储:aws,gce云厂商可以提供云存储卷
- pv和pvc:将存储管理和存储使用,解耦为生产、消费模型,存储管理有专门的存储集群运维,开发只需定义pvc即可使用存储卷
- 基于存储类Storageclass,可实现pv的动态供给,需要后端存储支持该特性,如:clusterfs,ceph的rbd,云存储产品等