Kubernetes 滚动更新期间如何安全执行数据库迁移?
数据阿明
结论
使用 Kubernetes Rolling Update 部署 FastAPI 应用时,通常应将 Alembic 迁移作为发布流程中的独立步骤,例如先运行 Kubernetes Job,再启动新版应用的滚动更新。避免让每个应用 Pod 都在启动时执行迁移。
独立 Job 可以避免迁移随着应用副本数重复启动,但不能单独保证零停机。迁移期间,schema 需要同时兼容旧版和新版应用。会破坏兼容性的清理操作应等旧 Pod 退出后再执行。
推荐的发布顺序
- 先发布兼容性变更。 新增表或列时,确认旧版应用仍能使用原有 schema。若需要回填数据,应安排独立、可控的回填步骤。
- 运行一次迁移。 发布流程启动一个 Job 执行
alembic upgrade head,并等待 Job 成功后再继续。确保同一数据库不会因发布流程而并发启动多个迁移任务。 - 滚动发布新版应用。 新版代码需要能使用迁移后的 schema,迁移阶段也要兼容仍在运行的旧版代码。Rolling Update 期间新旧 Pod 会短暂共存,因此两种版本都需要兼容。
- 旧版实例退出后再清理。 删除旧列、改名或执行其他不兼容变更时,应安排在后续发布中,避免旧代码仍依赖这些结构。
字段替换可以分阶段进行:先新增字段,让应用同时读写新旧字段;完成数据回填并部署不再依赖旧字段的版本后,再通过后续迁移删除旧字段。读写顺序和回填方式需根据应用逻辑设计。
Job、initContainer 和 Helm Hook 怎么选
- 独立 Job: 通常由 CI/CD 发布流程显式创建,并等待任务完成。这样可以将迁移与应用副本启动分开,也便于查看成功或失败状态。
- initContainer: 每个 Pod 启动前都会运行自己的 initContainer。滚动更新或扩容时,多个 Pod 可能同时启动,因此它不适合作为默认的全局迁移协调机制,除非另有可靠的并发控制设计。
- Helm Hook: 可以在 Helm 发布过程中触发迁移 Job,但仍需处理 Job 失败、重复发布以及新旧应用兼容问题。Hook 可以控制触发顺序,schema 变更仍需设计为向后兼容。
无论采用哪种方式,都要确保同一数据库不会同时有多个迁移执行者。可以通过发布系统串行化发布,并根据所用数据库和迁移实现评估是否需要额外的锁或协调机制。Kubernetes 的 Job 配置本身不能协调不同发布流程。
失败处理与注意事项
迁移 Job 失败时,应暂停后续应用发布,查看 Job 日志和数据库状态,再决定修复或重试。重试前要确认迁移是否已部分执行,以及再次运行是否安全。对于耗时较长或会锁表的变更,应先评估对线上读写的影响,并考虑拆分、分批处理或安排独立的维护步骤。
零停机部署依赖应用版本与 schema 的兼容设计。迁移操作的锁行为、可回滚性和影响范围,则与具体 SQL、PostgreSQL 操作及 Alembic 迁移内容有关,需逐项评估。
备注:内容仅供参考。
