部署生命周期
部署是一次受控状态转换,系统从已知基线进入候选版本。部署发布契约要明确三件事:候选版本必须满足哪些兼容条件,扩大暴露范围需要哪些证据,以及每类故障对应什么恢复动作。没有这份契约,构建成功只能说明生成了若干文件。它无法证明候选版本能与线上系统共存,也无法证明比较结果可信,更无法证明服务可以恢复。
本章以 第 88 章 产出的集成发布为输入,把它变成一次可运维的变更。控制对象是发布清单:一份经过签名的记录,用来组合共同决定行为的各项修订版本,即使它们分别部署。只有当期望状态与观测状态一致、所需证据已经附上,并且发布负责人接受剩余风险时,生命周期才算结束。最终产物是一份部署发布记录。
生成式 AI 出现之前,生产机器学习就已经暴露了这个问题。学习代码只占已部署机器学习系统的一小部分,数据依赖、配置、服务和监控才构成大部分运维范围 (Sculley et al. 2015)。因此,ML Test Score 把数据、模型、基础设施和监控测试都视为生产就绪证据 (Breck et al. 2017)。生成式 AI 又加入了提示词、检索、工具、策略、随机性评测,以及运维方往往无法检查实现的托管模型。发布需要控制的状态因此更多,早先的工程责任却一项也没有减少。
明确发布状态
模型检查点是一项制品,不是一次发布。发布清单把所有会影响行为的组件绑定到一个可审查的身份上。部署事件再把这份清单映射到某个环境和群组。最后,由运行时观测状态报告实际提供服务的内容。必须把这三类记录分开,因为清单获批并不代表每个单元都已经收敛到该版本。
发布清单至少应该为下列部分记录系统指纹。
| 表面 | 需要记录的身份 |
|---|---|
| 推理 | 模型修订版本、分词器或聊天模板、适配器、服务运行时、解码策略 |
| 上下文 | 提示词修订版本、检索快照、语料与索引修订版本、嵌入与重排序流水线 |
| 动作 | 工具实现与工具 Schema、权限与策略修订版本、影响类别 |
| 路由 | 路由配置、回退顺序、功能开关、分配策略 |
| 状态 | API 与事件 Schema、数据 Schema、序列化器、缓存命名空间、迁移阶段 |
| 运维 | 基础设施摘要、区域或单元、遥测 Schema、评测器修订版本 |
| 可变依赖 | 端点、提供商修订版本、区域、声明的可变性、证据有效期、探针、回退方案、终止开关 |
对于可以控制的制品,应记录不可变的内容摘要,而不是 latest 之类的可变标签。机密值绝不能写进清单,只能记录有明确作用域的机密版本引用。托管 API、在线工具或持续变化的语料库未必能提供字节身份。此时应把这种限制登记为有界的可变依赖,为它指定负责人、契约有效期、变更检测探针、重新验证规则和回退方案。不透明的提供商标识可以成为一项证据,但无法证明字节级可复现。
能识别制品,不代表制品可信。摘要只能证明字节身份,不能证明这些字节由谁发布。签名只能证明某项声明在既定信任策略下有效,不能证明发布安全。软件物料清单只能盘点声明的组成,不能证明实现正确。来源证明记录构建过程,却不能证明源代码本身无害。这些控制必须配合使用:准入时一并验证制品摘要、签名清单、证明对象、获准的构建器与来源,以及软件物料清单。SLSA 和 in-toto 等供应链来源证明让这条链路可以审查 (SLSA Community 2025; Torres-Arias et al. 2019)。更新元数据还应抵御回滚攻击、冻结攻击,以及把从未共同获批的修订版本混搭起来。更新框架(The Update Framework)对这些威胁给出了正式模型 (Cappos et al. 2026)。
发布清单记录系统指纹,发布记录则还要包含范围、负责人、权限、验收证据、已知缺口、有效期、期望状态、观测状态和恢复目标。每个请求、对话或长任务都应记录自己被分配到的发布版本,发生事件时才能追溯当时究竟由哪套行为处理了它。
区分生命周期动作
下面这些动作并非同义词。
- 部署:让候选版本在某个环境中可用,但不一定向用户开放。
- 发布:为声明的群组启用候选版本。
- 提升:所需证据通过后,扩大暴露范围。
- 中止:在暴露继续扩大或发生不可逆操作之前停止转换。
- 回滚:恢复到上一条仍兼容的服务路径。
- 向前修复:无法安全撤回时,部署修复版本。
功能开关可以把部署与发布分离。滚动更新会在新旧版本共存期间逐步替换容量。蓝绿部署维护两套环境并切换流量,只有两套环境同时接收流量时,它才构成金丝雀。金丝雀是一次局部、限时的发布,需要与对照组比较 (Warner and Davidovič 2018)。应根据变化涉及的状态和风险选择机制,没有哪一种机制在所有场景下都最安全。
暴露前验证共存
发布期间,新旧代码会同时运行。因此,兼容性边界远不止请求和响应类型。它还包括 API 与事件 Schema、数据 Schema 与序列化器、旧读取方与新读取方、旧写入方与新写入方、检索索引代际、缓存命名空间、会话状态、检查点状态、排队任务和工具影响记录。如果仍要保留流量回滚能力,旧版本就必须能够安全解释候选版本写入的内容。
进入生产环境前,需要双向测试。
| 测试夹具 | 回答的问题 |
|---|---|
| 旧客户端访问新服务端,新客户端访问旧服务端 | 请求与响应契约是否兼容? |
| 新写入方写入后由旧读取方读取,旧写入方写入后由新读取方读取 | 混合版本能否共享持久状态? |
| 一半旧版本、一半新版本的机群 | 路由、缓存、队列和会话语义能否在共存期间保持正确? |
| 升级、由候选版本写入,再降级 | 承诺的回滚是否真的能保住数据? |
| 长会话和排队任务跨越切换点 | 有状态工作能否固定在同一个发布身份上? |
| 重试迁移并执行恢复 | 迁移步骤是否幂等、可观测且可恢复? |
AWS 的回滚安全指南对分布式部署提出了同样的纪律:先让读取方兼容,再改变写入方;需要回退时则按相反顺序执行 (Pokkunuri 2019)。一致性测试矩阵既要在 CI 中运行,也要在接近生产的环境中使用真实的序列化器、队列、Schema 和适配器运行。只针对单一版本通过单元测试,无法证明混合版本兼容。
如果 Schema 无法通过一次兼容变更完成迁移,应采用扩展、迁移、收缩 (Sato 2014)。先扩展读取方和 Schema,让它们同时接受新旧格式,同时让写入方继续保留旧格式。随后按需双读或双写,用可恢复的检查点执行回填,并验证数量、引用完整性和语义等价。只有混合版本测试通过后,才能启用新格式。收缩应放在后续发布中进行,等旧读取方、旧写入方、会话和任务全部退出,并且回滚窗口已经关闭后,再移除旧格式。移除旧格式是一条明确声明的恢复边界,不是日常清理工作。
随证据和暴露范围逐步提升
提升从构建并验证开始,而不是从用户流量开始。首先验证摘要、签名、来源证明、配置、Schema、容量、凭据和兼容性测试夹具。随后运行 第 87 章 定义的离线闸门,其中既包括确定性不变量,也包括代表性切片上的质量估计。暗启动会启动候选版本及其依赖,却不向它路由请求,从而暴露启动、容量和控制平面故障。
影子执行可以发现离线数据集与线上输入之间的差距,但它绝非无害。复制请求可能泄露数据、消耗提供商配额、污染共享缓存、修改共享状态,甚至执行工具。安全的影子路径必须先应用当前授权再复制请求,抑制副作用,使用沙箱化工具,限制出站访问,使用隔离缓存和隔离状态,限制负载,将追踪数据隔离保存,并丢弃候选输出。有些工作负载无法安全地运行影子流量。
真正的暴露从一个受限单元开始,随后进入粘性金丝雀。必须明确分配单元是租户、用户、会话、对话还是任务。如果状态或体验会延续,就应选择能避免同一项工作跨越候选版本和基线版本的单元。保留同期对照组,同时记录分配记录与实际暴露,并按观测到的发布版本标记遥测数据。在解释结果之前,先检查样本比例失配。计划分配与实际分配不一致,往往说明分配逻辑或埋点存在故障 (Fabijan et al. 2019)。
区域波次用来限制相关故障。先选择一个规模较小但有代表性的单元,再进入特征不同或流量更高的区域。只有经过烘焙期后才能提高并行度。保留故障转移容量和容量余量,遵守数据驻留与本地依赖约束,绝不同时更新同一故障域内的全部副本。条件允许时,每次比较只保留一个活跃变更,以便归因。路由和配置应从上一已知正常记录以原子方式发布,并让每个波次遵守同一个全局停止条件。这种分阶段形态沿用了成熟的无人值守部署实践 (Liguori 2020)。
让闸门回答发布问题
确定性检查与统计检查回答的是不同问题。Schema 验证、授权、策略、幂等性、工具权限、迁移完整性和路由身份都属于确定性不变量,任何一项违反都会阻止提升。统计比较不能替代这些检查。它估计的是某个总体中不确定的质量或性能差异。
对于每个必需的指标或切片 ,定义
其中, 表示候选版本在声明总体上的结果, 表示同期对照组在同一总体上的结果。令 为 的有效置信下界,令 为发布前声明、服务可以容忍的实际损失,也就是非劣效界值。必要的质量条件是
这仍不是完整闸门。发布前还要声明一个主要指标、保护性指标、最小可检测效应、切片、最低流量、驻留时间和延迟结果窗口。闸门必须要求证据完整性。分配、暴露、评测器或遥测数据缺失时,必须默认阻止提升。即使候选版本优于一个已经失效的对照组,也必须满足绝对 SLO 和伤害边界。共同故障、群组间干扰、早期分配造成的残留效应、新奇效应和延迟结果,都会让简单比较失效。线上对照实验实践为这些检查提供了实验基础 (Kohavi et al. 2009)。
不断查看普通固定时域区间,直到它通过为止,会改变原本的错误率。应选择固定时域,或者选择专为持续监控和可选停止设计的始终有效方法 (Johari et al. 2022)。“没有显著差异”并不是安全证据,实验可能只是检验功效不足。只有发布前声明的界值和运维保护条件通过,候选版本才能提升,而不是因为没有告警就默认通过。
生成具有随机性,因此逐字节完全一致通常不是合适的质量契约(第 31 章)。但这不代表所有发布决策都应依赖统计。服务层让质量比较转向总体估计,Schema、权限、副作用与状态契约仍然必须精确。因此,发布闸门要把 第 87 章 的评测证据、第 88 章 的边界契约,以及 第 56 章 的授权规则结合起来。
提升后检测变化
即使没有更换模型,一次发布也可能发生变化。配置漂移、策略漂移、检索语料或索引漂移、Schema 漂移、工具漂移、评测器漂移、遥测漂移、运行时漂移和基础设施漂移,都会改变观测到的行为。自托管系统也不例外,可变标签、内核、硬件、缓存和在线数据都可能在底层移动。
对于托管依赖,应优先选择不可变修订版本,并记录响应中实际观测到的模型或提供商修订版本。如果提供商只暴露可变别名,就要缩短证据有效期,运行变更检测探针,关注弃用通知,并要求在身份变化前或变化后立即重新验证。固定探针无法证明完全等价,但能让原本无声的变化变得可见。生产故障应通过 第 92 章 的数据回路进入整理过的回归集。直接回放原始追踪数据,仍需重新执行当前授权并隔离副作用。
每个单元都要持续协调期望状态与观测状态。控制平面健康,并不能证明每个副本都加载了正确的提示词、索引或策略。混合版本检测、带发布标签的遥测数据和定期黑盒探针可以弥合这道缺口。
恢复系统,而不只是切回流量
恢复包含多种动作。中止会停止继续暴露。流量回滚会把新工作路由到上一条兼容的发布路径。状态恢复会把持久数据恢复到一个已知时间点。禁用功能或终止开关可以遏制某项能力。撤销凭据可以限制已经受损的依赖。补偿用于协调无法抹除的外部影响。向前修复则修补上一版本无法安全读取的状态。这些动作不能互相替代。
在宣称回滚安全之前,必须证明上一版本制品仍被保留且可以加载,它的凭据和依赖仍然有效,有足够的容量余量,它的读取方能够向后兼容当前的持久状态和排队状态,并且没有不可逆影响越过声明的恢复窗口。还要记录恢复时间目标(RTO)和恢复点目标(RPO)(Swanson et al. 2010)。备份恢复是一套具有可测数据损失和耗时的恢复程序,不是普通的路由操作。
发布前应把每项变更归入以下类别之一。
- 可逆: 将流量回滚到上一发布版本即可恢复服务。
- 可恢复: 除了流量回滚,还需要状态恢复或明确的补偿动作。
- 只能向前修复: 经过某个指定迁移或外部影响后,回滚将不再安全。
停止流量只是开始。还要决定是排空还是取消进行中的请求,如何处理队列和积压,哪些长会话继续保留原分配,以及恢复期间如何阻止混合版本写入方。随后协调工具影响账本和外部副作用,再执行恢复验证:逐单元比较期望清单摘要与观测清单摘要,运行黑盒任务和确定性不变量,检查 SLO 与策略指标,验证数据和序列化器完整性,检查队列与缓存、各项依赖,以及遥测链路本身。测量 RTO 和 RPO,经过一段烘焙期持续观察,只有明确的终止条件全部满足后才能关闭事件。NIST 的恢复指南同样要求事先规划、开展测试、验证恢复结果并持续监控 (Bartock et al. 2016)。
如果影响或不确定性较大,应尽早宣布事件。明确事件指挥官、运维负责人、沟通负责人、发布负责人和记录员,冻结无关发布,并维护一条记录证据、决策和实际影响的时间线。缓解措施的目标是恢复安全服务,根因分析可以在紧急阶段过后继续。清晰的角色和持续更新的工作记录,可以避免这些任务在响应期间互相争夺注意力 (Mace et al. 2018)。
演练失败,而不只验证成功
发布流程本身也是软件,需要自己的一致性测试和故障矩阵。
| 故障 | 必需的响应与证明 |
|---|---|
| 金丝雀统计功效不足或分配错误 | 暂停;验证分配、实际暴露、样本比例、检验功效和驻留时间 |
| 影子副作用或违反数据策略 | 停止影子执行;遏制影响;审计重复数据和授权 |
| 遥测缺失或过期 | 默认阻止提升;恢复前先证明遥测链路有效 |
| 区域发布不完整 | 停止新波次;逐单元协调期望状态与观测状态 |
| 候选版本写入后发现 Schema 不兼容 | 禁止流量回滚;按照迁移记录恢复或向前修复 |
| 回滚或恢复失败 | 升级事件;隔离写入方;保留证据;使用经过测试的备用恢复路径 |
| 提供商别名变化或即将弃用 | 暂停证据;识别实际观测到的修订版本;重新验证或启用回退方案 |
| 恢复看似健康,但用户任务仍失败 | 保持事件开启;再次执行黑盒任务与数据完整性验证 |
应定期演练混合机群升级与降级、候选版本写入后的回滚、备份恢复、区域疏散、控制平面故障、遥测故障和影响补偿。没有真正恢复过代表性状态的方案只是一项假设,不能算作恢复证据。
完整生命周期
对于每个候选版本,都应完成以下步骤。
- 冻结签名发布清单、信任证据、负责人、范围、有效期、兼容性边界、发布策略和恢复类别。
- 构建并验证制品身份、来源证明、Schema、配置、容量、凭据和混合版本一致性测试夹具。
- 通过离线闸门,包括确定性不变量、代表性质量估计、安全策略、迁移检查和恢复前置条件。
- 先暗启动,再只在数据处理和影响隔离已经得到证明的场景中执行影子流量。
- 向受限单元和粘性金丝雀发布,同时保留同期对照组,记录分配与暴露,满足最低驻留时间并确保遥测完整。
- 只有确定性阻断项、绝对保护条件和预先声明的非劣效界值都通过时,才能通过区域波次继续提升。
- 等回滚窗口关闭后再完成迁移,协调期望状态与观测状态,并保留上一已知正常恢复路径。
- 记录证据、事件、偏差、RTO/RPO 结果、已知缺口、有效期,以及接受最终状态的负责人。
最终产物是一份部署发布记录。它说明原本计划运行什么、实际运行了什么、为何扩大暴露范围、转换期间发生了哪些变化,以及哪条恢复路径经过了验证。下一章将讨论,如何为已经向用户提供服务的非确定性行为定义可靠性(第 90 章)。
- 第一批金丝雀应该多有代表性。 低风险内部群组可以限制伤害,却可能遗漏生产负载和真实行为。有代表性的群组能改善推断,却需要接受更大暴露。发布清单应明确第一波次服务于哪个目标。
- 固定时域还是连续决策。 固定时域更容易审计,始终有效的设计则能在保留错误率保证的同时更早停止。看到数据后再更换方法,会让两种方案都失效。
- 降级兼容应该保留多久。 更长的回滚窗口能改善可恢复性,但也会推迟 Schema 收缩并增加运维成本。这项决定应写进发布契约,不能留给临时清理任务。
延伸阅读
- Sculley et al., “Hidden Technical Debt in Machine Learning Systems” (评测债务也是系统债务), 2015. papers.nips.ccSculley 等人描述机器学习系统中的隐性技术债,包括边界侵蚀、纠缠、数据依赖和未声明消费者。
- Breck et al., “The ML Test Score: A Rubric for ML Production Readiness and Technical Debt Reduction” (把测试作为生产就绪标准), 2017. research.googleML Test Score 提供覆盖数据、模型、基础设施与监控测试的生产就绪评分准则。
- Shankar et al., “Operationalizing Machine Learning: An Interview Study” (从业者真正在做什么:版本管理、漂移,以及速度与可复现性之间的张力), 2022. arXiv:2209.09125对18位机器学习工程师的访谈研究识别出MLOps成功的三个关键变量(速度、验证、版本管理),并记录了在生产环境中部署和维护机器学习流水线的实践与痛点。
- Beyer, Betsy; Jones, Chris; Petoff, Jennifer; Murphy, Niall Richard. Site Reliability Engineering: How Google Runs Production Systems (SLI、SLO、错误预算). O'Reilly Media, 2016. sre.googleGoogle SRE 一书提供了本章改造到 AI 系统上的运营词汇:服务承诺、错误预算、事故指挥以及从失败中学习。
评论
登录后评论