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核心关系

  1. 集群存在若干PV(真实存储资源),具备不同容量、性能、访问规则;

  2. 用户创建PVC提交存储需求;

  3. K8s自动匹配符合条件的PV,完成绑定(Bound);

  4. 绑定后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重启数据不丢失:

  1. 创建PVC:提交PVC配置,声明存储容量、访问模式;

  2. 绑定PV:集群动态创建或匹配现有PV,PVC状态变为Bound;

  3. Pod挂载使用:Deployment创建Pod,挂载PVC,容器业务数据写入底层PV;

  4. 删除Pod:Pod销毁,但PVC、PV为独立集群资源,不会同步删除,底层数据完整保留;

  5. 重建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. 全文核心总结

  1. 存储核心痛点:Pod生命周期短暂,容器内本地数据会随Pod删除丢失,核心业务必须依赖独立存储卷;

  2. 临时存储方案:emptyDir用于Pod内多容器临时数据共享,hostPath仅用于本地测试,生产均不推荐;

  3. 生产核心方案:PVC+PV实现数据持久化,云环境动态供应无需手动管理底层存储;

  4. 核心访问模式:RWO单Pod读写(数据库主流)、ROX多只读、RWX多读写(共享存储);

  5. 业务适配规则:无状态应用无需持久化,有状态应用必须搭配PVC,多副本有状态服务需使用StatefulSet;

  6. 数据安全关键:生产环境关注PV回收策略,核心数据建议开启Retain模式,避免误删丢失。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