Kubernetes的Volume

(1).Volume是Pod中能够被多个容器访问的共享目录。

(2).Volume的生命周期独立于容器,Pod中的容器可能被销毁或重建,但Volume会被保留

(3).Volume支持多种类型的mount,包括:emptyDir、hostPath、NFS、Ceph、gcePersistentDisk、

awsElasticBlockStore;

1.emptyDir

一个emptyDir Volume是在Pod分配到Node时创建的。其实一个emptyDir Volume实际上是宿主机上的临时空目录,不过这个空目录是Kubernetes自动分配的一个目录。当Pod从Node上移除时,emptyDir中的数据也会永久删除。但对于容器来说是持久的。也就说emptyDir的生命周期与Pod是一致的。

emptyDir有哪些用途呢?

  • 临时空间;例如用于某些应用程序运行时所需的临时目录,且无需永久保留

  • 长时间任务的中间过程CheckPoint的临时保存目录

  • 一个容器需要从另一个容器抽个获取数据的目录(例如:日志收集,一个容器写日志,一个容器读日志)

验证一:Pod内的多个共享目录

如下面的例子:

cat emptydir.yaml

apiVersion: v1

kind: Pod

metadata:

 name: emptydir

spec:

 imagePullSecrets:

 - name: cd-registry

 containers:

 - name: busybox

   image: harbor.ttsingops.com/busybox/busybox:1.28

   imagePullPolicy: IfNotPresent

   command: ["sh","-c"," echo `date '+%H:%M:%S'` >> /data/logs/app.log;sleep 60 "]

   volumeMounts:

   - name: app-logs

     mountPath: /data/logs/

 - name: log-collector

   image: harbor.ttsingops.com/busybox/busybox:1.28

   imagePullPolicy: IfNotPresent

   command: ["sh","-c","cat /logs/app.log"]

   volumeMounts:

   - name: app-logs

     mountPath: /logs

 volumes:

 - name: app-logs

   emptyDir: {}

kubectl create -f emptydir.yaml

说明:

这里设置的Volume名为app-logs,类型为emptyDir,挂载到busybox容器的/data/logs目录,同时挂载到log-collector容器的logs目录。我们可以通过kubectl logs命令来查看log-collector容器日志

kubectl logs emptydir log-collector

Kubernetes的Volume存储卷_第1张图片

说明 log-collector成功读取到了/logs下的文件,也说明了两个容器共享emptyDir 的Volume

另:我们可以通过docker inspect container_id来查看两个容器的源路径,其实都是mount到同一个目录

先使用kubectl get po -o wide 查看emptydirPod在哪个Node上

2.png

【Node节点执行】

docker ps -a

docker inspect 7639c6651ab1|grep Source

docker inspect 0d29817ceea3|grep Source

Kubernetes的Volume存储卷_第2张图片

验证二:Volume与Pod生命周期

由于emptyDir是Node上创建的临时目录,不具备持久性;若Pod不存在,则emptyDir也就不存在;

下面我们把pod删除然后在重建Pod,看数据变化情况。

kubectl delete -f emptydir.yaml

kubectl create -f emptydir.yaml

kubectl logs emptydir log-collector

Kubernetes的Volume存储卷_第3张图片

2.hostPath

hostPath类型的Volume,是将宿主机上的目录mount给Pod的容器。与上面介绍的emptyDir不同的是,Pod被销毁了,hostPath中对应的目录数据也还会被保留

那它主要用在哪些方面呢?

  • 容器应用程序生产的日志文件需要永久保存,可以使用宿主机的高速文件系统存储

  • 需要访问宿主机Docker引擎内部数据结构的容器应用,可以通过定义hostPath为宿主机/var/lib/docker目录,使容器内部应用可以直接访问Docker的文件系统

使用注意的点:

  • 在不同的Node上具有相同配置的Pod可能会因为宿主机上的目录和文件不同而导致对Volume上目录和文件的访问结果不一致

  • 若使用资源配额,则k8s集群无法将hostPath在宿主机上使用的资源纳入管理

验证:挂载宿主机上的目录到Pod中

