docs: document v02 cicd performance budget

This commit is contained in:
Codex
2026-05-30 09:50:08 +08:00
parent e2a29f9fd8
commit b52c569d17
+95 -1
View File
@@ -116,6 +116,99 @@ CI/CD 内部由 UniDesk 手动触发入口、PipelineRun、component planner、B
写 mirror 的一致性模型是 local-first、manual-flush。promotion task 只能持有 mirror/relay 写凭证,不持有 GitHub deploy keyGitHub deploy key 只存在于 `devops-infra` mirror/relay sync/flush 边界。mirror/relay 必须在本地 receive 期间完成 object closure、目标 branch allowlist、non-fast-forward 拒绝和 changed-path 最小校验;receive 成功后本地 ref 即为 Argo 可消费事实。flush 失败不得回滚已经 rollout 的本地 GitOps revision,但必须保留 pending/outbox 状态,下一次手动 flush 可重试并输出 last error,不得静默丢弃。
## 性能预算与回归判定
`v0.2` fast lane 的性能目标是让 code-only/env-reuse 场景主要受 G14 集群调度、PVC 和本地磁盘 I/O 限制,而不是受 GitHub 网络、重复依赖安装或无效 runtime 等待限制。性能预算只用于发现退化和指导排障,不新增发布门禁;发现退化时先按本节做现场热探测,再决定是否需要完整 CI/CD 复跑。
代表性 env-reuse 场景的对比基线如下。后续更换 runner、PVC、Tekton controller、Argo repo server 或 mirror 存储后,必须重新测量并更新本表的预算口径。
| 场景 | 关键路径总耗时 | 主要阶段表现 | 判定口径 |
| --- | ---: | --- | --- |
| env-reuse + mirror-write 初始路径 | 约 108s | `prepare-source` 约 56s;包含无效 `npm ci` 和多余探针;runtime wait 仍执行 | 只作为旧基线,不应回归。 |
| 移除 `prepare-source` 中的 `npm ci` | 约 76s | `prepare-source` 降到约 21s;其余路径仍有多余探针和 runtime wait | 不应再恢复依赖安装。 |
| 剪裁 fast-path 探针 | 约 50s | `prepare-source` 约 11s`gitops-promote` 约 7s`runtime-ready` 约 17s | runtime 有实际变化时的合理预算。 |
| P1 no-op runtime skip | 约 37s | `prepare-source` 约 10s`plan-artifacts` 约 6s`collect-artifacts` 约 7s`gitops-promote` 约 8s`runtime-ready` 跳过 | source-only 且 runtime identity-only 变化时的目标预算。 |
当前预算判定:source-only、所有 service 都复用 artifact、GitOps runtime 只发生 source identity 变化时,总耗时应接近 40s;超过 50s 需要先查是否误触发 `runtime-ready`、是否发生 GitHub 直连、是否恢复了 `npm ci` 或无效 preflight。真正需要 rollout 的 code-only 变更允许约 50s,因为 `runtime-ready` 必须等待 Argo 与 workload 收敛。涉及 BuildKit publish、env image rebuild、registry push 或真实 runtime 滚动时,不适用 40s 预算,应按 affected service 的 build 耗时单独测量。
关键阶段预算如下:
| 阶段 | 正常预算 | 退化信号 |
| --- | ---: | --- |
| `prepare-source` | 约 10-12s | 超过 20s、出现 `npm ci`、访问 GitHub canonical remote、catalog fetch 超过数秒。 |
| `source-clone` | 约 1-2s | 超过 5s 通常说明没有命中 `devops-infra` mirror 或 PVC/网络异常。 |
| `catalog-fetch` | 小于 1s | 超过 3s 先查 mirror refs、object closure 和 catalog branch。 |
| `plan-artifacts` | 约 5-7s | `buildServices``rolloutServices` 非空但本轮只改 CI/CD 文档/脚本时,先查 component input 与 catalog 是否加载。 |
| `collect-artifacts` | 约 6-8s | 未输出 `artifact_reuse``buildSkippedCount=9` 时,先查 catalog digest 与 service identity。 |
| `gitops-promote` no-op | 约 7-9s | 未输出 `skipped-runtime-unchanged`,或写入了 `v0.2-gitops`,说明 runtime 比对未命中。 |
| `runtime-ready` | no-op 应跳过;真实 rollout 约 15-20s | no-op 场景出现 TaskRun 即为 P1 退化;真实 rollout 超时则按 Argo/workload 排障。 |
## 性能优化原理
`prepare-source` 不安装依赖。该 task 只负责 checkout source、读取上一版 catalog、输出 source identity 和基础文件,不运行 `npm ci`、不探测 npm registry、不做与后续 task 重复的工具链检查。需要依赖的语法检查、render test 或 build task 必须使用各自镜像内已有工具或在专属阶段处理,不能把全仓依赖安装塞回 source 准备阶段。
Git 读写都走 `devops-infra` 本地 mirror/relay。读路径用 HTTP mirror checkout `v0.2` source 和 `v0.2-gitops` catalog;写路径把 promotion 推到 mirror/relay 的 `v0.2-gitops`Argo 也从 mirror/relay 读取。这样 source clone、catalog fetch、GitOps clone/push 都落在集群内网络和本地磁盘,GitHub 只通过手动 `sync`/`flush` 进入或离开本地 mirror,不在 CI 关键路径内。
env image 复用把系统依赖和业务代码身份分离。`environmentDigest` 表示可复用运行环境,`HWLAB_BOOT_REPO``HWLAB_BOOT_COMMIT``HWLAB_BOOT_SH` 表示本次代码启动身份。code-only 变更只更新 boot metadata 和 runtime identity,不发布新 env image;只有 `environmentInputHash` 变化时才进入 env rebuild。
P1 no-op runtime skip 只跳过无实际 runtime 变化的等待。planner 输出 `buildServices=[]``rolloutServices=[]` 后,`gitops-promote` 会在写入前对旧 `runtime-v02` 与新 render 结果做归一化比较:忽略 source commit、artifact source commit、boot commit 和等价 commit env/annotation 这类 identity-only 字段。如果归一化结果相同,promotion 输出 `skipped-runtime-unchanged`,把 Tekton result `runtime-ready-required=false` 写出,并跳过 GitOps commit、push、Argo hard refresh 和 `runtime-ready`。如果 workload spec、image digest、env image、SecretRef、Service、Ingress、FRP、ConfigMap 或 rollout service 有实际变化,必须保持 `runtime-ready-required=true` 并等待 runtime 收敛。
快速优化不能绕过 fail-closed 语义。mirror miss、commit ancestry 不合法、boot script 缺失、digest 缺失、Argo observer RBAC 不足、workload 未 ready 或公网 health 不一致,都不能为了追求耗时而降级为 warning。允许跳过的只有已经证明 runtime desired state 没有实际变化的等待。
## 快速排障
先看一次 PipelineRun 总览,确认是否是性能退化、构建退化还是 runtime 收敛失败:
```bash
bun scripts/cli.ts ssh G14:k3s script -- 'set -eu
ns=hwlab-ci
pr=<pipeline-run-name>
kubectl get pipelinerun -n "$ns" "$pr" \
-o jsonpath="status={.status.conditions[0].status}{\"\\n\"}reason={.status.conditions[0].reason}{\"\\n\"}message={.status.conditions[0].message}{\"\\n\"}start={.status.startTime}{\"\\n\"}done={.status.completionTime}{\"\\n\"}"
echo taskruns
kubectl get taskrun -n "$ns" -l tekton.dev/pipelineRun="$pr" \
-o jsonpath="{range .items[*]}{.metadata.name}{\"\\t\"}{.metadata.labels.tekton\\.dev/pipelineTask}{\"\\t\"}{.status.conditions[0].status}{\"\\t\"}{.status.conditions[0].reason}{\"\\t\"}{.status.startTime}{\"\\t\"}{.status.completionTime}{\"\\n\"}{end}" | sort -k2,2
echo skipped
kubectl get pipelinerun -n "$ns" "$pr" \
-o jsonpath="{range .status.skippedTasks[*]}{.name}{\"\\n\"}{end}" | sort
'
```
再抓关键日志。正常 no-op fast lane 应看到 `source-clone` 约 1-2s、`catalog-fetch` 小于 1s、`buildSkippedCount=9`、九个 `artifact_reuse``skipped-runtime-unchanged``gitops-commit``gitops-push``skipped`,并且 `runtime-ready` 出现在 skipped tasks 中。
```bash
bun scripts/cli.ts ssh G14:k3s script -- 'set -eu
ns=hwlab-ci
pr=<pipeline-run-name>
for task in prepare-source plan-artifacts collect-artifacts gitops-promote runtime-ready; do
tr=$(kubectl get taskrun -n "$ns" \
-l tekton.dev/pipelineRun="$pr",tekton.dev/pipelineTask="$task" \
-o jsonpath="{.items[0].metadata.name}" 2>/dev/null || true)
[ -n "$tr" ] || { echo "--- $task skipped/no-taskrun ---"; continue; }
pod=$(kubectl get pod -n "$ns" -l tekton.dev/taskRun="$tr" \
-o jsonpath="{.items[0].metadata.name}")
echo "--- $task $pod selected logs ---"
kubectl logs -n "$ns" "$pod" --all-containers=true | \
grep -E "skipped-runtime-unchanged|runtime-ready-required|runtime-identity-only|g14-cicd-timing|git-operation|g14-ci-plan|artifact_reuse|buildSkippedCount|gitops-commit|gitops-push" || true
done
'
```
常见故障按以下顺序处理:
| 现象 | 优先检查 | 处理原则 |
| --- | --- | --- |
| `prepare-source` 回到 20s 以上 | 日志是否出现 `npm ci`、npm registry probe、GitHub URL、SSH setup 或长时间 catalog fetch | 拆掉无效依赖安装和重复探针;读路径必须回到 mirror。 |
| `source-clone` 超过 5s | PipelineRun 参数 `git-read-url`、mirror service、PVC I/O、`git-mirror status` | 不要改回 GitHub 直连;先修 mirror/read service。 |
| catalog 缺失导致全量 build | `prepare-source` 是否从 `v0.2-gitops` 取到 `deploy/artifact-catalog.v02.json` | 先 `git-mirror sync --confirm`;必要时查 mirror refs/object closure。 |
| `buildSkippedCount` 不是 9 | `g14-ci-plan``affectedServices``buildServices``rolloutServices` 和 changed path summary | 真实业务变更可以 buildCI/CD 文档或 render-only 变更不应误触发全量 build。 |
| no-op 仍执行 `runtime-ready` | `gitops-promote` 是否输出 `runtime-ready-required=false``skipped-runtime-unchanged` | 查 runtime 归一化比较;不要直接删除 `runtime-ready`,只修 no-op 判定。 |
| mirror `pendingFlush=true` 长期存在 | `bun scripts/cli.ts hwlab g14 git-mirror status` 和最近一次 flush 错误 | 手动 `git-mirror flush --confirm`flush 不影响已 rollout 本地 revision,但不能静默积压。 |
| Argo `Synced/Healthy` 但公网不通 | `hwlab-v02-frpc` 日志、master frps allowlist、`19666/19667` | 修 FRP allowlist 或 frpc;不要把 DEV/PROD 入口当作 v02 证据。 |
| `runtime-ready` 超时 | Argo app revision、workload Pod template source commit、Pod events、observer RBAC | 真实 rollout 必须 fail closed;先定位 Argo 或 workload,不要降低等待为 warning。 |
性能退化排障结束后,只把可复用的预算、原理和入口更新到本文;一次性 PipelineRun 名称、Pod 名称、日志全文和临时证据放到 issue 或 PR,不写入长期规格。
## Env 容器复用与三变量启动
`v0.2` code-only fast lane 的 runtime desired state 由三类输入组成:可复用 env image digest、自动推导的 code boot metadata、以及既有 service runtime config。开发者仍按当前 DEV/OPS 流程提交 `v0.2` source commit 和维护 `deploy/deploy.json`;发布入口不得要求人工填写 repo、commitId 或 boot script 路径。
@@ -254,7 +347,8 @@ GitOps branch 已更新、source branch render 通过、PipelineRun 名称存在
| FRP `19666/19667` 入口 | 已实现 | 由 `hwlab-v02-frpc` 与 master frps allowlist 共同提供。 |
| SecretRef 独立与 provider 验收 | 已实现/持续约束 | SecretRef 已独立;验收必须做真实短连接聊天。 |
| env 容器复用三变量启动 | 已实现/持续约束 | device-pod fast lane 已由 CI/CD 自动推导 `HWLAB_BOOT_REPO``HWLAB_BOOT_COMMIT``HWLAB_BOOT_SH`code-only rollout 复用 env image digest,只更新代码身份。 |
| `devops-infra` git mirror/relay 加速 | 部分实现/待迁移写路径 | source/catalog/runtime checkout 读路径已使用独立基础设施集群 mirror/cache;下一步必须把 GitOps promotion、Argo source 和 GitHub flush 收敛到真正写 mirror。runtime namespace 不持有 GitHub deploy keyregistry 保持 G14 `hwlab-ci/hwlab-registry`mirror 同步和 flush 由 UniDesk CLI 手动触发,不设置 CronJob。 |
| `devops-infra` git mirror/relay 加速 | 实现/持续约束 | source/catalog/runtime checkout 读路径和 GitOps promotion 写路径均使用独立基础设施集群 mirror/relayArgo source 指向本地 mirrorGitHub flush 由 UniDesk CLI 手动触发,不设置 CronJob。runtime namespace 不持有 GitHub deploy keyregistry 保持 G14 `hwlab-ci/hwlab-registry`。 |
| CI/CD fast lane 性能预算 | 已实现/持续约束 | env-reuse no-op 目标约 40s;真实 runtime rollout 目标约 50s;不得恢复 `prepare-source` 依赖安装、GitHub 关键路径写入或 no-op runtime 等待。 |
| 自动 registry GC | 未实现 | 初期不启用自动 GC,后续需 lane/profile 保护集。 |
## 平行 lane 运维边界