C31

K8s 存储

点击正文段落选定收藏或划线位置;未选定时使用屏幕内第一段。

课内目录

1 K8s 存储要回答什么

订单 API 已经能通过 Service 接收请求,容器镜像也能重复部署。现在,运营人员希望下载每天生成的订单导出文件。开发者把文件写进容器里的 /data/exports,测试时能够下载,重新发布后却找不到了。问题不在文件名,而在于方案没有回答:文件存在哪里,它的寿命由谁决定,接手请求的新 Pod 能不能访问它。

容器可写层适合程序运行时的临时改动,不能承担跨 Pod 的数据承诺。Pod 是运行应用的调度单位,可以被控制器重建;新建的 Pod 即使使用相同镜像,也不会自动获得旧 Pod 的文件。K8s 存储首先要把“运行程序的位置”和“保存数据的资源”分开,再说明它们如何连接。容器路径看起来相同,并不表示背后是同一份数据。

本课让订单 API 把正式订单记录保存在独立数据库,把待下载的导出文件放到持久卷,把能够重新计算的排序结果放到临时目录。这样区分不是按文件大小,而是按丢失后果:缓存丢失可以重算,导出文件丢失可能需要补生成,正式记录丢失则影响业务正确性。选择存储之前,先明确数据能否重建,以及谁负责重建。

接下来要回答 4 个问题。第 1,文件是否需要跨越容器重启和 Pod 重建。第 2,几个应用实例需要怎样访问它,是否可能同时写。第 3,节点或可用区发生故障后,数据在哪里,计算资源还能在哪里启动。第 4,删除应用、删除存储申请和删除后端数据分别会发生什么。容量只是其中的条件,不能代替这些生命周期问题。

应用、存储申请与故障域的关系
应用、存储申请与故障域的关系

图中控制面处理申请和关联,节点负责让卷进入容器路径,后端负责实际保存数据。它们处在不同位置,也可能由不同团队管理。Pod 显示 Running 只说明运行状态,不能证明导出任务已经成功写入;PVC 显示 Bound 只说明关联已建立,也不能证明容器有写权限。观察时必须沿着这条链逐段确认。

还要区分持久化与保护。持久化表示数据寿命不必随着某个 Pod 结束,备份则为误删、损坏等情况保留可恢复的副本。后端提供副本也不能自动解决应用误覆盖。K8s 可以组织存储的申请和使用,但不会替应用决定哪些内容值得保存,也不会凭空赋予普通文件多实例事务能力。

2 Volume、PVC 与 StorageClass 边界

Volume 是 Pod 声明的卷入口,容器再用 volumeMounts 将它挂到指定路径。卷可能来自临时目录、配置资源,也可能来自持久存储。因而“用了 Volume”并不等于“数据已经持久化”。emptyDir、hostPath 和引用 PVC 的卷都能出现在 Pod 的 volumes 中,生命周期和可迁移性却差别很大。

PVC,中文常称持久卷声明,是命名空间内的申请对象。应用通过它表达需要多少容量、什么访问模式、使用哪类存储。Pod 使用 PVC 的名字,不必把后端磁盘标识直接写进部署配置。Pod 与 PVC 必须位于同一命名空间;把另一个命名空间中的同名 PVC 当成当前申请,会得到完全不同的结果。

PV,即持久卷,是集群范围内代表可用存储的资源对象。它描述实际卷的接入信息及相关约束,与 PVC 建立绑定关系。通常 1 个 PV 绑定 1 个 PVC,但同一个 PVC 能否供多个 Pod 使用,还要看访问模式、节点位置和驱动能力。不要把 PV 与 PVC 的绑定关系,误读成所有场景都只允许 1 个 Pod。

StorageClass 是供给规则的入口。它指定使用哪个供给器,以及绑定时机、回收策略等参数。管理员可能提供面向不同性能或可用区需求的类别,但类别名称本身不构成性能保证。应用应依据实际约定选择类别,而不是猜测 fast 这样的名字意味着多高吞吐或多强可靠性。供给器通常通过 CSI 驱动与后端连接;本课只把 CSI 理解为接入接口,不展开内部组件。

