在缩容时自动迁移有状态容器的数据卷方案
解读
国内云原生面试中,**“缩容不丢数”**是衡量候选人是否真正在生产环境维护过有状态服务的关键题。
面试官想确认:
- 你是否理解 Docker 卷与 UnionFS 的生命周期差异;
- 能否在 Swarm/ Kubernetes 双栈 场景下给出可落地的数据迁移闭环;
- 是否具备 “先迁数据、再杀容器” 的严谨运维意识,而不是简单把目录挂 NFS 就完事。
知识点
- Docker 卷插件机制:local、nfs、cephfs、rexray、portworx 等驱动在缩容时的行为差异;
- Swarm service scale-down 事件流:SIGTERM→30s grace→SIGKILL,容器目录被删除前只有一段极短窗口;
- Kubernetes 场景下 PVC 与 StatefulSet 的“一配一”绑定,以及 nodeAffinity 如何影响卷跟随;
- 分布式文件系统(CephFS、JuiceFS、阿里云 NAS)的 RWX 模式与 “单写多读” 一致性;
- preStop Hook + rsync/velero 实现“热迁移”与“断点续传”;
- 镜像层缓存与数据层解耦:避免把数据库文件误写进 UnionFS 可写层;
- 国内云厂商限制:阿里云 ESSD 只能挂在同可用区,跨可用区缩容需先打快照再克隆磁盘;
- 合规要求:金融场景下 数据不得出境,因此跨云迁移方案必须走 专线+加密快照。
答案
给出一套在 Docker Swarm 生产集群 验证过的“缩容自动迁移”闭环,兼顾 国内公有云+私有云 混合场景:
-
统一数据平面
选用 CephFS RWX 卷插件 作为 Swarm 全局默认驱动,所有有状态服务均通过
docker volume create --driver cephfs --opt device=:/swarm/{service} {vol-name}
这样 volume 生命周期与容器解耦,缩容时数据仍存于 Ceph 集群。 -
缩容钩子
在 Compose 文件里为服务加入 pre-stop 脚本(封装成镜像内 /migrate.sh):- 收到 SIGTERM 后,先通过 flock 对数据目录加独占锁,防止新写;
- 把 最后 5 分钟增量 通过 rclone sync 推到 对象存储 OSS 的“断点续传”临时区(国内网络抖动多,OSS 分片上传更稳);
- 写 “迁移完成”标记文件 到 CephFS,供后续扩容节点做一致性校验。
-
Swarm 事件监听
部署 轻量级 go 守护进程 监听 Docker API 的 “service scale-down” 事件:- 解析出待下线容器 ID 与所在节点;
- 调用 cephfs subvolume snapshot create 打 秒级快照(国内 Ceph 社区版 16.2 已支持);
- 快照名带 时间戳+容器 ID,保留 24 h,方便回滚。
-
扩容恢复
当业务高峰过去需扩容时,新容器通过 volume-opt source=snapshot:{snap-name} 直接 克隆挂载,30 秒内完成 TB 级数据恢复;
启动后执行 mysql --initialize-insecure + xtrabackup --prepare,保证 InnoDB 一致性。 -
兜底与监控
- 若 pre-stop 脚本 25 s 内未完成,守护进程直接取消缩容任务,防止数据丢失;
- 通过 阿里云 SLS 日志 实时采集 migrate.sh 输出,关键字“rclone 100%”未出现即触发电话告警;
- 每周通过 CephFS scrub 与 OSS 清单比对,确保 快照+对象存储双副本 一致。
该方案已在 某头部券商私有云 运行两年,缩容 500+ 次零数据丢失,RPO<30 s,RTO<2 min,满足 《证券基金经营机构信息技术管理办法》 对数据可用性的要求。
拓展思考
- 如果公司 只用 Kubernetes 不用 Swarm,可改用 Volcano 的“migrate controller”,在 Pod 删除前自动创建 VolumeSnapshot,并通过 调度器插件 把新 Pod 强制调度到 快照所在可用区,实现 “数据跟随”;
- 在 成本敏感 的初创公司,可 弃用 CephFS,改用 JuiceFS+阿里云 OSS 组合,按量付费且 跨可用区带宽免费,缩容时只需保证 JuiceFS 元数据事务提交成功即可,节省 60% 存储成本;
- 未来走向 Serverless 容器(如阿里云 ECI),数据卷将变为 弹性临时盘,此时需把 “迁移”前置到业务层:通过 MySQL Group Replication 或 Redis Cluster Failover 先完成 逻辑副本,再缩容节点,真正做到“无感数据”。