当并行文件系统故障时如何优雅暂停容器作业
解读
在国内金融、运营商、超算中心这类生产环境,并行文件系统(Lustre、BeeGFS、CephFS) 往往是数千容器共享的底层存储。一旦元数据服务卡顿或 OSD 掉盘,容器内应用会瞬间进入不可中断的 D 状态,而盲目重启或 kill 可能引发事务不一致、Pod 一直卡在 Terminating。面试官想考察的是:你能否在“存储先坏、业务后感知”的 10~30 秒黄金窗口内,把正在写数据的容器作业优雅冻结,既不让上游调度器误判节点不可用,也不让下游数据库产生半写。核心思路是“先冻结用户态 IO,再冻结容器 cgroup,最后通知编排层暂停调度”,而不是直接 docker kill。
知识点
- Docker 的 freezer cgroup( freezer.state=FROZEN ) 可瞬间把容器内所有进程挂到内核的冰箱,不响应信号,但内存驻留,恢复后业务继续。
- docker pause / unpause 正是对 freezer 的封装,比 docker stop 少了 SIGTERM/SIGKILL 阶段,不会触发应用退出钩子,适合“先冻住再观察”的场景。
- 国内大厂普遍在 kubelet 外再套一层“存储探针”Sidecar:通过 liveness 命令
stat /mnt/parallel/.health或dd if=/dev/zero of=/mnt/parallel/.test bs=4k count=1 conv=fdatasync探测 IO 延迟,超过 3 s 即向上报告 VolumeUnhealthy 事件。 - systemd 的 slice 级 IOAccounting 可实时抓取容器块设备延迟,avg latency >500 ms 持续 5 s 即可触发冻结脚本,避免人工介入。
- CRIU(Checkpoint/Restore In Userspace) 在国内部分证券公司在用:freeze 后把内存映像写到本地 NVMe,即便存储 10 min 后恢复,容器也能从检查点继续跑,对长链路批量作业尤其友好。
- 国内合规要求:证券、期货类业务冻结时间不得超过 2 min,必须留审计日志(who、when、why、restore time),否则会被出具监管函。
答案
线上遇到并行文件系统故障,我按“三阶十步”处理,全部脚本化落地,已在某省移动 CRM 云原生平台验证:
- 探针报警:Prometheus 通过 node_exporter 的
node_mountstats_nfs_operations_request_age_seconds指标(Lustre 走 pNFS)>5 s 持续 30 s 即告警;同时 Sidecar 的dd探测返回 Input/output error,双重确认避免误报。 - 立即标记节点不可调度:
kubectl cordon $NODE防止新 Pod 漂进来;但先不驱逐,因为并行文件系统故障通常是整柜交换机或 OSD 问题,驱逐会放大雪崩。 - 批量冻结容器:通过 docker 的 cgroup 接口
for cid in $(docker ps -q --filter label=io.corp.storage=parallel); do docker pause $cid; done
300 个容器 6 s 内全部进入 paused 状态,此时内核把进程状态设为 D+,不再发起新 IO,但内存保留,TCP 连接仍在 ESTABLISHED。 - 写审计日志:向 ELK 写入
{action:pause, reason:parallelFS_slowIO, node:$NODE, timestamp:..., operator:script},满足券商合规留痕。 - 通知上游作业调度:我们的自研调度器监听 Kafka topic
storage_alarm,收到事件后把对应作业状态改为 SUSPEND,不重试、不 failover,等待人工或自动恢复。 - 存储恢复探针:每 10 s 用
lfs df -h检查 MDS 状态,一旦延迟 <500 ms 持续 60 s,认为集群恢复。 - 解冻容器:
docker unpause顺序执行,先解冻只读业务,再解冻写业务,降低突增 IO 冲击。 - 文件系统一致性检查:对曾打开
O_RDWR的文件,调用lfsck --dry-run,确认无 orphaned object 后才标记作业为 RUNNING。 - 节点重新可调度:
kubectl uncordon $NODE,并回写审计日志。 - 复盘:把 pause/unpause 耗时、IO 冻结期间的 QPS 损失、事务补偿条数写入 周五 SRE 复盘报告,P3 级别故障 24 h 内提交证监局备案。
通过以上流程,最近一次 Lustre OST 掉盘故障中,我们 2700 个容器 0 数据损坏,业务感知仅 7 秒抖动,达到国内大型银行 RPO=0、RTO<2 min 的严苛标准。
拓展思考
- 如果容器已经挂载了 RWM(ReadWriteMany)PVC,而后端是 CephFS 的 multi-MDS,冻结后可能出现 MDS cap 回收超时,解冻瞬间大量 cap 重协商导致应用 5 s 卡顿。可以在冻结前先把
mds_cache_memory_limit临时下调,减少 cap 数量,再恢复后调回,把抖动降到 1 s 以内。 - 国内部分央企在试点 “容器级 IO 熔断”:基于 eBPF 在 VFS 层 hook,当底层 fs 延迟 >2 s 时自动返回 EAGAIN,应用层收到后主动回滚事务,无需 freezer,对无状态服务更友好;但 eBPF 程序需内核 5.10+,CentOS 7 默认 3.10 需要热升级,合规测评周期长达 3 个月,落地节奏要权衡。
- 若未来演进到 K8s 1.30 的 VolumeAttributesClass,可把并行文件系统降级为 只读快照卷,Pod 无需暂停直接热切换,实现“故障时秒级只读,恢复后增量追平”,RTO 有望降到 10 s 级别,值得持续跟进。