版本与部署控制面:从不可变快照到灰度与回滚
version 与 deployment:先分清两个原语
前一章把 env 与 binding 全部讲清楚,读者手上已经有一个"能跑通的 Worker"——能读 vars、读 secrets、调用 KV/D1/R2 等等。但这只解决了"写代码",还没解决怎么把它交付到生产。Cloudflare 在这一层的设计选择是:把"提交了什么"和"现在线上跑的是哪个"显式分开。
第一个原语是 version(版本)。Versions & deployments 文档原话:"Every time you change your Worker's code or configuration, Workers creates a version. A deployment determines which version(s) are actively serving traffic."——每次你改 Worker 的代码或配置,Workers 都会创建一个 version。这个 version 捕获该时点的"bundled code, static assets, bindings, compatibility settings"——也就是你在 wrangler.toml 加上代码共同描述的那份不可变快照。每个 version 都有唯一 ID,记录创建者、创建时间、来源。读者可以给 version 附加 message 和 tag(让 CI 提交号、PR 号有自然落点)。
第二个原语是 deployment(部署)。"A deployment determines which version(s) of your Worker are actively serving traffic. A deployment can reference one version (serving 100% of traffic) or two versions (with traffic split between them during a gradual deployment)."——deployment 是"接流量的是哪个或哪两个 version"的指向。一个 deployment 可以是单 version 100% 流量,也可以是两个 version 按百分比切流(这就是 gradual deployment,灰度)。每个 deployment 同样记录创建者、创建时间、参与的 version。
把这两个原语拆开之后,"版本"与"部署"在工程上的意义是:
- version 是不可变工件——它一旦创建就锁定,可以被任意 deployment 引用、可以回滚到它、可以被 Preview URL 指向;
- deployment 是当前生产状态的指向——它可能引用一个 version,也可能引用两个 version 切流;
- 默认
wrangler deploy把两步合在一起——上传新代码、上传新 version、立即创建一个 100% 流量的 deployment。适合小项目和快速迭代。 - 解耦路径是
wrangler versions upload+wrangler versions deploy——前者只创建不可变 version(不接流量),后者把指定 version 设为接流量。适合需要审批、需要先在其他环境验证、需要在多版本之间切流的工程。
Deployment management 文档给出几个明确的工程约束。第一是"100 个最近版本上限":文档原话 "You can only create a deployment with the last 100 uploaded versions of your Worker"——超过 100 个的旧 version 不会被自动清理,但不能被新 deployment 引用。这条隐含一个工程实践:长期维护的项目应当定期清理无用 version(dashboard 或 API),把"可回滚范围"留给真正在用的版本。第二是"首次必须 C3 或 wrangler deploy":文档原话 "You must use C3 or wrangler deploy the first time you create a new Workers project. Using wrangler versions upload the first time you upload a Worker will fail."——首次项目必须用 wrangler deploy 把项目先建起来,第二次起才能用 versions upload 走解耦路径。第三是"service worker 语法不支持":上传到 versions upload 的 Worker 必须是 ES modules 格式,service worker 语法会被拒收;以及 Durable Object 类生命周期变更不能通过 versions upload,必须走 wrangler deploy——这是因为 DO 类生命周期变更需要 migrations,而 migrations 与版本上传是两条不同的控制路径。
最后还有一个非显然的事实:关联资源(KV / R2 / Durable Objects / D1)的状态变化不被 version 跟踪。文档原话:"State changes for associated storage resources such as KV, R2, Durable Objects, and D1 are not tracked with versions."——version 跟踪的是"你的代码 + 你的 binding 配置",不是"你的 KV 里现在有什么数据"。…