docs: document v02 cicd parallelism troubleshooting

This commit is contained in:
Codex
2026-05-31 08:12:03 +08:00
parent fddda5daa5
commit ff2c32ca99
+109
View File
@@ -169,6 +169,38 @@ BuildKit publish 采用 service 级全并行 fan-out。
跳过的 task 由 Tekton `when` 表达式裁剪,执行的 task 并行写入 `/workspace/source/service-results/<serviceId>.json`
`collect-artifacts` 只从 report 目录收敛结果,不再通过 `tasks.build-*.results` 直接依赖某个前序 task 输出,因此全并行不会改变 artifact 身份语义。
全并行不是无限资源承诺,而是 DAG 不主动限流。
CI/CD 拓扑只表达依赖:`prepare-source` 输出 source/catalog,轻量检查并行完成后进入 `plan-artifacts`
所有被选中的 `build-*` task 只依赖 `plan-artifacts`,最后由 `collect-artifacts` fan-in。
实际同一时刻运行的 Pod 数由 Tekton controller、Kubernetes scheduler、G14 node 资源、PVC I/O、BuildKit sidecar 和本地 registry 共同决定。
如果这些节点因为容量不足自然排队,可以接受真实并发低于 selected service 数。
不允许为了掩盖排队把 Pipeline YAML 改回服务串行链或固定并发上限。
限制全并行的关键节点如下:
- `Tekton controller` 与 Kubernetes API 负责把 selected build task 展开成 TaskRun/Pod。
控制面慢会让 TaskRun 创建或状态更新延迟;退化信号是 `plan-artifacts` 已完成但 build TaskRun 创建时间分散。
- Kubernetes scheduler 与 G14 node 决定 Pod 是否能同时落到节点。
CPU、内存、ephemeral storage 和 image pull 会限制实际并行度;退化信号是 Pod `Pending``Unschedulable``OOMKilled``Evicted` 或 node pressure event 增多。
- shared workspace PVC 与本地磁盘承载 source 读取、service workdir 复制、report 写入和 BuildKit 层数据。
退化信号是 build step 开始慢、`cp`/`tar`/workspace 操作耗时异常、Pod I/O wait 高或 PVC/local-path event。
- 每个 TaskRun 的 BuildKit sidecar 独立运行,但同时消耗 CPU、内存、overlayfs、socket readiness 和 layer cache I/O。
退化信号是 `buildkitd` 启动慢、socket unavailable、build context upload 慢、sidecar OOM 或 build step 等待 daemon。
- `hwlab-ci` 本地 registry 是全并行 rebuild 后半段的共享写点,承载所有 affected service 的 layer 和 manifest push。
退化信号是 push 耗时拉长、连接 reset、5xx、blob upload timeout 或 registry Pod CPU/I/O 压力。
- `devops-infra` git mirror/relay 影响 `prepare-source`、catalog fetch 和 `gitops-promote` 的固定开销。
它通常不在 build fan-out 中;退化信号是 clone/catalog 超过预算、promotion push 慢或 mirror pending/outbox 堆积。
并发回归的高风险修改必须提前识别。
`build-*` task 之间新增 `runAfter` 会把关键路径改成服务耗时求和。
把所有 build 写到同一个 report 或共享 workdir 会产生覆盖和竞态。
直接依赖 `tasks.build-*.results` 会让 skipped task 的结果解析变脆。
在 build task 内修改 `/workspace/source/repo` 会污染其他并发 task 的输入。
对不同 service 复用同一 image repo/tag 会造成 registry tag 覆盖。
把容量抖动误判为拓扑问题会导致重新串行化。
正确做法是保持 source tree 只读、每个 service 独立 workdir 和 report、每个 service 独立 image repo。
先按容量节点定位真实瓶颈,再决定是否增加资源或修 sidecar/registry/mirror。
planner 必须按 service component model 裁剪 build。`tools/` 下的短连接 CLI 源码不是 runtime service 输入;`skills/` 只有 agent runtime 或 skills bundle 真正消费的子目录才影响对应 runtimedevice-pod host CLI asset 属于 skills bundle 或 host 侧分发输入,不得让 cloud-api、agent-worker、gateway、edge-proxy 等服务重建。CI 读取 artifact catalog 时支持 repo 相对路径和绝对路径,便于用真实 catalog 做本地热探测;catalog 缺失才允许 fail closed 到 rebuild,不得把“诊断命令没读到 catalog”误判为生产路径必须全量构建。
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 收敛。
@@ -229,6 +261,83 @@ done
| 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 总耗时直接得出“并发失败”结论。
必须同时看 `plan-artifacts` 完成时间、每个 build TaskRun 创建时间、Pod startTime、container finishTime 和 build/push 日志。
检查 live Pipeline DAG,确认所有 build task 没有互相依赖:
```bash
bun scripts/cli.ts ssh G14:k3s script -- 'set -eu
ns=hwlab-ci
pipeline=hwlab-v02-ci-image-publish
kubectl get pipeline -n "$ns" "$pipeline" \
-o jsonpath="{range .spec.tasks[*]}{.name}{\"\\t\"}{.runAfter}{\"\\n\"}{end}" | \
grep "^build-"
'
```
检查一次 PipelineRun 的真实并发时间线:
```bash
bun scripts/cli.ts ssh G14:k3s script -- 'set -eu
ns=hwlab-ci
pr=<pipeline-run-name>
kubectl get taskrun -n "$ns" -l tekton.dev/pipelineRun="$pr" \
-o custom-columns=START:.status.startTime,DONE:.status.completionTime,\
STATUS:.status.conditions[0].status,REASON:.status.conditions[0].reason,\
TASK:.metadata.labels.tekton\\.dev/pipelineTask,NAME:.metadata.name \
--no-headers | \
grep -E "build-|plan-artifacts" | sort
'
```
检查调度和节点压力:
```bash
bun scripts/cli.ts ssh G14:k3s script -- 'set -eu
ns=hwlab-ci
pr=<pipeline-run-name>
kubectl get pod -n "$ns" -l tekton.dev/pipelineRun="$pr" -o wide
kubectl get events -n "$ns" --sort-by=.lastTimestamp | tail -80
kubectl describe node | grep -E "Name:|Pressure|Allocatable|Allocated resources|cpu|memory|ephemeral-storage" || true
'
```
检查 BuildKit 和 registry 共享写点。
先用 TaskRun 找到对应 Pod,再分别看 build step、BuildKit sidecar 和 registry Pod 日志。
如果 build step 卡在 push 或 sidecar 等待,优先处理 registry/BuildKit/PVC,而不是修改 Pipeline 并发拓扑。
```bash
bun scripts/cli.ts ssh G14:k3s script -- 'set -eu
ns=hwlab-ci
pr=<pipeline-run-name>
task=<build-task-name>
tr=$(kubectl get taskrun -n "$ns" \
-l tekton.dev/pipelineRun="$pr",tekton.dev/pipelineTask="$task" \
-o jsonpath="{.items[0].metadata.name}")
pod=$(kubectl get pod -n "$ns" -l tekton.dev/taskRun="$tr" \
-o jsonpath="{.items[0].metadata.name}")
kubectl logs -n "$ns" "$pod" --all-containers=true | \
grep -E "buildkit|daemon|socket|push|manifest|blob|timeout|reset|no space|OOM|killed" || true
kubectl get pod -n "$ns" -o name | grep -E "registry|hwlab-registry" || true
'
```
并发相关故障按下表归类,避免把不同问题混成“并行不稳定”:
| 故障类型 | 判定信号 | 修复方向 |
| --- | --- | --- |
| 拓扑退化 | build TaskRun 的 `runAfter` 出现其他 build taskstartTime 严格一个接一个且没有 Pod Pending 证据。 | 修 render 和 live Pipeline,恢复 build task 只依赖 `plan-artifacts`。 |
| 控制面或调度排队 | `plan-artifacts` 完成后 TaskRun/Pod 创建分散,event 出现调度等待。 | 查 Tekton controller、scheduler、API latency 和 node 可用资源。 |
| 节点资源压力 | Pod `Pending``OOMKilled``Evicted`、ephemeral storage 不足或 node pressure。 | 增加/释放资源、调整单 task resource request,不能靠串行化掩盖。 |
| PVC 或本地磁盘瓶颈 | build step 在复制 source、上传 context、写 layer 或写 report 时集体变慢。 | 减少共享写、确认 source tree 只读、必要时优化 service workdir 和 BuildKit 存储。 |
| BuildKit sidecar 竞态 | step 日志出现 daemon/socket not ready、sidecar OOM 或 buildkitd 异常退出。 | 修 sidecar readiness、资源和日志;不要把问题转成 build task 互相依赖。 |
| registry 写瓶颈 | 多个 build 同时 push 时出现 5xx、reset、blob timeout 或 registry Pod 压力。 | 查 registry Pod、存储和网络;必要时提升 registry 资源或存储能力。 |
| report fan-in 异常 | `collect-artifacts` 找不到某个 service report,或多个 service 报告内容互相覆盖。 | 确认 report 文件名按 serviceId 隔离,失败 task 能输出明确失败报告。 |
| skipped task 误判 | selected service 正确跳过,但 collect 误读为失败或缺 digest。 | 保持 collect 读 catalog+report 目录,不恢复 `tasks.build-*.results` 硬依赖。 |
| 下游 promotion 慢 | build 全部完成后才慢,日志集中在 mirror push、Argo refresh 或 runtime-ready。 | 按 mirror/GitOps/runtime 排障;这不是 build 并发问题。 |
性能退化排障结束后,只把可复用的预算、原理和入口更新到本文;一次性 PipelineRun 名称、Pod 名称、日志全文和临时证据放到 issue 或 PR,不写入长期规格。
## Env 容器复用与三变量启动