Volume、PVC、PV 与 StorageClass 的责任边界
Volume、PVC、PV 与 StorageClass 的责任边界

可以把 Pod 看成“我要在这个路径使用数据”,PVC 看成“我要这样的存储”,PV 看成“这份申请对应这块资源”,StorageClass 看成“按什么规则准备资源”。其中,StorageClass 不是装文件的目录,PVC 也不保存文件正文。删除和重建这些对象是否保留数据,取决于对象关系、回收策略与后端行为,不能只看资源名称是否相同。

申请容量还需要读懂边界。例如申请 5Gi,表示希望获得至少满足该请求的容量,不是程序只能生成 5Gi 业务数据的完整管理方案。实际可用空间、文件系统开销、扩容支持和容量告警需要另行确认。省略 storageClassName 可能使用默认类别;显式设置为空字符串通常表示不选择动态供给类别。这 2 种写法不能混为一谈。

对于订单导出服务,部署文件只引用约定的 PVC,平台维护可选的 StorageClass,存储管理者说明后端与恢复边界。这样应用升级可以更换镜像,而不需要同时更换数据资源。分开职责并不意味着可以不沟通:路径、权限、容量和删除责任仍然需要写进同一份方案。

3 动态供给、绑定与回收策略

静态供给是先由管理员准备 PV,再让 PVC 匹配它。动态供给则由 PVC 触发,根据 StorageClass 创建后端卷及相应 PV。动态供给减少了逐块准备资源的工作,但申请仍然可能因配额不足、类别不存在、驱动不可用或拓扑条件不满足而等待。创建 PVC 成功,只代表 API 接受了对象,不代表后端资源已经准备好。

正常链路可以分成申请、选择或创建资源、绑定、安排 Pod、附加与挂载、应用读写几个阶段。对于需要附加到节点的块存储,附加和节点上的文件系统挂载也是不同操作;对于部分网络文件存储,则未必存在相同的附加流程。不要要求所有后端都出现完全相同的事件,应该识别各阶段要完成的责任。

volumeBindingMode 影响绑定时机。Immediate 倾向于在 PVC 创建后就处理绑定与供给;WaitForFirstConsumer 会结合首个使用者的调度条件决定合适的位置。后者常用于有拓扑约束的存储:如果卷只能在某个可用区使用,就需要把节点选择和卷的位置放在一起考虑。此时 PVC 暂时 Pending 可能是在等待消费者,并非已经出错。

动态供给与首次消费者参与的流程
动态供给与首次消费者参与的流程

绑定后,Pod 仍需要满足节点和卷的兼容条件,驱动需要完成相应操作,容器还需要拥有目录访问权限。一个阶段成功不会替后面的阶段作保证。例如 PVC 已经 Bound,但旧节点仍持有卷的附加关系,新节点可能暂时无法接管。此时反复重建 PVC 往往会扩大问题,而不是缩短等待时间。

回收策略描述 PVC 被删除、PV 被释放后的处置。常见的 Delete 会在驱动支持并完成处理时删除相应后端资源;Retain 通常保留后端数据,交给管理员处理后续恢复或复用。动态供给产生的 PV 通常从 StorageClass 获得初始策略,实际操作前应查看目标 PV 当前的策略。修改类别并不意味着已有 PV 自动得到相同变更。

Retain 也不等于“重新创建同名 PVC 就自动接回原数据”。旧 PV 的状态、绑定信息、后端资源和重新关联步骤都需要核实。Delete 更不应该被解释为业务级安全擦除证明,它表达的是资源回收行为。对于本课的导出文件,应明确哪些文件可补生成,哪些需要备份,并在删除申请前确认后端数据的处置责任。

4 动手:对照一次挂载失败的事件链

用户常把“文件路径用不了”统称为挂载失败,但排查时必须判断链路走到了哪里。本实验故意让 Pod 引用不存在的 PVC,观察它为什么还没进入真正的挂载阶段。随后修正引用,让驱动继续处理。目标是练习用事件定位边界,而不是依靠反复重启碰运气。实验仅使用专用命名空间和可丢弃的数据。

