转载:k8s数据卷 Volume 之 hostPath 与 emptyDir
一、为什么需要 volume(数据卷)?
容器中的文件在磁盘上是临时存放的,这给容器中运行比较重要的应用程序带来一些问题。
- 问题1:当容器升级或者崩溃时,kubelet会重建容器,容器内文件会丢失
- 问题2:一个Pod中运行多个容器需要共享文件。
Kubernetes 卷(Volume) 这一抽象概念能够解决这两个问题。
二、常用数据卷
- 本地(emptyDir,hostPath)
- 网络(NFS,Ceph,GlusterFS)
- 公有云(AWS EBS)
- K8S资源(configmap,secret)

三、empryDir
emptyDir卷: 是一个自动创建的、 Pod 所在node主机上的临时目录(node上预设定好的存储位置),与Pod生命周期绑定在一起,如果Pod删除了,emptyDir卷也会被删除。
应用场景: Pod中容器之间数据共享,常用于同一个pod内容器(container)之间直接的数据传输。
例子
# 做一个测试yaml vi emptydir.yaml
apiVersion: v1 kind: Pod metadata: name: pod1 spec: containers: - name: write # 业务容器(写数据) image: centos command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"] volumeMounts: - name: data mountPath: /data - name: read # 辅助容器(读数据) image: centos command: ["bash","-c","tail -f /data/hello"] volumeMounts: - name: data mountPath: /data volumes: - name: data emptyDir: {}
kubectl apply -f emptydir.yaml
这个 YAML 文件定义了一个 Kubernetes Pod,通过emptyDir 卷实现两个容器间的数据共享。
这是一个典型的主容器 + 辅助容器模式:
- 主容器(write):循环写入数据到共享目录。
- 辅助容器(read):实时读取并输出共享目录中的数据。
- emptyDir 卷:作为临时存储,连接两个容器的数据通路。
主容器(写入数据)
- name: write image: centos command: ["bash","-c","for i in {1..100};do echo $i >> /data/hello;sleep 1;done"] volumeMounts: - name: data mountPath: /data
- 每秒向
/data/hello
文件追加一个数字(从 1 到 100)。 >>
:追加写入,避免覆盖原有内容。/data
目录映射到 emptyDir 卷(data
),确保数据可被另一个容器访问。
辅助容器(读取数据)
- name: read image: centos command: ["bash","-c","tail -f /data/hello"] volumeMounts: - name: data mountPath: /data
- 使用
tail -f
实时监控并输出/data/hello
文件的更新内容。 tail -f
:持续跟踪文件变化,新内容会立即显示。- 与主容器挂载同一 emptyDir 卷,确保能读取到写入的数据。
emptyDir 卷(数据共享核心)
volumes: - name: data emptyDir: {}
- 在 Pod 内创建一个临时目录,供所有容器共享。
- 生命周期与 Pod 绑定:Pod 创建时生成,删除时销毁。
- 容器间可见:所有挂载该卷的容器可读写同一目录。
- 默认存储在节点磁盘:也可配置为内存存储(
medium: Memory
)。
工作流程
- Pod 启动:Kubernetes 创建 Pod,同时初始化 emptyDir 卷(初始为空)。
- 数据写入:
write
容器启动,执行循环脚本。- 每秒向
/data/hello
写入一个数字(如1
、2
、3
…)。
- 数据读取:
read
容器启动,执行tail -f /data/hello
。- 实时监控文件变化,新写入的数字会立即显示在
read
容器的日志中。
- 结果验证:
kubectl logs pod1 read # 查看read容器的日志,会看到递增的数字
执行后,可以看到两个文件data是共享的,测试可以看到两个文件是共享的。

empryDir在k8s中的存储位置
一般在 /var/lib/kubelet/pods/{pod-id}/volumes/kubernetes.io~empty-dir
下。

四、hostPath
hostPath卷: 挂载Node文件系统(Pod所在节点)上文件或者目录到Pod中的容器。
应用场景: Pod中容器需要访问宿主机文件。但不适合做持久化。
示例
vi hostPath.yaml
apiVersion: v1 kind: Pod metadata: name: pod2 spec: containers: - name: write # 业务容器(写数据) image: centos command: ["bash","-c","for i in {1..1000};do echo $i >> /data/hello;sleep 1;done"] volumeMounts: - name: data mountPath: /ttt volumes: - name: data hostPath: path: /tmp type: Directory # 文件类型:定义node主机上的 /tmp 是文件夹还是文件。
测试,在 pod 的 /ttt
目录下写入一个123文件后,查看此pod所处节点

# 查看 pod 所在的 node kubectl get pods -o wide

进入node1节点tmp下查看

五、emptyDir 与 hostPath 的区别
相同点
- emptyDir 和 hostPath 类型都可用于 container 之间数据共享。
区别
- emptyDir 是 pod 级别的。pod 销毁后, emptyDir 也会销毁。
- emptyDir 被初始化后里面是空的。所有在同一个 pod 中的 container 都可以通过挂载emptyDir后对其进行读写操作。
- emptyDir 主要用于同一个 pod 中的 container 之间共享数据。(如:log 日志目录)
- emptyDir 使用 emptyDir 这种 volume 时,一个pod中一般会有2个以上的 container。
- hostPath 是 node 级别的,node 是持久化的。一个 node 可以创建 N 个 pod 。
emptyDir
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-app image: my-app-image volumeMounts: - mountPath: /cache name: cache-volume - name: sidecar image: busybox volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: {}
hostPath
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-app image: my-app-image volumeMounts: - name: test-volume mountPath: /test-pd volumes: - name: test-volume hostPath: path: /data # directory on host type: Directory # optional # type: # Other values for type are 'DirectoryOrCreate', 'File', 'FileOrCreate'.