CFN Cloud
2025-10-08

Kubernetes Volume 基础:临时卷、持久卷与数据生命周期

从 emptyDir 到持久卷,理解 Kubernetes 常见 Volume 类型、数据是否持久,以及不同场景下的选型方式。

容器天然是临时的,但应用经常需要文件、缓存、配置挂载,或者真正持久化的数据。Volume 的作用,就是把容器级运行环境变成更接近真实业务需求的运行环境。

为什么 Volume 这么重要

  • 容器会重启,但数据未必能丢
  • 一个 Pod 里的多个容器可能要共享文件
  • 配置和密钥通常更适合挂成文件
  • 存储选型会直接影响性能、可靠性和恢复策略

最值得先理解的几类 Volume

  • emptyDir:跟随 Pod 生命周期的临时存储
  • configMap / secret:挂载配置和密钥
  • persistentVolumeClaim:向集群申请持久卷
  • hostPath:直接挂宿主机目录,少数场景有用,但非常容易被用错

emptyDir:临时,但很实用

emptyDir 很适合:

  • 缓存
  • 临时工作目录
  • sidecar 之间共享文件
  • 中间处理产物
volumes:
  - name: cache
    emptyDir: {}
volumeMounts:
  - name: cache
    mountPath: /cache

它会随着 Pod 消失而一起消失。所以它要么刚好是你需要的,要么正好是你不能用的。

配置和 Secret 挂载

Volume 也是很多工作负载接收配置的主要方式:

volumes:
  - name: app-config
    configMap:
      name: app-config
  - name: app-secret
    secret:
      secretName: app-secret
volumeMounts:
  - name: app-config
    mountPath: /etc/app/config
    readOnly: true
  - name: app-secret
    mountPath: /etc/app/secret
    readOnly: true

这部分和 kubernetes-quickstart-configmap-secret.md 是天然连着看的,那篇会更深入讲配置与密钥生命周期。

基于 PVC 的持久存储

当数据必须在 Pod 被替换后还保留下来时,通常就要进入 PVC 这条链路:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

然后在 Pod 中挂载:

volumes:
  - name: data
    persistentVolumeClaim:
      claimName: data-pvc
volumeMounts:
  - name: data
    mountPath: /var/lib/app

这条链路更完整的解释在:

  • kubernetes-quickstart-pv-pvc.md
  • kubernetes-quickstart-storageclass.md

第一个该先做的选择:临时还是持久

在选 Volume 之前,先回答一个问题:

  • 如果 Pod 没了,这份数据能不能一起没?

如果能,那 emptyDir 很可能就够。

如果不能,那就要进入 PVC、StorageClass、回收策略、备份与恢复这些更完整的存储话题。

只要先把这一步分清,很多选型问题会简单很多。

一个 Pod 内共享数据的典型模式

如果多个容器需要共享同一份文件,可以挂同一个卷:

apiVersion: v1
kind: Pod
metadata:
  name: producer-consumer
spec:
  volumes:
    - name: shared
      emptyDir: {}
  containers:
    - name: producer
      image: busybox
      command: ["sh", "-c", "while true; do date >> /data/out.txt; sleep 5; done"]
      volumeMounts:
        - name: shared
          mountPath: /data
    - name: consumer
      image: busybox
      command: ["sh", "-c", "tail -f /data/out.txt"]
      volumeMounts:
        - name: shared
          mountPath: /data

这在 sidecar、日志处理和内容生成场景里都很常见。

hostPath:能用,但很容易用出问题

hostPath 是直接把宿主机目录挂进 Pod。

少数场景下它很方便,但也有明显代价:

  • 可移植性差
  • 把工作负载和节点强绑定
  • 容易带来宿主机级安全风险

如果你并不强控制节点生命周期,hostPath 通常不该是第一选择。

Volume 和有状态工作负载的关系

很多有状态系统需要的不只是“有卷”,还需要:

  • 稳定身份
  • 稳定 DNS
  • 可预测的更新顺序

所以存储这条线,通常会自然连到:

  • kubernetes-quickstart-pv-pvc.md
  • kubernetes-quickstart-storageclass.md
  • kubernetes-quickstart-statefulset.md

常见故障模式

Pod 一直 Pending

很多时候是 PVC 绑定或 StorageClass 相关问题。

挂载失败

这时候可能已经进入 CSI、节点权限或后端存储本身的问题域了。

重启后数据不见了

常见原因是本该持久化的数据被放进了临时卷。

权限不对

通常是文件系统属主、securityContext 或挂载路径本身不匹配。

常用排障命令

kubectl describe pod <pod-name>
kubectl describe pvc <pvc-name>
kubectl get pv

更深层的持久化存储问题,很多时候还是要看 CSI 控制器日志,而不只是看 Pod 事件。

FAQ

Q: 什么情况下用 emptyDir,什么情况下该上 PVC? A: 如果数据跟着 Pod 一起消失也没关系,就用 emptyDir;如果数据必须跨 Pod 生命周期保留,就该看 PVC。

Q: Volume 等于备份吗? A: 不等于。Volume 解决的是共享或持久化,备份和恢复仍然要有独立方案。

Q: hostPath 什么时候算坏主意? A: 在多数需要可移植、可迁移或多租户隔离的环境里,它通常都不是理想方案,因为它和宿主机耦合太深。

下一步阅读

  • 接着读 kubernetes-quickstart-pv-pvc.md,理解持久化存储契约
  • 再读 kubernetes-quickstart-storageclass.md,理解动态供给和平台侧策略
  • 如果要进入有状态工作负载,继续读 kubernetes-quickstart-statefulset.md

收个尾

Volume 相关问题看起来很多,其实第一步通常都很简单:先分清你面对的是“临时数据”还是“持久数据”。这一步一旦想明白,后面的存储设计会顺很多。

参考链接