14.1 多环境隔离 (dev / staging / prod)

一句话

多环境的目的不是 “有三套机器”,而是 “让变更在低风险环境里暴露问题,同时保证生产环境不被误操作”;隔离的维度是 网络、数据、密钥、权限、配额 五件事,少一件就会 “测试事故打到生产”。

五维隔离

维度 dev staging prod
网络 可访问公网、共享 VPC 独立 VPC、可访问生产只读副本(可选) 独立 VPC、默认拒绝入站
数据 假数据/脱敏 生产同构的脱敏数据 真实数据(加密 + 审计)
密钥 测试凭证 测试凭证(与生产不同) 生产密钥(KMS/Vault)
权限 开发者可写 发布流水线可写 仅流水线 + 值班可写
配额 小 中(接近生产) 按容量规划

关键:staging 要 “像生产”(同构、同依赖版本),否则 “测试通过” 没有意义;但 staging 不能连生产库写,只能读脱敏副本。

环境矩阵与常见配置错误

配置 常见错误 后果
数据库连接串 dev 指向 staging、staging 指向 prod 测试数据写进生产
消息队列 topic 共用同一 topic 测试消息被生产消费
密钥 三套环境同一把 key 泄露即全线沦陷(见 13.4 密钥与凭证管理)
域名/回调地址 staging 回调打到生产 支付/通知串环境
定时任务 staging 也开定时任务 重复跑批、重复发券
# 环境配置用“同一份声明 + 不同 values”,避免手工改
# values-staging.yaml
database: {host: pg-staging.internal, name: app_staging}
features: {payment_mock: true}
cron: {enabled: false}          # staging 默认关掉定时任务

反模式

反模式 后果
环境靠 “手工配置” 维护 漂移成 “三套不同系统”,问题复现不了
staging 连生产库(可写) 测试数据污染生产
三套环境共用一个数据库/账号 隔离形同虚设
staging 与生产依赖版本不同 测出来的结论不成立
没有 “生产变更审批/双人” 误操作直接打生产
环境太多(dev1/dev2/qa/uat…) 维护成本爆炸,没人管得过来

三条铁律

🔑 staging 要像生产,但不能连生产写。

🔑 五维隔离缺一不可;只隔离网络等于没隔离。

🔑 环境靠声明式配置生成,不靠手工。

自检

Q1 为什么 “staging 像生产” 很重要?

▸ 答案:因为很多问题只在真实规模与真实依赖下才出现:数据量大后的慢查询、依赖版本差异、并发下的竞态。如果 staging 数据量小、依赖版本不同,测试通过也证明不了生产可用。

Q2 staging 连生产只读副本有什么风险?

▸ 答案:两个:读到敏感数据(未脱敏则违规,见 3.2 个人信息保护与 GDPR);误写(权限没管住,只读变可写)。若要连,必须只读账号 + 脱敏视图 + 审计。

Q3 为什么 “三套环境共用一把密钥” 是严重问题?

▸ 答案:因为泄露面变成全线:dev 的开发者、测试环境的日志、CI 缓存都可能泄露这把 key,一旦泄露,生产也沦陷。正确做法是每环境独立密钥 + 轮换,生产密钥只对生产工作负载可见。

Q4 “环境太多” 为什么反而危险?

▸ 答案:因为维护成本与漂移概率随环境数增长:每个环境都要配网络/密钥/数据,没人能保证一致;最终出现 “只有某台机器能复现” 的困境。通常 dev / staging / prod 三套足够,临时环境用 “按需创建、用完销毁”。

Q5 如何避免 “测试消息被生产消费”?

▸ 答案:topic/队列按环境隔离(前缀或独立实例),消费组同理;用 IaC 生成名字(如 app-staging-orders),而不是手工建。共用 topic 是最典型的 “隔离漏洞”。

Q6 定时任务在 staging 该怎么处理?

▸ 答案:默认关闭,需要时手动触发或用 “mock 外部副作用” 的运行。否则 staging 会重复发券/重复对账,甚至因为连了生产下游而影响真实用户。

Q7 怎么证明 “环境隔离有效”?

▸ 答案:做故障演练:在 staging 制造 “写生产” 的尝试(如误配连接串),验证它被拦住(权限/网络/审计);再验证 “生产变更必须经流水线 + 审批”。隔离不是文档,是能被攻击验证的边界。

关联