准备条件是:集群已有可动态供给文件系统卷的 StorageClass,当前身份能在实验命名空间创建 PVC 和 Deployment,节点能够拉取示例镜像。下面的 REPLACE_WITH_CLASS 必须替换为已确认可用的类别名。没有合适类别时,应先和平台确认条件;空等一个不会供给的申请,不能帮助验证后面的挂载流程。

apiVersion: v1
kind: Namespace
metadata:
  name: c31-storage-lab
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: exports-data
  namespace: c31-storage-lab
spec:
  storageClassName: REPLACE_WITH_CLASS
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: exports-demo
  namespace: c31-storage-lab
spec:
  replicas: 1
  selector:
    matchLabels:
      app: exports-demo
  template:
    metadata:
      labels:
        app: exports-demo
    spec:
      containers:
        - name: reader
          image: busybox:1.36
          command: ["sh", "-c", "sleep 86400"]
          volumeMounts:
            - name: exports
              mountPath: /data/exports
      volumes:
        - name: exports
          persistentVolumeClaim:
            claimName: exports-dtaa

把清单保存为 c31-storage-lab.yaml,替换类别后执行。exports-dtaa 是故意留下的错误名称;真正申请的名字是 exports-data。先保留这个差异,以便观察证据。

kubectl apply -f c31-storage-lab.yaml
kubectl -n c31-storage-lab get pods,pvc
kubectl -n c31-storage-lab describe pod -l app=exports-demo
kubectl -n c31-storage-lab describe pvc exports-data
kubectl -n c31-storage-lab get events --sort-by=.metadata.creationTimestamp

预期 Pod 处于 Pending,事件提示找不到所引用的 PVC,常见原因字段是 FailedScheduling。事件文字会随版本变化,重点是它指出的对象名。此时容器还没有在目标节点完成启动,不能归因于目录写权限。正确 PVC 若使用延迟绑定,可能仍等待消费者;若采用立即绑定,也可能已经 Bound。两者都不能替代对 Pod 引用的核对。

从 Pod 引用到应用读写的观察位置
从 Pod 引用到应用读写的观察位置

修正 Deployment 模板里的引用,控制器会据此创建新的 Pod。不要把修复动作做成删除 PVC,因为实验中存在的是引用错误,存储申请本身并不需要被重建。

kubectl -n c31-storage-lab patch deployment exports-demo --type=json -p='[{"op":"replace","path":"/spec/template/spec/volumes/0/persistentVolumeClaim/claimName","value":"exports-data"}]'
kubectl -n c31-storage-lab rollout status deployment/exports-demo --timeout=180s
kubectl -n c31-storage-lab describe pod -l app=exports-demo

如果后续仍未就绪,应继续读新 Pod 的事件。FailedAttachVolume 指向附加阶段,FailedMount 指向挂载阶段;它们的具体原因仍要结合消息判断。若错误变成应用进程的 Permission denied,则要检查容器身份与目录权限。等待超时只是观察结果,不能证明后端数据已经损坏。

待 Deployment 就绪后,可以在实验卷中写入 1 个标记,再重建 Pod 验证跨 Pod 保存。下面读取结果应为 c31-ok;这验证了当前条件下的卷重用,不代表已经验证可用区故障恢复或备份。

kubectl -n c31-storage-lab exec deployment/exports-demo -- sh -c 'echo c31-ok > /data/exports/marker.txt'
kubectl -n c31-storage-lab rollout restart deployment/exports-demo
kubectl -n c31-storage-lab rollout status deployment/exports-demo --timeout=180s
kubectl -n c31-storage-lab exec deployment/exports-demo -- cat /data/exports/marker.txt

记录修复前后的 Pod 名称、PVC 名称、阶段和事件原因,才能说明“引用修正后链路继续前进”。实验结束时先确认该命名空间只含实验资源,再按回收策略清理;删除命名空间也会删除其中的 PVC,可能触发后端资源回收。保留策略的卷还需要管理员单独处理,不能假设删完命名空间就没有遗留资源。

