讲解
容器的文件系统是临时的:容器重启(同一 Pod 内)文件还在,但 Pod 删除重建就全没了;而且同一 Pod 里多个容器之间想共享文件也没门路。Volume(存储卷)解决这两个问题:它是 Pod 级别声明、容器里挂载使用的目录,生命周期跟着 Pod 走。Kubernetes 支持几十种卷类型,但学习阶段掌握三个就够用:emptyDir、hostPath、以及下一章的 PersistentVolumeClaim。
emptyDir 是「Pod 级临时目录」:Pod 创建时在节点上开一个空目录,Pod 删除时随之一同删除;容器崩溃重启不影响它(所以它能扛住容器重启,扛不住 Pod 删除)。经典用途是同 Pod 多容器共享文件——比如一个容器产出静态页面,另一个容器(nginx)对外服务。hostPath 是把节点宿主机上的目录挂进 Pod,数据跟着节点走,Pod 调度到别的节点就看不到了——它主要给系统组件用(比如节点日志采集器读 /var/log),业务应用用它等于把自己钉死在节点上,要非常谨慎。
卷的声明分两层,这是初学者最容易绕晕的地方:spec.volumes 里「声明」卷(名字 + 类型 + 来源),每个容器的 volumeMounts 里「挂载」卷(卷名 + 容器内路径)。同一声明可以被多个容器挂到不同路径。挂载点还有个细节:容器内路径下原有内容会被卷遮住(不是删除,是看不见),所以把卷挂到镜像里有数据的目录前要想清楚。
示例
emptyDir 共享实战:writer 容器每 5 秒把时间写进共享目录,web 容器(nginx)把同一目录对外服务:
# wait: pod/ohmydocs-verify-share
apiVersion: v1
kind: Pod
metadata:
name: ohmydocs-verify-share
labels:
app: ohmydocs-verify-share
spec:
containers:
- name: writer
image: busybox:1.36
command:
- sh
- -c
- |
echo '<h1>emptyDir 共享卷</h1>' > /data/index.html
while true; do date >> /data/heartbeat.log; sleep 5; done
volumeMounts:
- name: shared
mountPath: /data
- name: web
image: nginx:1.27-alpine
ports:
- containerPort: 80
volumeMounts:
- name: shared
mountPath: /usr/share/nginx/html
volumes:
- name: shared
emptyDir: {}
两个容器看到的是同一个目录:web 容器能服务 writer 写的页面,heartbeat 在持续增长:
kubectl exec ohmydocs-verify-share -c web -- wget -qO- http://127.0.0.1/
kubectl exec ohmydocs-verify-share -c writer -- tail -2 /data/heartbeat.log
hostPath 的样子(把节点目录挂进容器;它把 Pod 绑死在节点文件系统上,此处只做客户端校验,不真的挂节点目录):
# 仅示意:hostPath 依赖节点本地目录,可移植性差且有安全风险,仅演示字段结构
apiVersion: v1
kind: Pod
metadata:
name: ohmydocs-verify-hostpath
spec:
containers:
- name: busybox
image: busybox:1.36
command: ["sleep", "3600"]
volumeMounts:
- name: node-logs
mountPath: /node-logs
readOnly: true
volumes:
- name: node-logs
hostPath:
path: /var/log
type: Directory
常见坑
- 指望 emptyDir 持久化:Pod 一删 emptyDir 就没——它只是「容器重启安全」的临时空间,要持久化用下一章的 PVC。
- volumeMounts 名字对不上 volumes:挂载引用了不存在的卷名,Pod 直接创建失败;声明与挂载的名字必须一致。
- 挂载遮住镜像内容:把卷挂到 /usr/share/nginx/html 这类镜像自带内容的目录,原内容被遮住——用 emptyDir 时首页变 403/404 多半是这里。
- 业务用 hostPath:数据跟着节点漂移、多副本互相看不见对方数据,还有提权风险;除非写节点级 agent,别碰。
小结
Volume 是 Pod 级目录:emptyDir 临时共享、hostPath 绑节点(慎用)、声明与挂载分两层。真正的持久化要让存储的生命周期独立于 Pod——下一章 PersistentVolume 与 PersistentVolumeClaim。