官方文档: Volumes
Volumes
Container(容器) 中的磁盘文件是短暂的,当容器崩溃时,Kubelet 会重新启动容器,但最初的文件将丢失,Container 会以最干净的状态启动。另外,当一个 Pod 运行多个 Container 时,各个容器可能需要共享一些文件。Kubernetes Volume 可以解决这两个问题。
一些需要持久化数据的程序才会用到 Volumes,或者一些需要共享数据的容器需要 volumes,比如 Redis-Cluster 的配置文件 nodes.conf;还有容器日志收集的需求,需要在应用程序的容器中加一个 sidecar,这个容器时一个收集日志的容器,比如 filebeat,它通过 volumes 共享应用程序的日志文件目录。
背景
Docker 也有卷的概念,但是在 Docker 中,卷只是磁盘上或者另一个 Container 中的目录,其生命周期不受管理。虽然目前 Docker 已经提供了卷驱动程序,但是功能非常有限,例如从 Docker 1.17 版本开始,每个 Container 只允许一个卷驱动程序,并且无法将参数传递给卷。
另一方面,Kubernetes 卷具有明确的生命周期,与使用它的 Pod 相同。因此,在 Kubernetes 中的卷可以比 Pod 中运行的 Container 都长,并且可以在 Container 重启或者销毁之后保留数据。Kubernetes 支持多种类型的卷,Pod 可以同时使用任意数量的卷。
从本质上讲,卷只是一个目录,可能同时包含一些数据,Pod 中的容器可以访问它。要使用卷,Pod 需要通过 .spec.volumes
字段指定为 Pod 提供的卷,以及使用 .spec.containers.volumeMounts
字段指定卷挂载的目录。从容器中的进程可以看到由 Docker 镜像和卷组成的文件系统视图,卷无法挂载其他卷或具有到其他卷的硬链接,Pod 中的每个 Container 必须独立指定每个卷的挂载位置。
Volumes 的类型
emptyDir
当将 Pod 分配给节点时,首先创建 emptyDir
卷,并且只要该 Pod 在该节点上运行,该卷便存在。顾名思义,emptyDir
卷最初是空的。Pod 中的所有容器都可以在 emptyDir
卷中读取和写入相同的文件。但是,如果出于任何原因将 Pod 从节点中删除,则 emptyDir
中的数据将被永久删除。
一般情况下,emptyDir
卷用于 Pod 中的不同 Container 共享数据。它可以被挂载到相同或者不同的路径上。默认情况下,emptyDir 卷支持节点上的任何介质,可能是 SSD,磁盘或者网络存储,具体取决于自身的环境。可以将 emptyDir.medium
字段设置为 Memory
,让 Kubernetes 使用 tmpfs
(内存支持的文件系统),虽然 tmpfs
非常快,但是 tmpfs
在节点重启时,数据同样会被清除,并且设置的大小会被计入到 Container 的内存限制当中。
EmptyDir 卷示例
使用 emptyDir
卷的示例,如下,指定 emptyDir
为 {}
即可。
1 | apiVersion: apps/v1 |
hostPath
hostPath 卷可将节点上的文件或目录挂载到 Pod 上,用于 Pod 自定义日志输出或访问 Docker 内部的容器等等。
hostPath 卷示例
使用 hostPath 卷的示例,如下,将主机的 /etc/timezone 文件挂载到 Pod /etc/timezone
1 | apiVersion: apps/v1 |
hostPath 卷常用的 type(类型)如下
- type 为空字符串: 默认选项,意味着挂载 hostPath 卷之前不会执行任何检查;
- DirectoryOrCreate: 如果给定的 Path 不存在任何东西,那么将根据需要创建一个权限为 0755 的空目录,和 kubelet 具有相同的组合权限;
- Directory: 目录必须存在于给定的路径下;
- FileOrCreate: 如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设置为 0644,和 kubelet 具有相同的组和权限;
- File: 文件,必须存在于给定的路径中;
- Socket: UNIX 套接字,必须存在于给定的路径中;
- CharDevice: 字符设备,必须存在于给定的路径中;
- BlockDevice: 块设备,必须存在于给定的路径中;
NFS
NFS 卷允许将现有的 NFS(网络文件系统)共享安装到 Pod 中。与 EmptyDir 不同,在删除 Pod 时会删除 EmptyDir,但是 NFS 卷的内容会被保留,而只是卸载了该卷。这意味着可以在 NFS 中预填数据,并且可以在 Pod 之间共享数据。
NFS 服务器的安装与配置
1 | # 安装 nfs |
NFS 卷示例
1 | apiVersion: apps/v1 |