feat(ql3): bind deployment locks to release catalogs

This commit is contained in:
whyour
2026-08-16 15:08:15 +08:00
parent 00a65360cf
commit 2ccdd71851
7 changed files with 440 additions and 79 deletions
+24 -20
View File
@@ -73,7 +73,6 @@ node scripts/ql3-release-catalog-consumption-ceremony.cjs \
--source-repository="${repository}" \
--output-directory="${bundle}"
release_set="${bundle}/qinglong3-release-set-${version}-${scope}.json"
catalog_manifest="${bundle}/qinglong3-release-catalog-manifest-${version}-${scope}.json"
consumption_report="${bundle}/qinglong3-release-catalog-consumption-${version}-${scope}.json"
```
@@ -87,9 +86,9 @@ ceremony,也不能与在线 ceremony 下载的文件混合后伪造成同一 t
## 生成离线 deployment lock
`inspect` 成功后,不要手工复制 digest,也不要直接修改仓库中的 Kustomize 占位符。deployment-lock
materializer 在可信工作站离线运行,只读取已经验证的 release set 与本地清单;它不访问 registry、不连接 Kubernetes
API,也不会执行 `kubectl apply`
`audit` 成功后,不要从 bundle 中抽出 release-set 再作为独立输入,不要手工复制 digest,也不要直接修改仓库中的
Kustomize 占位符。deployment-lock materializer 在可信工作站离线运行,必须重新审计完整 three-file bundle,并让同一次审计
读取的 release set 直接进入物化;它不访问 registry、不连接 Kubernetes API,也不会执行 `kubectl apply`
### Local / Compose
@@ -105,7 +104,8 @@ node scripts/ql3-deployment-lock-contract.cjs \
--source-ref="${source_ref}" \
--release-scope="${scope}" \
--repository-owner="${owner}" \
--release-set="${release_set}" \
--source-repository="${repository}" \
--consumption-bundle="${bundle}" \
--allow-root-service=false \
--output="${selection}"
@@ -116,13 +116,15 @@ node scripts/ql3-deployment-lock-contract.cjs \
--source-ref="${source_ref}" \
--release-scope="${scope}" \
--repository-owner="${owner}" \
--release-set="${release_set}" \
--source-repository="${repository}" \
--consumption-bundle="${bundle}" \
--allow-root-service=false \
--selection="${selection}"
```
把已审计的 `service.image``service.allowRootService` 交给现有 Local private prepare/rollout 入口。selection
本身不修改 Compose 文件,也不启动容器。是否允许 root service 必须显式给出,不能由设备默认值推断。
v2 selection 同时绑定 catalog immutable reference、manifest digest、consumption report digest 与 release-set digest。把已审计的
`service.image``service.allowRootService` 交给现有 Local private prepare/rollout 入口。selection 本身不修改 Compose 文件,
也不启动容器。是否允许 root service 必须显式给出,不能由设备默认值推断。
### Kubernetes / Cluster / Worker
@@ -144,7 +146,8 @@ node scripts/ql3-deployment-lock-contract.cjs \
--source-ref="${source_ref}" \
--release-scope="${scope}" \
--repository-owner="${owner}" \
--release-set="${release_set}" \
--source-repository="${repository}" \
--consumption-bundle="${bundle}" \
--manifest="${rendered}" \
--required-images=control \
--output-manifest="${locked}" \
@@ -157,7 +160,8 @@ node scripts/ql3-deployment-lock-contract.cjs \
--source-ref="${source_ref}" \
--release-scope="${scope}" \
--repository-owner="${owner}" \
--release-set="${release_set}" \
--source-repository="${repository}" \
--consumption-bundle="${bundle}" \
--manifest="${rendered}" \
--locked-manifest="${locked}" \
--report="${lock_report}" \
@@ -166,9 +170,9 @@ node scripts/ql3-deployment-lock-contract.cjs \
materializer 只改写 Pod、Deployment、StatefulSet、DaemonSet、ReplicaSet、Job、CronJob 的
`containers`/`initContainers`/`ephemeralContainers`,以及固定名称
`ql3-plugin-package-secret-action-admission` ConfigMap 的 `data.image`。每个改写资源及其 Pod template 都绑定
release-set digest、source revision 与 version annotation;未知位置的完整 QingLong role image authority、畸形已知
container image、缺少 required role、YAML alias/cycle/非 mapping、超限输入或已有输出文件都会失败关闭。
`ql3-plugin-package-secret-action-admission` ConfigMap 的 `data.image`。每个改写资源及其 Pod template 都绑定 release-set、catalog
manifest、consumption report digest、source revision 与 version annotation;未知位置的完整 QingLong role image authority、畸形
已知 container image、缺少 required role、YAML alias/cycle/非 mapping、超限输入或已有输出文件都会失败关闭。
审计成功并完成人工差异检查后,才由有权限的独立步骤执行 `kubectl apply -f "${locked}"`。不要直接 apply
`${rendered}`,也不要使用 `kubectl apply -k` 绕过 deployment lock。
@@ -177,20 +181,20 @@ container image、缺少 required role、YAML alias/cycle/非 mapping、超限
1. 只接受已验证 Cosign exact workflow identity 与 GitHub source tag/revision provenance 的 catalog immutable
referencediscovery tag 无 authority。
2. `schema` 必须为 `qinglong/release-set@v1``release.version``release.sourceRef`
`release.sourceRevision``release.scope` 必须与变更单一致。
2. materializer 只能接受完整 `qinglong/release-catalog-consumption-ceremony@v1` bundle,不能接受旧的松散 `--release-set`;其中
`qinglong/release-set@v1``release.version``release.sourceRef``release.sourceRevision``release.scope` 必须与变更单一致。
3. 镜像集合必须与上表精确相等;每个 `reference` 必须是 digest reference,且 owner/repository 与部署目标一致。
4. Kubernetes 必须先渲染 overlay,再用离线 post-render materializer 生成和复验 locked manifest;嵌套 overlay 的
`newName`/digest 不是最终 authority。Local 必须生成并审计 service selection。两族最终都只能消费 release set 中的
`@sha256:` reference。
4. Kubernetes 必须先渲染 overlay,再用离线 post-render materializer 生成和复验 v2 locked manifest;嵌套 overlay 的
`newName`/digest 不是最终 authority。Local 必须生成并审计 v2 service selection。两族输出都必须绑定同一 catalog manifest、
consumption report 与 release-set digest,并且只能消费 release set 中的 `@sha256:` reference。
5. rollout 前再次确认 catalog receipt/immutable reference 与已检查文件一致。version/source/catalog tag 都只能用于
发现;部署始终以 release set 中的镜像 digest 为准。
## 低资源设备
路由器或其他低配 Edge 设备不需要安装 Node、regctl、Cosign、GitHub CLI、Kustomize 或 materializer。维护者在可信工作站
完成上述 ceremony 和 Local selection 审计,再向设备传输已检查的 canonical JSON,并只把 `local` family 的 immutable
image reference 写入 compose/rollout。
完成上述 ceremony 和 Local v2 selection 审计,再向设备传输已检查的 catalog-bound canonical JSON,并只把 `local` family 的
immutable image reference 写入 compose/rollout。
设备不下载 Cluster 四镜像,也不加载 Kubernetes、CloudNativePG、PostgreSQL driver 或 Worker 私有发布证据。
如果设备本身不运行容器 registry client,可由工作站按 digest 拉取并通过既有离线交付渠道传送镜像;离线包的哈希与