我们知道容器和 Pod 的生命周期可能很短,会被频繁地销毁和创建。当容器销毁时,保存在容器内部文件系统中的数据都会被清除。为了持久化保存容器的数据,我们可以使用 Kubernetes Volume。
除此之外,有一些场景可能一个 pod 里面的多个容器需要共享数据。同样可以借助 Volume 来实现。
八、Volume 存储
1,什么是 Volume?
(1)Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留。
(2)本质上,Kubernetes Volume 是一个目录,这一点与 Docker Volume 类似。当 Volume 被 mount 到 Pod,Pod 中的所有容器都可以访问这个 Volume。
(3)Volume 也支持多种 mount 类型,包括: emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph 等。
2,emptyDir
(1)基本介绍
emptyDir 是最基础的 Volume 类型。正如其名字所示,一个 emptyDir Volume 实际上是 Host 上的一个临时空目录。
emptyDir Volume 对于容器来说是持久的,对于 Pod 则不是。当 Pod 从节点删除时,Volume 的内容也会被删除。但如果只是容器被销毁而 Pod 还在,则 Volume 不受影响。
也就是说,emptyDir Volume 的生命周期与 Pod 一致。
(2)emptyDir 常用于一个 pod 内多个容器共享临时数据(如日志收集),首先我创建 app.yml 文件,内容如下:
(1)该 pod 中有两个容器:
app 容器:模拟实际场景中的应用,负责把日志写到日志文件中。
log-collector 容器:模拟实际场景中的日志收集,负责从日志文件中读取日志。
(2)文件最底部 volumes 定义了一个 emptyDir 类型的 Volume shared-dir,app 和 log-collector 都是共享这个 Volume。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | apiVersion: v1 kind: Pod metadata: name: emptydir-test spec: containers: - image: busybox name: app volumeMounts: - mountPath: /logs # 将 shared-dir mount 到 /logs 目录。 name: shared-dir args: - /bin/sh - -c - echo ` date '+%H:%M:%S' ` >> /logs/app.log; sleep 60 #通过 echo 将数据写到文件app.log里(60秒一次) - image: busybox name: log-collector volumeMounts: - mountPath: /app_logs # 将 shared-dir mount 到 /app_logs 目录。 name: shared-dir args: - /bin/sh - -c - cat /app_logs/app.log; sleep 60 # 通过cat从文件app.log读数据(60秒一次) volumes: - name: shared-dir #定义了一个 emptyDir 类型的 Volume shared-dir emptyDir: {} |
(3)接着执行如下命令创建 pod:
1 | kubectl apply -f app.yml |
(4)过个几分钟,通过 kubectl logs 命令查看 log-collector 容器日志,可以发现该容器成功读到了 app 写入的数据,验证了两个容器共享 emptyDir Volume。
1 | kubectl logs emptydir-test log-collector |
(5)通过 docker inspect 查看容器的详细配置信息,我们发现两个容器都 mount 了同一个目录:
因为 emptyDir 是 Docker Host 文件系统里的目录,其效果相当于执行了 docker run -v /logs 和 docker run -v /app_logs。
(6)由于 emptyDir 是 Host 上创建的临时目录,它不具备持久性。如果 Pod 不存在了,emptyDir 也就没有了。下面我们把 pod 删除再重新创建,可以发现前的数据已经被清除了。
1 2 3 | kubectl delete -f app.yml kubectl apply -f app.yml kubectl logs emptydir-test log-collector |
3,hostPath
(1)基本介绍
hostPath 类型的 volume,是将主机上的目录 mount 给 pod 的容器。
与 emptyDir 不同的是,即使 pod 被销毁了,hostPath 对应的目录数据也还会被保留。
注意:大部分应用都不会使用 hostPath Volume,因为这实际上增加了 Pod 与节点的耦合,限制了 Pod 的使用。不过那些需要访问 Kubernetes 或 Docker 内部数据(配置文件和二进制库)的应用则需要使用 hostPath。
(2)这里我们同样以前面的日志写入、读取为例。只不过这次我们不再使用临时目录作为共享目录,而是用用主机上 /mylogs 这个目录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | apiVersion: v1 kind: Pod metadata: name: hostpath-test spec: containers: - image: busybox name: app volumeMounts: - mountPath: /logs name: shared-dir args: - /bin/sh - -c - echo ` date '+%H:%M:%S' ` >> /logs/app.log; sleep 60 - image: busybox name: log-collector volumeMounts: - mountPath: /app_logs name: shared-dir args: - /bin/sh - -c - cat /app_logs/app.log; sleep 60 volumes: - name: shared-dir hostPath: path: /mylogs |
(3)创建 pod 后可以看到 /mylogs 这个目录下确实已经生成了日志文件:
4,NFS
(1)我们也可以 mount 一个NFS(网络数据卷)类型的 volume。即允许一块现有的网络硬盘在同一个 pod 内的容器间共享。
(2)还是以上面的日志写入、读取为例。只不过这次我们使用 NFS 目录作为为共享目录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | apiVersion: v1 kind: Pod metadata: name: nft-test spec: containers: - image: busybox name: app volumeMounts: - mountPath: /logs name: shared-dir args: - /bin/sh - -c - echo ` date '+%H:%M:%S' ` >> /logs/app.log; sleep 60 - image: busybox name: log-collector volumeMounts: - mountPath: /app_logs name: shared-dir args: - /bin/sh - -c - cat /app_logs/app.log; sleep 60 volumes: - name: shared-dir nfs: server: 192.168.20.47 path: "/data/disk1" |
5,外部存储
(1)如果 Kubernetes 部署在诸如 AWS、GCE、Azure 等公有云上,可以直接使用云硬盘作为 Volume,下面是 AWS Elastic Block Store 的例子:
要在 Pod 中使用 ESB volume,必须先在 AWS 中创建,然后通过 volume-id 引用。其他云硬盘的使用方法可参考各公有云厂商的官方文档。
(2)Kubernetes Volume 也可以使用主流的分布式存,比如 Ceph、GlusterFS 等。下面是一个 Ceph 例子:将 Ceph 文件系统的 /some/path/in/side/cephfs 目录被 mount 到容器路径 /test-ceph。
原文链接:https://www.hangge.com/blog/cache/detail_2437.html