5 读写多与单挂载取舍

访问模式回答卷允许以什么方式被节点或 Pod 使用,不替应用安排业务并发。ReadWriteOnce,简称 RWO,通常表示可由 1 个节点读写挂载;同一节点上的多个 Pod 仍可能访问它。它不是严格的“只允许 1 个 Pod”。ReadWriteOncePod,简称 RWOP,面向支持该能力的 CSI 卷,约束为单个 Pod 读写使用,采用前需要确认集群和驱动支持。

ReadOnlyMany,简称 ROX,表示可由多个节点只读挂载;ReadWriteMany,简称 RWX,表示可由多个节点读写挂载。具体模式能否兑现,取决于后端与驱动,不能通过把 PVC 中的字符串改成 RWX,就把普通块卷变成共享文件系统。模式还需要与 PV 和供给规则匹配,否则可能连绑定都无法完成。

对订单导出服务,可以先选择 1 个后台任务生成文件,API 实例通过约定方式提供下载。若文件必须由多个节点上的 API 共同读取,就应考虑支持共享读取的文件存储,或把生成结果上传到对象存储。对象存储通常通过 API 访问,不应默认拥有本地文件系统的路径和操作语义。选择取决于应用实际使用方式。

即使使用 RWX,2 个进程同时覆盖 daily.csv 仍然可能制造半成品或丢失更新。解决办法可以是让生成者写独立临时文件,在后端支持的范围内完成发布操作,或者用任务协调保证只有指定生成者提交结果。涉及跨文件一致性和事务的细节应由应用与存储设计共同解决,不能把“允许写入”当作“并发写一定正确”。

访问模式也不等于读写权限控制。容器中的用户编号、组编号、目录权限及后端规则仍会影响能否打开文件。Pod 中把某个挂载标成只读,可以约束这个容器入口,但不能证明所有其他入口都只能读取。遇到权限错误时,应核对身份和目录属性,不宜把整个共享目录直接改成任何人都可写。

这个滑块比较共享同一批文件的节点数。节点数增加后,单节点读写的卷会逐渐不适合跨节点共享场景,但滑块不会替用户预测吞吐或可靠性。实际性能还受文件大小、请求并发、延迟和后端配置影响。单节点方案也可能有很高性能,共享方案也可能成为瓶颈,访问模式本身没有给出这些答案。

因此取舍应从写入者数量、读取者分布和失败后的恢复方式出发。对于初期只有 1 个导出任务的服务,受控的单写入者通常容易解释;需要跨节点共享时,再选择明确支持的共享后端并设计文件发布规则。增加 API 副本之前先核对这一点,否则扩容可能把原来隐藏的存储约束暴露为启动失败。

6 常见坑:把空目录当持久化

emptyDir 会为 Pod 提供临时空间,同一个 Pod 内的容器可以通过挂载共享它。容器在 Pod 内重启时,其中的文件通常仍在;Pod 被移除并重建后,新的 emptyDir 不会继承旧数据。这种差别容易造成错觉:开发者只测试了容器重启,文件还在,于是推断滚动发布和节点迁移也会保留文件。

它很适合可重建的下载缓存、解压目录、临时排序文件,也适合 Pod 内生产者与消费者交换中间结果。但生成成功且已经向用户承诺可下载的导出文件,如果只存在这里,承诺就受 Pod 生命周期限制。决定是否使用临时空间的标准应是数据能否在可接受时间内重建,而不是“测试环境放进去没丢”。

把 emptyDir 的介质设置为内存,也不会获得持久性,反而需要关注内存占用。普通临时目录同样消耗节点资源,写满可能影响工作负载稳定性。无论选择哪种介质,都应给临时数据规定清理方式和容量预期。临时并不表示免费,也不表示系统会替应用按业务优先级保留文件。

从数据可重建性到卷类型的选择
从数据可重建性到卷类型的选择

