第19章|部署基础:环境、配置、机密、特性开关与版本对齐

这一章解决一个“最折磨人的现实问题”:同一份代码在 dev 好好的,到 staging 就怪怪的,上 prod 直接翻车。 我们要把这种“玄学”拆成可控变量:环境配置机密特性开关,以及最容易被忽视但最致命的:版本对齐

Mindset

环境差异 = 变量,必须被“钉死”

  • 环境不是名字,而是一组可枚举的差异:依赖、网络、权限、数据、配额
  • 差异越不可见,事故越“突然”
  • 治理目标:减少漂移(drift)、减少未知未知
Core split

配置 / 机密 / 开关:三者分离

  • config:版本化、可回滚、可审计
  • secret:最小权限、短期化、轮换与吊销
  • flag:灰度发布、秒级止损、变更可追溯
Outcome

版本对齐:回滚要“成套”

  • 应用版本、配置版本、数据迁移版本要能一起前进/一起撤退
  • 只回滚镜像不回滚配置,等于把事故续命
  • 目标:known-good bundle(已知好组合)

1. 环境差异从哪里来?(以及为什么它总在你最自信时出现)

“在我电脑上没问题”不是笑话,而是一句诊断结论:你的系统包含了太多隐式依赖。 CD 世界里,最可怕的不是差异本身,而是差异不可见、不可追溯、不可回滚。

1.1 常见差异维度清单(建议抄到你的发布检查表里)

经验:“环境越像生产越好”不是绝对真理。更准确的说法是:staging 必须在会导致事故的维度上足够像生产。
环境漂移(Drift)地图:差异越隐蔽,越容易制造“突然事故” 目标:把差异显式化、版本化,并能被检测/审计 Environment Visible differences Hidden drift dev fast feedback · permissive mock deps · small data · wide perms toolchain versions vary local env state, caches staging prod-like · verify same deps · same network class cert chain / DNS edge cases seed data drift prod protected · audited strict perms · quotas · real traffic unknown unknowns rare paths + scale effects 治理手段:声明式配置 + 版本化 + drift detection
图 1:环境漂移地图。CD 的第一件事是把差异显式化,并让它可检测、可审计、可回滚。

2. 配置/机密/开关:三类变量,三套治理

如果把它们混在一起,你会得到四种经典事故:

  1. “回滚镜像但没回滚配置”:事故复发,甚至更严重。
  2. “把机密当配置”:泄露、权限失控、无法审计。
  3. “把开关当配置写死”:没有秒级止损能力,只能发 hotfix。
  4. “把配置当代码改”:改动频繁但缺少变更治理,线上不可控。
核心原则:config 追求可回滚,secret 追求可吊销/轮换,flag 追求秒级止损。目标不同,工具与流程也应不同。
变量治理三角:三种变量,三种“正确的默认值” 把变量从“混合汤”变成“可控部件” Config Secret Feature flag Goal versioned + rollback auditable change Goal least privilege short-lived + rotate Goal progressive rollout kill switch (seconds) 不要混:目标不同 → 流程不同 口诀:配置可回滚,机密可吊销/轮换,开关可秒级止损 —— 三者分别治理。
图 2:变量治理三角。把“目标”写清楚,才能选对工具:配置中心、密钥管理、开关平台各司其职。

3. 版本对齐:应用、配置、数据要能一起前进/一起撤退

“回滚”不是一个按钮,而是一个工程事实:你回滚的对象必须是一套兼容组合,而不是单个镜像或某个 YAML。 否则就会出现:镜像回滚了,但配置还在新版本;或者代码回滚了,数据库 schema 已经推进,旧代码读不懂新数据。

3.1 三个版本的关系

目标:定义一个 release_bundle:它包含(app_digest, config_version, schema_stage, flags_snapshot, approvers, rollout_id)。回滚时回滚 bundle。
版本对齐:用“发布包(bundle)”而不是“单点回滚” 目标:known-good combination · 回滚回到一套兼容组合 release_bundle app_digest: sha256:… config_version: cfg-2026.03.18-7 schema_stage: expand-only flags_snapshot: ff-913 approvers: alice,bob · rollout: canary-10% Aligned rollout 1) deploy app_digest 2) apply config_version 3) verify metrics + gate → expand traffic Rollback logic 不要“回滚单点”。回滚到上一套 bundle:app + config + flags(必要时) Bad rollback only app back → config stays new Risky rollback schema already moved (no compat) Good rollback rollback to previous bundle (known-good)
图 3:版本对齐的核心是“发布包(bundle)”。回滚不是回滚某个点,而是回滚到上一套已知好组合。

4. 一个可落地的最小实践清单(你今天就能开始做)

  1. 把环境差异列出来:依赖/网络/权限/数据/资源五维度,每个维度至少给出“检测点”。
  2. 把变量分离:config/secret/flag 三者各自有仓库/系统/审批策略。
  3. 把回滚对象升级为 bundle:每次发布记录 app_digest + config_version + flags_snapshot + 审批信息。
  4. 把兼容性写进设计:变更默认向后兼容,数据库走 expand/contract(下一章会更深)。
  5. 把“秒级止损”变成默认能力:关键路径功能必须可用开关快速关闭。
你现在应该能回答:
1) 我们环境差异的“清单”是什么?哪些差异是隐式漂移?
2) 配置/机密/开关分别归谁管?如何审计?如何回滚/吊销/止损?
3) 我们回滚时回滚的“对象”是什么?是否能回到上一套已知好组合?
← 上一章:CD 总览 下一章:发布策略 1(蓝绿、金丝雀、灰度) →