GitOps 与蓝绿 / 零停机部署
症状
目标:在不停机的情况下部署 schema 和应用变更;通过 expand-contract 迁移、蓝绿环境、功能开关和自动回滚,接近零停机。
1. GitOps:让 Git 成为唯一可信来源
在 Git 中定义基础设施、schema 迁移和应用版本;部署由合并到仓库触发(GitOps)。协调器(Argo CD/Flux 或 CI/CD)将期望状态应用到实际环境。这样每个变更都可审计、可重复,并在需要时可以回退到之前的提交。
PostgreSQL
# repo/
# migrations/ (Vxxx__*.sql)
# k8s/ (Deployment, Service)
# flags/ (feature flag config)2. 以向后兼容的方式更改 schema(expand-contract)
为实现零停机,不要一步完成破坏性的 schema 变更;将其拆分为两个阶段。EXPAND:添加新结构(新列/新表),使旧代码和新代码可以同时运行(可空列、带默认值、双写)。在应用迁移到新结构之后,CONTRACT:在单独的迁移中删除不再使用的旧列/旧表。这样在部署期间,新旧应用版本可以并行运行而不出问题。
PostgreSQL
-- EXPAND (V5): backward-compatible addition
ALTER TABLE customer ADD COLUMN email text;
-- for a while the code writes/reads both columns
-- CONTRACT (V9): drop the old column
ALTER TABLE customer DROP COLUMN mail_old;3. 将高风险行为放在功能开关之后
将新的代码路径(例如读取新列)放在功能开关之后有条件地运行;schema 就绪后打开开关,出现问题时无需改动部署即可关闭。开关将代码部署(deploy)与功能启用(release)分离开来。expand 阶段已发布,但行为变更以受控方式启用,并可快速回退。
PostgreSQL
-- application layer (pseudocode)
-- if flag('new_email_field'):
-- SELECT email FROM customer ...
-- else:
-- SELECT mail_old FROM customer ...4. 搭建蓝绿环境
保持两套相同的环境:'blue'(线上)和 'green'(新版本)。将新的应用版本部署到 green,并在其接收真实流量之前进行验证;就绪后,将路由器/流量切换到 green。关键点:数据库通常是共享的,因此 schema 必须同时兼容两个版本(expand-contract 可确保这一点)。即使切换时连接目标发生变化,由于 schema 兼容,也不会停机。
PostgreSQL
# traffic is switched to green (new version)
# shared DB: schema must be compatible with both blue and green5. 通过监控验证部署(金丝雀/观察)
在切换全部流量之前,监控错误率、延迟、数据库错误/锁数量和复制延迟等指标;可选地将一小部分流量(金丝雀)发送到 green 并观察。若健康指标良好,逐步增加流量;若不佳,则不要继续。监控是自动回滚决策的输入。
PostgreSQL
-- live health queries
SELECT count(*) FROM pg_stat_activity WHERE wait_event_type='Lock';
SELECT * FROM pg_stat_replication;6. 准备自动回滚
若指标超过阈值,部署必须自动回滚:在蓝绿部署中,迅速将流量切回 blue(旧版本)。由于 blue 仍在运行,应用回滚是即时的。在 schema 方面,通常不需要回滚:得益于 expand-contract,新 schema 也兼容旧代码,因此回滚应用就足够了。这就是为什么 schema 变更应独立于应用部署,并始终保持向后兼容。
PostgreSQL
# traffic instantly returns to blue (application rollback)
# schema is not rolled back: expand-contract is compatible with old code
# if truly needed: write a new corrective migration