另一个误区是镜像中已经有 /data/exports,所以那里天然持久。目录只是路径;挂载前可能来自镜像或可写层,挂载后则可能显示卷中的内容。新卷覆盖这个挂载位置时,原镜像目录中的文件通常不会自动复制进去。应用如果依赖初始模板,应明确初始化过程,并避免把“看不到镜像文件”误判为历史数据被删除。

还有人把配置卷当作普通数据盘。ConfigMap 和 Secret 用于分发配置与敏感配置,不适合作为订单导出文件的写入目标。它们与 PVC 的权限、更新和容量边界也不同。把资源都叫作 Volume 是为了统一接入方式,不代表可以互换用途;同样的 mountPath 也不能抹平底层差异。

持久卷本身还会遇到容量不足、文件权限错误和应用写入中断。程序成功打开文件,不代表已经完成完整内容的发布;请求返回成功之前需要满足什么写入条件,应由应用明确。入门阶段至少要避免让读者下载正在覆盖的文件,并区分“写入任务完成”与“容器仍在运行”这 2 个状态。

验收可以使用清晰的生命周期场景:重启容器、重建 Pod、变更节点、恢复备份,逐项说明预期。前 2 项通过不意味着后 2 项通过。只要每个测试都写清触发动作和结果,团队就能发现“持久化”这个词背后遗漏的条件,而不会把某次成功重启当成所有故障场景的证明。

7 案例:节点漂移丢失 hostPath 数据

订单导出服务最初使用 hostPath,把节点上的 /srv/exports 挂到容器内。服务只运行 1 个副本,长期落在节点 A,文件下载一直正常。维护期间节点 A 不再承载这个 Pod,控制器在节点 B 创建替代实例。节点 B 上恰好也存在 /srv/exports,应用启动成功,下载列表却突然变成空白。

这里的“节点漂移”指 Pod 重建后被安排到另一个节点,并不表示原运行进程连同内存和文件一起搬家。相同的节点路径字符串,只能指出各节点自己的目录。节点 B 的 /srv/exports 与节点 A 的目录没有天然的数据同步关系。监控看到新 Pod Running,并不能证明业务文件已经随之迁移。

第一步应保存证据:原 Pod 与新 Pod 的节点名称、部署所引用的卷类型、文件最后成功生成时间,以及节点 A 当前是否可访问。若节点 A 的盘仍完整,旧文件可能还在那里。“新实例看不到”与“物理数据已消失”必须区分,否则可能过早执行初始化或清理,覆盖原本可以恢复的数据。

hostPath 故障的定位与恢复分支
hostPath 故障的定位与恢复分支

恢复时先暂停会覆盖同名文件的生成任务,再由具备权限的人员确认节点 A 上数据的完整性,必要时复制到临时保护位置。接着为目标持久卷安排受控的数据迁移,核对文件数量、大小和抽样内容,确认新应用的读写身份,再切换业务入口。具体复制工具依环境确定,不能为了找回文件而把节点宿主目录任意开放给所有容器。

如果节点 A 已不可恢复,且没有副本或备份,就只能从独立订单记录重新生成可重建的导出文件,并评估缺失时间段。这也说明了为什么本课不把正式订单数据库放进这个示例目录:数据可重建的前提来自另一份可靠记录,而不是来自重新启动应用。若源数据也只在同一块损坏磁盘上,重新生成就没有依据。

长期修复不能只给 Pod 加上固定节点条件。固定位置可以暂时避免误入另一份目录,却同时限制故障后的接替能力。hostPath 本来就绑定宿主环境,适合少数明确需要访问节点资源的工作负载;若确实要使用本地持久存储,应选择能表达节点亲和约束的 local PV,并理解节点不可用时依旧需要额外恢复手段。

这个案例的根因是方案把“路径相同”当成“数据相同”,又把“能重新调度”当成“数据能跟随”。修复后的验收必须包含跨节点重建与读取已知文件,记录实际限制。换成 PVC 只是接入方式的改进,还要检查其后端是否仍然是节点本地资源;仅凭资源名字出现 PVC,不能宣布节点故障风险已经消除。

