一、k8s物理集群
首先简单了解下k8s物理化集群,我们知道k8s物理化集群是由master节点以及node节点共同组成的如图1所示,master节点主要负责管理和调度整个集群,是指挥中心,Node节点是工作负载节点,里面是一系列的业务pod,而pod里面就是由docker创建的容器,每一个pod里面可以有一个或者多个。

图1. k8s 物理集群架构
Pod中每一个容器都自己独立的文件系统,实际上就是一个完成的Linux系统,因为这些文件系统都来自容器镜像。有时候我们不需要或者不想要整个文件系统被持久化的时候,而只仅仅希望实际数据的目录或者文件例如logs等被持久化时,我们就会使用到k8s数据持久化的机制。K8s数据持久化是借助Volume这个概念来完成的,volume是pod中能够被多个容器共享的目录。K8s中的volume是定义在pod上,然后被pod里面的多个容器挂载到具体的文件目录下。在容器重新启动期间,卷的内容将保持不变,pod重新启动之后,新的容器可以识别前一个容器写入volume的所有文件。Volume的使用很简单,首先在pod上声明一个volume,然后在容器里引用该volume,并且mount到容器的某个目录上即可。Volume的几种持久化方式如图2 所示。
K8s中的持久化存储,主要分为本地存储和网络存储。本地存储,本篇主要涉及到emptyDir、hostPath、configmap、secret等,网络存储主要讲述NFS以及glusterFs.
二、本地存储
1. emptyDir是pod被分配到node时创建的,它的初始内容为空,并且无需指定宿主机上对应的目录文件,这是k8s自动分配的一个目录,当pod从node上移除时,emptyDir 上面的数据也会被永久删除,emptyDir的主要用途如下:
作为无需临时保存的临时目录,或者同一个pod内的多容器共享目录,其示意图如图3.

图2. k8s主要的存储类型

图3. emptyDir 文件共享示意
hostPath可以挂载宿主机上的文件或者目录,比如程序生成的日志需要永久保存时,可以使用宿主机的高速文件系统进行存储,以hostPath挂载Java服务的log文件为例
volumeMounts:- mountPath: /logsname: data-logvolumes:- hostPath:path: /home/k8s/javaname: data-log
configMap ,顾名思义就是用于保存配置数据的键值对,可以用来保存单个的属性也可以用来保存配置文件,对于一些非敏感的数据,比如应用的配置信息,就可以使用configmap就行配置。使用configmap存储配置文件非常方便,以c++数据解析服务为例:
volumeMounts:- name : "c-config"mountPath: "/app/output/conf"volumes:- name : "c-config"configMap:name: “c-config”items:- key: rabbit_mq_config.jsonpath: rabbit_mq_config.json- key: consul_config.jsonpath: consul_config.json- key: httpserver_config.jsonpath: httpserver_config.json- key: message_wrap_config.jsonpath: message_wrap_config.json
Secret特别适用于保存一些敏感数据、像证书和私钥、token等等,secret的使用和配置等都和configmap类似,都是使用key-value进行存储以及声明使用.k8s通过仅仅将secret分发到需要访问secret的pod所在服务器节点来保障安全性。Secret只会存储在节点的内存中,而不写入到物理磁盘中,因此从节点上删除secret时就不需要擦除磁盘了。如果一个配置文件同时包含敏感数据和非敏感数据,则该文件应该被存储在secret中。
三、网络存储
本地存储有一些弊端,因为当pod挂掉重建到其他节点上时,所挂载的数据无法跨主机进行访问。所以这时候最好使用网络存储。网络存储的优势就是不受pod调度位置的限制,k8s借助Persistent Volume(PV) Persistent Volume Claim(PVC) 这两种资源使用网络存储,PV可以理解成k8s集群中的网络存储中对应的一块存储,与volume非常类似,但是有以下区别:
PV 只能是网络存储,不属于任何Node,但是可以在每一个Node上进行访问;PV并不是定义在pod上的,而是独立于pod之外进行定义的,PV和PVC之间的关系以及调用关系见图4描述。

图4. PV、PVC以及用于调用之间的关系
NFS存储就是一种网络存储,即为network file system的缩写,k8s可以通过配置挂载到NFS到pod之中,NFS中的数据可以永久保存。Pod被删除之后,volume被卸载,但是内容被保留,但是下次pod重启仍然可以读取到之前的数据信息,即使pod调度到其他节点也没有关系。PV 创建示例:
apiVersion: v1kind: PersistentVolumeClaimmetadata:name: consul-consul-0spec:accessModes:- ReadWriteManystorageClassName: ""resources:requests:storage: 250Mselector:matchLabels:pv: nfs-consul-pv1
volumeClaimTemplates:- metadata:name: consulspec:accessModes:- ReadWriteManystorageClassName: ""resources:requests:storage: 250M
glusterFs分布式网络存储,具备高扩展性、高可用性、高性能、可横向扩展等优点。分布式文件系统是指文件系统管理的物理存储资源并不是直接与本地节点相连,而是分布于计算网络中的一个或者多个节点的计算机上。Glusterfs 支持PB级别的存储容量并且能处理数千客户端,同时具备自动故障转移功能,可以避免单点故障。
apiVersion: v1kind: PersistentVolumemetadata:name: gluster-dev-volumespec:capacity:storage: 8GiaccessModes:- ReadWriteManyglusterfs:endpoints: "glusterfs-cluster"path: “/opt/glusterfs"readOnly: false
四、总结
emptyDir ——用于存储临时数据的简单空目录,主要用于在同一个pod中运行的容器之间共享文件
hostPath —— 用于将目录从Node节点的文件系统挂载到pod中,只能挂载到当前Node节点上的pod
configmap—— 主要用于挂载pod中所使用的配置信息等
secret——主要用于挂载隐私信息如token、证书、密码等
nfs —— 网络存储,通过网络共享挂载不同Node节点上的目录或者文件
glusterfs —— 分布式网络存储,适用于数据密集型任务的可扩展网络文件存储