这里我为Pod打了标签,指定在特定的Node上运行(或者也可以都在node上建立相同的目录)

kubectl label node cd-k8s-node-3 type=node3

kubectl get nodes --show-labels

5.png

我们在node-3上的节点上新建/opt/logs目录

[root@cd-k8s-node-3 opt]# mkdir -p /opt/logs

6.png

cat hostpath.yaml

apiVersion: v1

kind: Pod

metadata:

 name: hostpath

spec:

 imagePullSecrets:

 - name: cd-registry

 nodeSelector:

   type: node3

 containers:

 - name: busybox

   image: harbor.ttsingops.com/busybox/busybox:1.28

   imagePullPolicy: IfNotPresent

   command: ["sh","-c"," echo `date '+%H:%M:%S'` >> /data/logs/app.log;sleep 60 "]

   volumeMounts:

   - name: app-logs

     mountPath: /data/logs/

 - name: log-collector

   image: harbor.ttsingops.com/busybox/busybox:1.28

   imagePullPolicy: IfNotPresent

   command: ["sh","-c","cat /logs/app.log"]

   volumeMounts:

   - name: app-logs

     mountPath: /logs

 volumes:

 - name: app-logs

   hostPath:

     path: /opt/logs

kubectl create -f hostpath.yaml

kubectl get po -o wide

7.png

这时到Node-3上查看/opt/logs/目录下是否有文件内容

[root@cd-k8s-node-3 logs]# cat /opt/logs/app.log

8.png

说明将宿主机目录挂载到容器中了

这时,若我们删除pod,node3上的数据也是还是存在的

kubectl delete -f hostpath.yaml

Kubernetes的Volume存储卷_第4张图片

3.NFS

也可以mount一个NFS类型的Volume,在同一个Pod内容器进行共享。

首先我们需要在系统中部署一个NFS Server,可参见《NFS部署实战及原理介绍》

实例验证:

NFS Server: 192.168.1.104/

Node节点上需要安装nfs-utils,否则在创建Pod时,提示挂载失败

我这里也指定在了node3节点上

先在node3节点上安装nfs依赖软件包

[root@cd-k8s-node-3 yum.repos.d]# yum install nfs-utils

cat nfs.yaml

apiVersion: v1

kind: Pod

metadata:

 name: nfstest

spec:

 imagePullSecrets:

 - name: cd-registry

 nodeSelector:

   type: node3

 containers:

 - name: busybox

   image: harbor.ttsingops.com/busybox/busybox:1.28

   imagePullPolicy: IfNotPresent

   command: ["sh","-c"," echo `date '+%H:%M:%S'` >> /data/logs/app.log;sleep 60 "]

   volumeMounts:

   - name: app-logs

     mountPath: /data/logs/

 - name: log-collector

   image: harbor.ttsingops.com/busybox/busybox:1.28

   imagePullPolicy: IfNotPresent

   command: ["sh","-c","cat /logs/app.log"]

   volumeMounts:

   - name: app-logs

     mountPath: /logs

 volumes:

 - name: app-logs

   nfs:

     server: 192.168.1.104

     path: "/nfsdata/k8sdata"

kubectl create -f nfs.yaml

然后我们到NFS Server上查看/data/k8sdata目录的

cat /nfsdata/k8sdata/app.log

Kubernetes的Volume存储卷_第5张图片

同时我们到Node3节点上查看

[root@cd-k8s-node-3 ~]# mount -l|grep nfs

11.png

#补充

 一个各个容器的时间都是相差八个小时,其实可以可以定义一个Volume类型为hostPath的,将宿主机的/etc/localtime挂载到容器中即可。

Kubernetes 的Volume也可以使用主流的分布式存储;诸如:Ceph、GlusterFS等

若Kubernetes部署在诸如AWS、GCE、阿里云等公有云,可以直接使用云硬盘作为Volume。使用时,请参阅它们各自的官方文档;基本都相差不大。

例如阿里云的k8s存储中可以使用:云盘、Nas、OSS

具体可参见:阿里云 容器服务Kubernetes版的官方文档