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
说明 log-collector成功读取到了/logs下的文件,也说明了两个容器共享emptyDir 的Volume
另:我们可以通过docker inspect container_id来查看两个容器的源路径,其实都是mount到同一个目录
先使用kubectl get po -o wide 查看emptydirPod在哪个Node上
【Node节点执行】
docker ps -a
docker inspect 7639c6651ab1|grep Source
docker inspect 0d29817ceea3|grep Source
验证二:Volume与Pod生命周期
由于emptyDir是Node上创建的临时目录,不具备持久性;若Pod不存在,则emptyDir也就不存在;
下面我们把pod删除然后在重建Pod,看数据变化情况。
kubectl delete -f emptydir.yaml
kubectl create -f emptydir.yaml
kubectl logs emptydir log-collector
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
我们在node-3上的节点上新建/opt/logs目录
[root@cd-k8s-node-3 opt]# mkdir -p /opt/logs
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
这时到Node-3上查看/opt/logs/目录下是否有文件内容
[root@cd-k8s-node-3 logs]# cat /opt/logs/app.log
说明将宿主机目录挂载到容器中了
这时,若我们删除pod,node3上的数据也是还是存在的
kubectl delete -f hostpath.yaml
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
同时我们到Node3节点上查看
[root@cd-k8s-node-3 ~]# mount -l|grep nfs
#补充
一个各个容器的时间都是相差八个小时,其实可以可以定义一个Volume类型为hostPath的,将宿主机的/etc/localtime挂载到容器中即可。
Kubernetes 的Volume也可以使用主流的分布式存储;诸如:Ceph、GlusterFS等
若Kubernetes部署在诸如AWS、GCE、阿里云等公有云,可以直接使用云硬盘作为Volume。使用时,请参阅它们各自的官方文档;基本都相差不大。
例如阿里云的k8s存储中可以使用:云盘、Nas、OSS
具体可参见:阿里云 容器服务Kubernetes版的官方文档