8 把持久化与故障域写进存储方案

存储方案需要同时写出数据寿命和可访问范围。假设导出文件保存在某个可用区内的卷上,Pod 可以在该可用区内换节点恢复,但未必能在另一个可用区挂载同一卷。即便控制面支持跨区安排 Pod,也不能让区域受限的卷突破自身边界。可用区故障后的恢复方案,需要后端能力、复制或备份共同支撑。

可以把故障域理解为可能一起受影响的范围,例如容器、Pod、节点、可用区。针对每个范围,都要回答数据是否还在、接替实例能否访问、需要谁执行什么操作。不要仅用“支持高可用”概括这些问题。某个后端在区域内部具有副本,也不能推导出误删可恢复,或跨区切换无需时间。

故障范围与恢复承诺对照
故障范围与恢复承诺对照

RPO 表达故障后允许丢失多长时间内的数据,RTO 表达恢复服务允许花多长时间。例如导出文件可从订单库补生成,团队可能接受丢失最近 24 小时的导出产物,并要求在 60 分钟内恢复下载能力。这里描述的是导出文件,不是订单记录本身;不同数据应有不同目标。目标需要依据业务承诺和演练结果确定,不能照抄示例。

备份计划应覆盖备份位置、频率、保留期、访问权限和恢复验证。快照能否承担备份职责,要看它是否独立于目标故障域、能否保留所需版本以及如何恢复。对持续写入的数据,时间点是否一致也很重要。入门方案至少需要 1 次实际恢复到隔离位置的验证,证明备份内容可以被应用使用,而不只是备份任务显示成功。

日常观察应覆盖可用容量、申请与绑定状态、挂载或附加失败,以及应用读写结果。存储后端的指标说明资源情况,业务日志说明导出任务是否完成,两者需要关联。例如卷未满但写入失败,可能是权限或连接问题;卷还有空余但导出超时,可能需要进一步检查延迟与应用行为。不要用 1 个容量百分比代替全部健康判断。

删除责任也应写清:谁能删除 PVC,谁能改变 PV 回收策略,应用退役后数据保留多久,如何确认备份不再需要。权限要同时考虑 K8s API、后端资源和容器文件访问,这些身份不一定相同。给应用读写文件的能力,并不意味着应该给它删除存储申请的权限;自动部署工具的权限同样需要按职责设置。

容量规划最后回到业务量。按每天导出体积、在线保留天数和临时生成空间估算起点,再用实际增长修正。扩容是否可用,需要确认 StorageClass、驱动与文件系统支持,并安排验证;申请增加也不保证应用立刻看到可用空间。方案应规定容量预警后的负责人和动作,避免只写“支持自动扩展”却没人处理逼近上限的卷。

9 从K8s 存储走向K8s 调度(C32)

到这里,存储已经不只是容器内的目录,而是会限制 Pod 可以在哪里运行的资源。CPU 和内存足够的节点,仍可能因为卷的可用区、节点亲和关系或访问模式而无法承载这个 Pod。下一课讨论 K8s 调度时,会把这些条件与其他运行约束放到一起,解释为什么“集群还有资源”不代表某个 Pod 一定能启动。

本课先建立一个简单判断:存储需要与计算位置相容。对立即绑定的区域卷,要检查卷位置能否满足 Pod 的调度条件;对延迟绑定的卷,要允许调度需求参与供给。若管理员指定了 Pod 只能在区域 B 运行,而现有卷只在区域 A 可用,等待更多相同配置的节点通常解决不了矛盾,必须修改真实约束或安排数据迁移。

扩容和滚动发布也会触及存储。Deployment 更新时可能短暂出现新旧 Pod 并存;单副本配置不等于任何时刻都只有 1 个 Pod。对于只能由单个节点或单个 Pod 使用的卷,需要核对发布策略与应用写入方式。不能在看见附加冲突后就断定驱动故障,因为工作负载的更新过程也可能提出了互相冲突的使用请求。

