在缩容时自动迁移有状态容器的数据卷方案

解读

国内云原生面试中,**“缩容不丢数”**是衡量候选人是否真正在生产环境维护过有状态服务的关键题。
面试官想确认:

  1. 你是否理解 Docker 卷与 UnionFS 的生命周期差异;
  2. 能否在 Swarm/ Kubernetes 双栈 场景下给出可落地的数据迁移闭环;
  3. 是否具备 “先迁数据、再杀容器” 的严谨运维意识,而不是简单把目录挂 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 生产集群 验证过的“缩容自动迁移”闭环,兼顾 国内公有云+私有云 混合场景:

  1. 统一数据平面
    选用 CephFS RWX 卷插件 作为 Swarm 全局默认驱动,所有有状态服务均通过
    docker volume create --driver cephfs --opt device=:/swarm/{service} {vol-name}
    这样 volume 生命周期与容器解耦,缩容时数据仍存于 Ceph 集群。

  2. 缩容钩子
    在 Compose 文件里为服务加入 pre-stop 脚本(封装成镜像内 /migrate.sh):

    • 收到 SIGTERM 后,先通过 flock 对数据目录加独占锁,防止新写;
    • 最后 5 分钟增量 通过 rclone sync 推到 对象存储 OSS 的“断点续传”临时区(国内网络抖动多,OSS 分片上传更稳);
    • “迁移完成”标记文件 到 CephFS,供后续扩容节点做一致性校验。
  3. Swarm 事件监听
    部署 轻量级 go 守护进程 监听 Docker API 的 “service scale-down” 事件:

    • 解析出待下线容器 ID 与所在节点;
    • 调用 cephfs subvolume snapshot create秒级快照(国内 Ceph 社区版 16.2 已支持);
    • 快照名带 时间戳+容器 ID,保留 24 h,方便回滚。
  4. 扩容恢复
    当业务高峰过去需扩容时,新容器通过 volume-opt source=snapshot:{snap-name} 直接 克隆挂载30 秒内完成 TB 级数据恢复
    启动后执行 mysql --initialize-insecure + xtrabackup --prepare,保证 InnoDB 一致性

  5. 兜底与监控

    • 若 pre-stop 脚本 25 s 内未完成,守护进程直接取消缩容任务,防止数据丢失;
    • 通过 阿里云 SLS 日志 实时采集 migrate.sh 输出,关键字“rclone 100%”未出现即触发电话告警
    • 每周通过 CephFS scrubOSS 清单比对,确保 快照+对象存储双副本 一致。

该方案已在 某头部券商私有云 运行两年,缩容 500+ 次零数据丢失,RPO<30 s,RTO<2 min,满足 《证券基金经营机构信息技术管理办法》 对数据可用性的要求。

拓展思考

  • 如果公司 只用 Kubernetes 不用 Swarm,可改用 Volcano 的“migrate controller”,在 Pod 删除前自动创建 VolumeSnapshot,并通过 调度器插件 把新 Pod 强制调度到 快照所在可用区,实现 “数据跟随”
  • 成本敏感 的初创公司,可 弃用 CephFS,改用 JuiceFS+阿里云 OSS 组合,按量付费跨可用区带宽免费,缩容时只需保证 JuiceFS 元数据事务提交成功即可,节省 60% 存储成本
  • 未来走向 Serverless 容器(如阿里云 ECI),数据卷将变为 弹性临时盘,此时需把 “迁移”前置到业务层:通过 MySQL Group ReplicationRedis Cluster Failover 先完成 逻辑副本,再缩容节点,真正做到“无感数据”