软件版本与重建
两个 Terraform 变量用于设置 Customer Edge 的软件:ce_os_version 用于操作系统,ce_sw_version 用于 F5 Distributed Cloud 构建版本。两者的行为与直观理解恰好相反——留空字段会获取最新构建而非不安装任何内容,而在一个节点上能成功安装的版本,可能因磁盘较小而在另一个完全相同的节点上失败。
版本字段的作用,分两个阶段
Section titled “版本字段的作用,分两个阶段”区分两个阶段是理解全部内容的关键。若将两者混为一谈,其行为看起来会自相矛盾。
在首次启动时,节点会安装 ce_sw_version 所指定的版本。
terraform/modules/ce-node 使用 version = "latest" 部署市场镜像,因此节点到达时携带的构建版本取决于该镜像当时的内容——而这会随时间变化。ce_sw_version 决定的是目标版本,而非是否执行任何操作;留空意味着由服务端决定,而非节点保持原状。ce_os_version 同理。
不要假设变更方向是向上的。观测于 2026-07-28,镜像携带的构建版本为 20260703-e2c462a——比该机群的 crt-20250613-3382 更新,也比租户所通告的 crt-20260201-0179 更新。指定一个比镜像携带版本更旧的构建,意味着要求节点向后回退,这是常见操作:该机群正是以此方式创建并正常运行的。
将版本字段留空是风险最高的选择,而非中立选择。 创建时,服务端不会忽略空字段——它会将其填充为最新通告版本并进行安装。一个在两个字段均未设置的情况下创建的站点,最终被固定到 crt-20260201-0179 和 OS 9.2026.14(即租户当时通告的两个版本),随后安装失败。观测于 2026-07-29。
这带来两个后果:留空意味着”给我最新版本”,因此未固定版本的部署最可能触及下文所述的磁盘限制。此外,你无法通过留空其中一个字段来单独隔离它,因为服务端会将其填充——请有意识地同时设置两个字段,或接受各自的最新版本。
首次启动后,不会自动升级任何内容。 F5 Distributed Cloud 通告较新的构建后会等待。“节点保持在其落地版本”这一说法适用于创建之后,而非创建过程中。
两个阶段在站点对象上均可见。观测于 2026-07-28,该机群:
volterra_software_status.available_version crt-20260201-0179operating_system_status.available_version 9.2026.14而节点运行的是 crt-20250613-3382 和 OS 9.2024.6。更新的构建已提供但未被采用——这是稳定状态,而非停滞的升级。
Terraform 无法更改版本,但 API 可以
Section titled “Terraform 无法更改版本,但 API 可以”这是两个独立的事实,将其混淆会导致错误的计划。
Terraform 无法更改。 ce_os_version 和 ce_sw_version 实际上仅在创建时有效。更改其中任何一个并执行 apply,API 将以 [BAD_REQUEST] Invalid request parameters 拒绝更新。观测于 2026-07-29,在临时站点上测试了全部三个方向——向前固定到更新的构建、向后固定到更旧的构建,以及通过清空两个字段来取消固定。向前固定并非特殊情况。
API 可以更改。 F5 Distributed Cloud 为每个站点提供专用的升级操作,可就地启动变更——无需重建,也无需 Terraform 参与:
# 软件构建curl -X POST -H "Authorization: APIToken $TOKEN" -H 'Content-Type: application/json' \ --data '{"version": "<software-version>"}' \ "$API_URL/api/config/namespaces/system/sites/<site-name>/upgrade_sw"
# 操作系统curl -X POST -H "Authorization: APIToken $TOKEN" -H 'Content-Type: application/json' \ --data '{"version": "<os-version>"}' \ "$API_URL/api/config/namespaces/system/sites/<site-name>/upgrade_os"观测于 2026-07-29:软件调用返回 200,站点进入 UPGRADING 状态,deployment_state.phase 为 UPGRADE_IN_PROGRESS,站点对象的请求版本更改为所提交的版本。省略字段会返回 400,错误信息为 version empty in the request,字段名称由此得到确认。
预留数小时而非数分钟,并且不要在出现失败时慌乱。 在默认磁盘节点上,升级到 crt-20260201-0179 运行了约一小时,中途报告 UPGRADE_FAILED,result 为 Failed,然后成功完成并运行在新构建版本上。平台会自动重试。
这对监控升级或编写升级脚本的人有直接影响:Failed 结果是需要等待的状态,而非最终判决。将第一次失败视为最终结论,会把一次即将成功的升级报告为失败。
注意路径中的分组:这些接口位于 config 下,而非 operate。operate 下的相同路径返回 404 API Group could not be determined,这是路由消息,并非表示不存在升级操作——这一区别曾让本项目得出错误结论。
如果选择重建而非升级,替换 CE 的所有后果均会适用。
固定的构建版本可能安装失败,站点随即卡死
Section titled “固定的构建版本可能安装失败,站点随即卡死”接受固定版本与成功安装并不等同。在一个新创建的单节点 Azure Secure Mesh v2 Customer Edge 上,固定到 crt-20260201-0179 后,站点对象立即报告了固定版本——随后安装失败:
site_state PROVISIONINGphase UPGRADE_FAILEDresult Failedlast_installed (empty)message stage: 10, app: voucher obj: voucher objKind: DaemonSet failed ... required replicas: 1, current replicas: 0观测于 2026-07-28,并于 2026-07-29 复现两次。操作系统固定版本在同一次运行中正常安装(9.2024.6 升级到 9.2026.14,状态为 UPGRADE_COMPLETED);仅软件安装失败。站点始终未到达 ONLINE,last_installed_version 保持为空,因此没有任何内容回滚到可用构建——没有可供回滚的早期成功安装。
创建时的失败与升级过程中的失败不同。 两者行为不同,这在你决定是否介入时至关重要:
| 创建时 | API 升级过程中 | |
|---|---|---|
| 是否会重试至成功? | 否——连续两次保持 Failed 超过 20 分钟 | 是——已恢复并完成 |
| 节点最终处于何种状态? | PROVISIONING,未安装任何内容 | ONLINE,运行可用构建 |
| 是否可以放任不管? | 否,已卡死 | 是,会自行恢复或保留旧构建 |
因此,创建时的失败需要使用更大磁盘重建,而升级时报告 Failed 则应等待一段时间再下结论。
原因是磁盘,而非版本。 通过一个软件 × OS × 磁盘大小的矩阵测试,每种组合各创建一个临时的单节点 Azure Secure Mesh v2 站点,均使用相同的市场镜像,可以将问题隔离出来。观测于 2026-07-29:
| 软件 | OS 9.2024.6(镜像自带版本) | OS 9.2026.14 |
|---|---|---|
crt-20250613-3382 | 安装成功 | 安装成功 |
crt-20260201-0179 | 安装成功 | 失败,仅在默认磁盘上 |
两个版本单独均不会失败。只有组合在一起,且仅在镜像默认磁盘上才会失败——同样的组合在 33 GB 及所有测试的更大规格上均能成功安装。因此,更新的构建在此并非不受支持,更新的操作系统也不是;两者合在一起所需的磁盘空间略超过默认节点的容量。
terraform/modules/ce-node 未设置 disk_size_gb,因此每个 Customer Edge 都使用镜像默认值——而这恰好是该组合会失败的唯一规格。若要运行该版本组合,请扩大磁盘。
差距出人意料地小,这也是为何这个问题长期被误认为版本问题。默认值为 31 GiB(health 命令报告 size_gb: 31,在失败状态节点上 /var 为 29 G,剩余 3.5 G)。33 GB 可以正常安装。 因此默认值的不足约为两个千兆字节,差距并不大。
无论如何,在将版本变更应用到整个机群之前,请先在临时站点上进行测试:以此方式失败的机群会卡在 PROVISIONING,重建是唯一的出路。
本文档所描述的构建版本
Section titled “本文档所描述的构建版本”本站点的命令参考描述的是 crt-20250613-3382,即该机群所运行的构建版本。仅存在于较新构建上的命令记录在 sitecli/command-classification.json 的 not_on_this_build 下,并单独记录在较新构建上的命令中,因此该文档中的内容不应被视为在当前版本可用。另请参阅节点上的命令。