DevOps 入门系列:K8s 持久化存储(PVC)
K8s存储——解决Pod重启丢数据问题
前置知识:需要读者掌握Docker数据卷概念,以及Kubernetes的Pod、Deployment、Service等核心资源。本文无具体执行命令,仅讲解存储相关概念、原理及YAML核心字段。
1. 一个现实问题:Pod 重启后,数据去哪了?
Pod的生命周期是短暂的。在Deployment管理模式下,删除旧Pod后,K8s会自动创建新Pod替代,但存在一个核心问题:
Pod容器内写入的所有数据,会随Pod删除彻底消失。
典型场景:
-
业务应用:容器内生成业务文件
/app/data/report.txt -
MySQL容器:数据库数据存储在容器内
/var/lib/mysql -
Nginx容器:用户上传资源存储在容器内
/usr/share/nginx/html/uploads
当Pod因滚动更新、节点故障、手动删除被销毁后,新Pod启动后,上述所有数据都会彻底丢失。
2. 解决方案:Volume(数据卷)
Volume是K8s解决数据持久化的核心机制,核心作用是将存储资源与Pod生命周期解耦,让 Pod 里存的数据,不会因为 Pod 被删掉就跟着消失,让数据独立于Pod存在。
定义:Volume就是挂载到Pod上的独立“硬盘”,Pod可正常读写该硬盘,Pod删除销毁后,硬盘数据可根据类型保留。
3. Volume的类型:从临时存储到持久存储
K8s支持多种Volume类型,核心可根据数据是否随Pod保留分为两大类,适配不同业务场景。
3.1 临时类型(Pod删除,数据同步删除)
| 类型 | 说明 | 典型用途 |
|---|---|---|
| emptyDir | Pod分配节点时自动创建空目录,Pod销毁后目录及数据彻底清空 | 同一Pod内多容器共享临时数据 |
| hostPath | 直接挂载宿主机指定目录至容器内 | 单机测试、访问宿主机本地文件(生产环境慎用) |
3.2 持久类型(Pod删除,数据保留)
| 类型 | 说明 | 典型用途 |
|---|---|---|
| PersistentVolumeClaim(PVC) | 主动申请集群存储资源,与底层存储硬件解耦,标准化持久存储 | 生产环境核心持久化方案,绝大多数业务场景适配 |
| CSI / 云存储 | 对接云厂商磁盘、NAS、对象存储等底层资源 | 云上生产环境高可用、高可靠存储场景 |
在大部分情况下,持久化需求仅需使用PVC,可自动绑定云硬盘、网络存储等底层资源,无需手动维护底层存储细节。
4. emptyDir:最简单的临时存储
4.1 核心概念与适用场景
emptyDir是K8s最基础的临时存储卷,Pod调度到节点时自动创建空目录,Pod运行期间目录持续存在,Pod删除则数据永久丢失。
作用:解决同一Pod内多个容器的数据共享问题。
经典场景:
业务主容器写入日志至固定目录,Sidecar日志收集容器读取同目录日志,完成日志采集、转发至日志中心的流程。
4.2 使用方式(YAML)
在Deployment的Pod模板中声明emptyDir卷,多个容器挂载同一卷即可实现数据共享。
spec:
template:
spec:
containers:
- name: app-container
image: my-app:v1
volumeMounts:
- name: shared-data
mountPath: /app/data # 业务容器内挂载路径
- name: sidecar-container
image: log-collector:v1
volumeMounts:
- name: shared-data
mountPath: /logs # 日志容器内挂载路径
volumes:
- name: shared-data
emptyDir: {} # 声明为emptyDir临时卷
4.3 特性与使用场景
-
基础写法
emptyDir: {},K8s自动创建空目录,无需额外配置 -
支持内存挂载:配置
emptyDir.medium: "Memory",数据存入内存,读写速度更快,但占用节点内存,Pod删除数据同样丢失 -
适用场景:临时缓存、中间计算结果、日志中转、无需持久化的临时数据
注意:emptyDir仅适用于临时场景,数据库、用户文件等核心数据绝对不能使用。
5. PV与PVC:真正的生产级持久存储
5.1 为什么emptyDir无法满足生产需求?
emptyDir核心短板:Pod销毁,数据彻底丢失,完全无法适配生产核心业务场景:
-
有状态服务:MySQL、PostgreSQL等数据库,数据必须永久保留
-
用户资源:用户上传头像、附件、图片等业务数据
-
运维数据:需要长期归档的业务日志、监控数据
-
动态配置:应用运行中动态生成、重启后需保留的配置文件
这类场景的核心需求:Pod删除、重启、迁移后,数据不丢失,新Pod可重新读取原有数据。
5.2 PV与PVC核心概念及关系
PV和PVC是K8s持久化存储的核心搭档,二者解耦协作。
| 概念 | 全称 | 核心定义 | 通俗类比 |
|---|---|---|---|
| PV | PersistentVolume(持久卷) | 集群内真实存在的存储资源,可由管理员预先创建或云厂商自动生成,包含容量、读写模式、存储类型等属性 | 已接入服务器的物理硬盘/云硬盘(10GB/100GB、SSD/HDD) |
| PVC | PersistentVolumeClaim(持久卷申请) | 用户向集群发起的存储资源申请,声明所需存储容量、读写模式、存储类型等需求 | 存储资源申请单:需要10GB可读写硬盘空间 |
PV与PVC核心关系:
-
集群存在若干PV(真实存储资源),具备不同容量、性能、访问规则;
-
用户创建PVC提交存储需求;
-
K8s自动匹配符合条件的PV,完成绑定(Bound);
-
绑定后Pod可通过PVC挂载使用底层PV存储。
重点:云环境(阿里云ACK、AWS EKS等)支持动态供应,开发者只需创建PVC,集群会自动创建PV并绑定,无需管理员手动维护PV。日常开发仅需操作PVC!
5.3 PVC核心YAML及字段详解
PVC配置简洁,核心只需声明容量与访问模式,可选指定存储类型。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: flask-data-pvc # PVC名称,供Pod挂载引用
spec:
accessModes:
- ReadWriteOnce # 存储访问模式
resources:
requests:
storage: 10Gi # 申请10GB存储空间
# storageClassName: ssd # 可选:指定存储类型(SSD/HDD)
核心字段释义:
| 字段 | 含义 | 常用值 |
|---|---|---|
| accessModes | 卷的多Pod访问权限规则 | ReadWriteOnce、ReadOnlyMany、ReadWriteMany |
| resources.requests.storage | 申请的最小存储空间 | 10Gi、50Gi、100Gi等 |
| storageClassName | 指定存储类型(高性能SSD/普通HDD) | standard(普通盘)、ssd(高速盘) |
访问模式详细说明:
| 访问模式 | 权限含义 | 典型场景 |
|---|---|---|
| ReadWriteOnce(RWO) | 仅允许单个Pod读写挂载 | MySQL、PostgreSQL等单副本数据库(云上云盘默认支持) |
| ReadOnlyMany(ROX) | 允许多个Pod只读挂载 | 公共配置文件、静态资源分发 |
| ReadWriteMany(RWX) | 允许多个Pod读写挂载 | NAS共享存储、多节点文件读写场景 |
生产环境常用 ReadWriteOnce,大多数云上块存储(云硬盘)仅支持该模式。
5.4 Pod/Deployment挂载PVC使用方式
在Deployment中使用PVC只需两步:声明PVC类型存储卷、配置容器内挂载路径。
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-with-storage
spec:
replicas: 1 # RWO模式仅支持单Pod挂载,副本数必须为1
selector:
matchLabels:
app: flask-app
template:
metadata:
labels:
app: flask-app
spec:
containers:
- name: flask-container
image: your-registry/flask-app:v1
volumeMounts:
- name: data-volume # 引用下方定义的存储卷名称
mountPath: /app/data # 容器内数据挂载目录
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: flask-data-pvc # 关联已创建的PVC名称
注意事项:
-
PVC为RWO模式时,Deployment副本数必须为1,多副本会导致新增Pod因卷占用失败,处于Pending状态;
-
多Pod共享读写场景,需使用支持RWX模式的存储(NFS、NAS、CephFS等)。
5.5 PVC完整数据生命周期
通过完整流程,清晰理解PVC如何实现Pod重启数据不丢失:
-
创建PVC:提交PVC配置,声明存储容量、访问模式;
-
绑定PV:集群动态创建或匹配现有PV,PVC状态变为Bound;
-
Pod挂载使用:Deployment创建Pod,挂载PVC,容器业务数据写入底层PV;
-
删除Pod:Pod销毁,但PVC、PV为独立集群资源,不会同步删除,底层数据完整保留;
-
重建Pod:新Pod创建并挂载同一PVC,可直接读取历史数据,实现数据持久化。
5.6 StorageClass(存储类)概念
StorageClass用于定义不同规格、性能的存储类型,实现存储资源的精细化选择,适配不同业务性能需求。
| 存储类名称 | 存储类型 | 性能 | 成本 |
|---|---|---|---|
| standard | 普通HDD云硬盘 | 低 | 便宜 |
| ssd | SSD高速云硬盘 | 高 | 中等 |
| premium | 超高性能SSD硬盘 | 极高 | 昂贵 |
PVC中通过 storageClassName 指定存储类型,未配置时默认使用集群默认存储类(普通HDD)。云上集群均已预配置存储类,开发者直接选用即可。
5.7 有状态与无状态应用存储选型
| 应用类型 | 核心特性 | 是否需要PVC |
|---|---|---|
| 无状态应用 | 无本地持久化数据,可随时销毁重建(网关、前端、普通API服务) | 不需要 |
| 有状态应用 | 依赖本地数据,重启后数据不可丢失(数据库、消息队列、文件服务) | 必须使用 |
控制器适配说明:
-
Deployment + PVC:适用于单副本有状态应用(测试、小型业务);
-
StatefulSet:专门管理多副本有状态应用(数据库集群、消息队列集群),可为每个Pod分配独立PVC,拥有稳定网络标识与名称。
5.8 常见问题解答
Q1:PVC和PV是否需要手动创建?
云上K8s集群默认开启动态供应,开发者只需创建PVC,集群自动调用云厂商API创建PV并完成绑定,无需手动操作PV。
Q2:删除PVC后数据是否丢失?
由PV的**回收策略(persistentVolumeReclaimPolicy)**决定:
-
Delete(云上默认):PVC删除,PV及底层云硬盘同步删除,数据丢失;
-
Retain:PVC删除后,PV保留、数据留存,需管理员手动清理。
生产环境删除PVC前,建议修改PV回收策略为Retain,防止误删数据。
Q3:单个Pod能否挂载多个PVC?
可以。在Pod的volumes数组中配置多个PVC关联配置,分别挂载到容器不同目录即可,适配多类型数据隔离存储场景。
6. 主流Volume类型对比及选型指南
6.1 核心特性对比表
| 特性 | emptyDir | hostPath | PVC |
|---|---|---|---|
| 数据生命周期 | 随Pod删除销毁 | 随宿主机文件留存 | 独立于Pod、节点,永久持久化 |
| Pod删除数据保留 | ❌ 否 | ✅ 是 | ✅ 是 |
| 跨节点调度可用性 | ❌ 新节点重建空目录 | ❌ 仅原节点可访问 | ✅ 支持跨节点挂载 |
| 多Pod共享能力 | 仅同Pod内多容器共享 | 仅同节点Pod共享 | 由访问模式决定(支持跨节点共享) |
| 读写性能 | 极高(本地磁盘/内存) | 极高(本地磁盘) | 中等(网络存储,随云盘类型提升) |
| 生产适用场景 | 临时缓存、日志中转 | 仅测试环境,生产禁用 | 所有生产持久化场景 |
6.2 业务选型决策树
你的数据需要持久保存吗?
│
├── 否 → 使用 emptyDir(临时缓存、Pod内容器数据共享)
│
└── 是 → 数据需要跨节点/多Pod共享访问吗?
│
├── 否(单Pod业务,如单体数据库)→ PVC + ReadWriteOnce
│
└── 是(多Pod共享读写,如公共文件存储)→ PVC + ReadWriteMany(需存储后端支持)
总结:生产环境99%的持久化需求,直接选用PVC即可,emptyDir、hostPath仅用于特殊临时场景。
7. PVC持久化完整工作流程
第一步:准备存储资源
开发者创建PVC → 集群根据PVC需求动态创建/匹配PV → PVC与PV绑定(Bound),存储资源就绪。
第二步:Pod挂载使用存储
Deployment通过PVC名称关联存储卷 → Pod启动后挂载指定容器目录 → 业务写入的数据持久化存储在底层PV(云硬盘),而非容器本地目录。
第三步:Pod销毁数据留存
Pod因更新、删除、故障销毁 → PVC、PV资源不删除,底层数据完整保留 → 新Pod重建并挂载同一PVC,自动恢复历史数据。
8. 进阶核心概念补充
8.1 有状态应用核心特性
有状态应用区别于普通无状态应用,核心需求:
-
数据持久化:重启、重建后数据不丢失;
-
稳定标识:Pod名称、网络DNS固定,不会随机变化;
-
独立存储:集群部署、主从集群需每个Pod独享存储资源。
K8s通过StatefulSet管理有状态应用,适配数据库、消息队列、缓存集群等场景。
8.2 PV回收策略详解
| 回收策略 | 执行行为 | 适用场景 |
|---|---|---|
| Delete | PVC删除后,PV及底层存储同步删除,数据彻底清空 | 测试环境、临时业务,数据无留存价值 |
| Retain | PVC删除后,PV保留、数据留存,需手动清理 | 生产核心业务,防止误删数据 |
8.3 存储性能选型对比
| 存储类型 | 性能 | 持久性 | 跨节点访问 | 适用场景 |
|---|---|---|---|---|
| 本地存储(emptyDir/hostPath) | 极高 | 差(节点故障数据丢失) | 不支持 | 临时高速计算、本地缓存 |
| 云硬盘(PVC-RWO) | 中等/高(SSD高性能) | 极高(多副本备份) | 单Pod挂载 | MySQL、Redis等单副本数据库 |
| 云NAS(PVC-RWX) | 中等(轻微网络延迟) | 极高 | 支持多Pod跨节点共享 | 静态资源共享、多节点文件读写 |
9. 全文核心总结
-
存储核心痛点:Pod生命周期短暂,容器内本地数据会随Pod删除丢失,核心业务必须依赖独立存储卷;
-
临时存储方案:emptyDir用于Pod内多容器临时数据共享,hostPath仅用于本地测试,生产均不推荐;
-
生产核心方案:PVC+PV实现数据持久化,云环境动态供应无需手动管理底层存储;
-
核心访问模式:RWO单Pod读写(数据库主流)、ROX多只读、RWX多读写(共享存储);
-
业务适配规则:无状态应用无需持久化,有状态应用必须搭配PVC,多副本有状态服务需使用StatefulSet;
-
数据安全关键:生产环境关注PV回收策略,核心数据建议开启Retain模式,避免误删丢失。
更多推荐




所有评论(0)