StatefulSet 可以为有状态实例提供稳定的身份,并通过卷声明模板给实例组织持久卷,但它并不自动实现数据库复制、主节点选举或故障恢复。换一种控制器不会把不支持共享的卷变成共享卷,也不会自动为数据建立备份。初学阶段先把控制器的实例管理职责与应用的数据一致性职责分开,后续再学习更复杂的有状态服务设计。

进入 C32 前,可以用本课事件链判断问题所处的位置:找不到 PVC,先修正资源引用;PVC 长期 Pending,检查类别、供给与绑定时机;Pod 有目标节点却附加或挂载失败,检查驱动、后端与相关事件;容器已启动但写入失败,检查路径、权限和应用日志。这是排查入口,不是仅靠状态名就能得出全部根因的口诀。

迁移性也有边界。把后端细节放进 StorageClass,确实能减少部署文件中的环境信息,但迁移到新集群时,数据内容、权限、访问模式、性能和恢复流程仍要重新对齐。相同 PVC 清单在另一个环境被接受,不代表原有文件已经搬过去。可移植的配置与可迁移的数据,需要分别验证。

最后保留 3 个自检问题:同样的 /data/exports 为什么可能指向不同数据;PVC Bound 后为什么仍可能无法写入;节点 A 故障后,节点 B 启动新 Pod 为什么不一定能恢复下载。能够用资源关系、事件阶段和故障域分别回答,就具备了讨论调度约束的基础,不必先记住驱动内部实现。

放进方案里

为订单 API 写存储方案时,先列出正式订单记录、导出成品和生成缓存。正式记录由独立数据库方案负责;导出成品使用 PVC 接入已确认的持久存储;生成缓存使用 emptyDir,允许随 Pod 重建丢失。给每类数据注明生产者、读取者、保留期和能否重新生成,避免用同一个目录承接不同的恢复承诺。

导出服务初期采用 1 个生成任务,申请支持 RWO 的文件系统卷,记录 StorageClass、初始容量、挂载路径与容器身份。说明多个 API 实例如何取得成品;如果需要跨节点直接共享,就改用明确支持相应访问模式的后端,并补充并发发布规则。为发布过程核对新旧 Pod 是否可能同时使用卷,不能只检查期望副本数。

写清后端所在故障域,以及容器重启、Pod 重建、节点故障和可用区故障各自的处理。导出文件暂定允许丢失最近 24 小时的产物,下载能力恢复目标为 60 分钟,正式承诺以演练为准。列明备份保留位置、恢复负责人和从订单记录补生成的入口;恢复验证要在隔离目录完成,再核对文件内容与应用读取。

运维部分同时观察剩余容量、绑定状态、附加与挂载事件、导出成功率。规定告警接收者和容量扩展步骤,记录谁能删除 PVC、当前 PV 回收策略以及退役后的数据保留责任。上线验收至少包含已知文件跨 Pod 重建后的读取、受控跨节点恢复和备份恢复,分别记录结果与限制。方案交付的是可检查的行为,而不是只有“已挂载持久卷”的配置截图。

验收时保存 PVC 与 PV 的绑定关系、后端卷标识、迁移前后节点及可用区,并对同一份已知文件比较校验和。只有新实例能完整读取且恢复耗时达标,才算该场景通过;无法跨区挂载时,应明确改走备份恢复或补生成路径。

10 小结:下一步K8s 调度(C32)

K8s 存储把应用路径、存储申请、实际卷与供给规则连接起来。理解 Volume、PVC、PV 和 StorageClass 的边界,才能解释绑定与挂载为什么是不同阶段。访问模式约束使用方式,后端决定故障域,应用负责正确发布与读取数据,备份负责额外的恢复路径。

下一步进入 K8s 调度(C32):把卷的位置与访问限制,和计算资源、节点条件一起考虑,判断 Pod 能在哪里运行,以及条件冲突时应该修改哪项约束。

同阶段相关课

AI 答疑

默认关闭。启用后,只发送本课标题、最近阅读的屏幕内正文摘录(最多 6000 字)与本次问题。

配置自己的服务