Prow 生态系统架构全景:test-infra、prow-configs、prow-images、cimaster 四大项目关系深度解析

Prow 生态系统架构全景

本文深入解析 eBay Tess CI/CD 系统的四个核心项目:test-infraprow-configsprow-imagescimaster,通过架构图和流程图展示它们之间的依赖关系与协作方式。


一、四大项目概览

项目 仓库 定位 核心产物
test-infra tess/test-infra Prow 框架源码(fork 自 kubernetes/test-infra) Prow 组件二进制:hook、plank、deck、manual-trigger 等
prow-configs tessops/prow-configs Prow 运行时配置 + Job 定义 config.yamlplugins.yaml、所有 ProwJob YAML
prow-images tess-contrib/prow-images CI 任务用的工具镜像集合 kanikoe2egolangtess-build 等镜像
cimaster tess-contrib/cimaster E2E 测试集群资源管理器 cimaster HTTP 服务,管理测试集群的分配与回收

二、项目关系总图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ eBay Tess CI/CD 生态系统 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │ test-infra(Prow 框架) │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │ │
│ │ │ hook │ │ plank │ │ deck │ │ tide │ │ manual-trigger │ │ │
│ │ │(webhook) │ │(调度器) │ │(Web UI) │ │(自动合并)│ │(手动触发API) │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────────────┘ │
│ ▲ 读取配置 ▲ 镜像被 ProwJob 使用 │
│ │ │ │
│ ┌────────┴──────────┐ ┌──────────┴──────────┐ │
│ │ prow-configs │ │ prow-images │ │
│ │ │ │ │ │
│ │ • config.yaml │ │ • kaniko │ │
│ │ • plugins.yaml │ │ • e2e │ │
│ │ • Job YAML 定义 │ │ • golang │ │
│ │ (presubmit/ │ │ • tess-build │ │
│ │ postsubmit/ │ │ • create-release │ │
│ │ periodic) │ │ • auto-validation │ │
│ │ │ │ • ci-generator │ │
│ └───────────────────┘ └──────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────────────────────┐ │
│ │ cimaster │ │
│ │ │ │
│ │ 集群池 ConfigMap ←→ ClusterManager ←→ manual-trigger API │ │
│ │ (K8s namespace:ci) (分配/回收/创建) (触发集群创建 ProwJob) │ │
│ └───────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────────┘

三、静态依赖关系图

graph TB
    subgraph test-infra["test-infra(Prow 框架源码)"]
        hook["hook
处理 GitHub 事件"] plank["plank
ProwJob 调度器"] deck["deck
Web UI"] manual["manual-trigger
手动触发 HTTP API"] clonerefs["pod-utils
clonerefs/sidecar 等"] end subgraph prow-configs["prow-configs(运行时配置)"] config["config.yaml
全局 Prow 配置"] plugins["plugins.yaml
插件配置"] jobs["jobs/**/*.yaml
所有 Job 定义"] presets["config.presets.yaml
通用 Preset"] end subgraph prow-images["prow-images(工具镜像)"] kaniko["kaniko
构建/推送镜像"] e2e["e2e
E2E 测试框架"] golang["golang
Go 编译环境"] tessbuild["tess-build
Tess 构建工具"] release["create-release
自动打 Tag/发布"] validator["prow-config-validator
配置校验"] cigen["ci-generator
Job 自动生成"] end subgraph cimaster["cimaster(集群资源管理)"] api["HTTP API
:8080"] mgr["ClusterManager
分配/回收/持有"] configmap["K8s ConfigMap
集群状态池"] end %% prow-configs 被 test-infra 读取 config -->|"ConfigAgent 加载"| hook config -->|"ConfigAgent 加载"| plank config -->|"ConfigAgent 加载"| deck config -->|"ConfigAgent 加载"| manual plugins -->|"PluginAgent 加载"| hook jobs -->|"Job 定义"| plank %% prow-images 被 Job 使用 kaniko -.->|"ProwJob spec.containers.image"| jobs e2e -.->|"ProwJob spec.containers.image"| jobs tessbuild -.->|"ProwJob spec.containers.image"| jobs release -.->|"ProwJob spec.containers.image"| jobs %% cimaster 使用 manual-trigger 创建集群 api -->|"POST /manual-trigger"| manual mgr --> api configmap --> mgr %% e2e 镜像与 cimaster 交互 e2e -->|"GET /getvacant 申请集群"| api e2e -->|"GET /finishtest 释放集群"| api %% prow-configs validator 使用 test-infra 逻辑 validator -.->|"引用 prow/config 包"| test-infra style test-infra fill:#dbeafe,stroke:#3b82f6 style prow-configs fill:#dcfce7,stroke:#22c55e style prow-images fill:#fef9c3,stroke:#eab308 style cimaster fill:#fce7f3,stroke:#ec4899

四、端到端流程:一次 E2E 测试的完整生命周期

4.1 流程总图

sequenceDiagram
    participant Dev as 开发者
    participant GH as GitHub
    participant Hook as hook
(test-infra) participant Plank as plank
(test-infra) participant Pod as E2E Pod
(prow-images/e2e) participant CI as cimaster participant CM as K8s ConfigMap
(集群池) participant Manual as manual-trigger
(test-infra) Dev->>GH: 提交 PR GH->>Hook: GitHub Webhook
(pull_request event) Hook->>Hook: 查找 prow-configs/jobs 中的 presubmit jobs Hook->>Plank: 创建 ProwJob CRD
(e2e-test) Plank->>Pod: 启动 Pod
image: hub.tess.io/prowimages/e2e:latest Note over Pod: InitContainers 运行
clonerefs 克隆代码 Pod->>CI: GET /getvacant?build=123&job=e2e-test CI->>CM: 查询空闲集群 CM-->>CI: 返回 cluster-01 CI->>CM: 标记 cluster-01 为 testing CI-->>Pod: 返回 "cluster-01" Note over Pod: 在 cluster-01 上运行 E2E 测试 Pod->>CI: GET /finishtest?cluster=cluster-01 CI->>CM: 标记 cluster-01 为 finished Pod-->>Plank: 任务完成 (exit 0) Plank->>GH: 上报 CI 结果 ✅ GH-->>Dev: PR Check 通过

4.2 手动触发 + 集群创建流程

sequenceDiagram
    participant User as 用户/运维
    participant CI as cimaster
    participant Manual as manual-trigger
(test-infra) participant Plank as plank
(test-infra) participant Pod as 集群创建 Pod
(prow-images/tess-build) participant CM as K8s ConfigMap User->>CI: GET /createcluster?user=john&branch=master CI->>Manual: POST /manual-trigger
{"org":"tess","repo":"tessops","prowjob":"sddz-e2e-k8s-1.32","user":"john"} Manual->>Manual: 在 prow-configs 中查找
"sddz-e2e-k8s-1.32" 任务定义 Manual->>Plank: 创建 ProwJob CRD Plank->>Pod: 启动集群创建 Pod
image: hub.tess.io/prowimages/tess-build:latest Note over Pod: 执行集群创建脚本
创建新的 Tess 集群 Pod-->>Plank: 完成 (exit 0) User->>CI: GET /addcluster?cluster=new-cluster®ion=us-west&name=admin CI->>CM: 将新集群加入集群池 CM-->>CI: 写入成功 CI-->>User: "cluster new-cluster is added successfully"

五、各项目内部结构详解

5.1 test-infra 项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
test-infra/
├── prow/
│ ├── cmd/ ← Prow 组件入口
│ │ ├── hook/ ← GitHub webhook 处理器
│ │ ├── plank/ ← ProwJob 调度器
│ │ ├── deck/ ← Web UI 服务
│ │ ├── tide/ ← 自动合并服务
│ │ ├── crier/ ← 结果上报服务
│ │ └── manual-trigger/ ← 手动触发 HTTP API ⭐
│ ├── config/ ← Prow 配置解析库
│ │ └── jobs.go ← JobBase/Presubmit/Postsubmit 定义
│ ├── apis/prowjobs/v1/ ← ProwJob CRD 类型定义
│ │ └── types.go ← ProwJob/ProwJobSpec/Refs 等
│ ├── pjutil/ ← ProwJob 工具库
│ │ └── pjutil.go ← PresubmitSpec/specFromJobBase
│ └── pod-utils/
│ ├── decorate/ ← Decoration 机制(注入 clonerefs 等)
│ ├── clone/ ← 代码克隆逻辑
│ └── downwardapi/ ← 环境变量注入
└── config/jobs/ ← 上游 k8s 项目的 Job 定义

核心职责: 提供 Prow 框架的所有运行时二进制Go 库

5.2 prow-configs 项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
prow-configs/
├── prow-configs/
│ ├── config.yaml ← Prow 全局配置(plank/tide/deck 行为)
│ ├── config.presets.yaml ← 通用 Preset(preset-builder/preset-kaniko 等)
│ └── plugins.yaml ← Hook 插件配置(trigger/lgtm/approve 等)
├── jobs/
│ ├── ebaytess/ ← ebaytess org 下各仓库的 Job
│ │ ├── tess-ovn/
│ │ ├── apiserver/
│ │ └── controllers/
│ ├── tessops/ ← tessops org 下各仓库的 Job
│ │ ├── test-infra/
│ │ └── prow-configs/
│ ├── tess-contrib/
│ │ ├── cimaster/ ← cimaster 自身的 CI Job
│ │ └── prow-images/
│ └── CloudSRE/
├── hack/
│ └── gen-jobs.sh ← Job 自动生成脚本
└── docs/
└── add-job.md ← 添加 Job 的文档

核心职责: 定义什么任务在什么时机运行(Job 配置)以及 Prow 如何行为(全局配置)。

5.3 prow-images 项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
prow-images/
├── e2e/ ← E2E 测试框架镜像 ⭐
│ ├── Dockerfile ← 基于 golang,含 tessci 工具
│ ├── entrypoint/main.go ← 申请集群 → 跑测试 → 释放集群
│ ├── e2e.sh ← E2E 测试脚本
│ └── tools/tessci/ ← 与 cimaster 交互的 CLI 工具
├── golang/ ← Go 编译环境镜像(多版本)
│ ├── Dockerfile
│ ├── 1.21.argfile
│ └── 1.24.argfile
├── kaniko/ ← 镜像构建/推送工具
├── tess-build/ ← Tess 构建工具(含 git-crypt)
│ ├── Dockerfile
│ └── entrypoint/ ← 构建脚本封装
├── create-release/ ← 自动创建 Git Tag/Release
├── auto-validation/ ← 自动化验证
├── prow-config-validator/ ← 校验 prow-configs 配置合法性
├── ci-generator/ ← 从 manifest 自动生成 Job YAML
└── clone-and-do/ ← 通用克隆+执行工具(其他镜像的基础)

核心职责: 提供 ProwJob Pod 中运行的工具镜像,每个镜像对应一种 CI 能力。

5.4 cimaster 项目结构

1
2
3
4
5
6
7
8
9
10
11
12
cimaster/
├── cmd/cimaster/main.go ← 服务入口,注册 HTTP 路由
├── cluster/
│ ├── cluster-manager.go ← 核心逻辑:分配/持有/释放/创建集群
│ ├── cluster-ops.go ← 单个集群操作(状态变更)
│ └── botadmin.go ← 管理员用户鉴权
├── pkg/types/types.go ← Cluster 数据结构定义
├── api-definition/
│ └── cimaster-clustermanager.yaml ← API 文档
└── spec/
├── cimaster.yaml ← K8s Deployment 部署清单
└── cimaster-service.yaml ← K8s Service 清单

核心职责: 维护一个共享 E2E 测试集群资源池,通过 HTTP API 提供集群的申请、释放、持有、创建能力。


六、配置流向图

prow-configs 如何影响各个 Prow 组件

graph LR
    subgraph prow-configs
        C[config.yaml]
        P[plugins.yaml]
        J[jobs/**/*.yaml]
        PR[config.presets.yaml]
    end

    subgraph test-infra 运行时
        Hook["hook
(处理 Webhook)"] Plank["plank
(调度 Job)"] Deck["deck
(展示 UI)"] Tide["tide
(合并 PR)"] MT["manual-trigger
(手动触发)"] end C -->|"plank/tide/deck 行为配置"| Plank C -->|"tide 合并策略"| Tide C -->|"deck 展示配置"| Deck C -->|"job 查询"| MT P -->|"trigger/lgtm/approve 插件"| Hook J -->|"presubmit/postsubmit 定义"| Hook J -->|"PowJob spec.PodSpec 来源"| Plank PR -->|"Preset env/volumes 注入"| Plank style prow-configs fill:#dcfce7 style test-infra 运行时 fill:#dbeafe

七、镜像引用关系图

prow-images 中各镜像的依赖层级

graph BT
    Base["hub.tess.io/tess/ubuntu-22.04:hardened
(基础系统镜像)"] CloneAndDo["clone-and-do
通用克隆+执行"] Golang["golang:1.21~1.24
Go 编译环境"] TessBuild["tess-build
含 git-crypt"] E2E["e2e
含 tessci + e2e.sh"] Kaniko["kaniko
镜像构建工具"] Release["create-release
Git Release 工具"] Validator["prow-config-validator
配置校验"] CIGen["ci-generator
Job 生成器"] Base --> CloneAndDo CloneAndDo --> Golang Golang --> TessBuild Golang --> E2E Golang --> Kaniko Golang --> Release Golang --> Validator Golang --> CIGen style Base fill:#f3f4f6 style CloneAndDo fill:#fef9c3 style Golang fill:#fef9c3 style TessBuild fill:#fef3c7 style E2E fill:#fde68a style Kaniko fill:#fde68a style Release fill:#fde68a

八、cimaster 集群状态机

stateDiagram-v2
    [*] --> finished: addcluster (管理员添加)

    finished --> testing: getvacant (测试任务申请)

    testing --> finished: finishtest (测试完成)
    testing --> held: holdcluster (暂时持有)

    held --> finished: releasecluster (释放持有)
    held --> finished: 自动过期 (6小时后)

    finished --> disabled: disablecluster (管理员禁用)
    disabled --> finished: enablecluster (管理员启用)

    finished --> [*]: deletecluster (管理员删除)

九、完整 CI 任务数据流

从代码提交到 CI 结果的完整数据链路:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
┌──────────────────────────────────────────────────────────────────────────────┐
│ 完整 CI 数据流 │
└──────────────────────────────────────────────────────────────────────────────┘

1. 【代码变更】
开发者提交 PR


2. 【事件接收】test-infra/hook
GitHub Webhook → hook 服务
hook 读取 prow-configs/plugins.yaml
识别需要触发的 Job(trigger 插件)


3. 【Job 查找】test-infra/hook
读取 prow-configs/jobs/**/*.yaml
找到匹配的 presubmit Job 定义
Job 定义中包含:
spec.containers[].image → prow-images 中的镜像
spec.containers[].command → 执行的命令


4. 【ProwJob 创建】test-infra/hook → Kubernetes API
创建 ProwJob CRD
spec.PodSpec 直接复制自 Job 配置


5. 【Pod 调度】test-infra/plank
监听 ProwJob CRD
读取 prow-configs/config.yaml(namespace、超时等)
应用 prow-configs/config.presets.yaml(preset-builder 等注入 env/volume)
执行 Decoration(注入 clonerefs/initupload/sidecar)
创建 Kubernetes Pod


6. 【Pod 执行】prow-images/e2e 容器
InitContainer: clonerefs 克隆代码
InitContainer: initupload 初始化 GCS 上传
Main Container: /entrypoint 包装用户脚本:
┌─────────────────────────────────────────┐
│ e2e/entrypoint: │
│ 1. GET cimaster/getvacant → 申请集群 │
│ 2. 运行 e2e.sh(测试脚本) │
│ 3. GET cimaster/finishtest → 释放集群 │
└─────────────────────────────────────────┘
Sidecar: 上传日志到 GCS


7. 【结果上报】test-infra/crier
读取 ProwJob 状态
上报 CI Check 结果到 GitHub PR

8. 【结果展示】test-infra/deck
读取 ProwJob/GCS 日志
在 https://prow.tess.io 展示

十、项目协作矩阵

动作 test-infra prow-configs prow-images cimaster
定义 Prow 框架组件 ✅ 实现 - - -
定义 Job 触发规则 - ✅ 定义 - -
提供 Job 运行镜像 - 引用镜像 URL ✅ 构建 -
管理 E2E 测试集群 - - 调用 API ✅ 实现
触发集群创建 Job 提供 API 定义 Job 执行构建 调用 API
校验 prow-configs 提供 Go 库 ✅ 被校验 校验工具镜像 -
自动生成 Job YAML - ✅ 存储 生成器镜像 -

十一、关键接口汇总

test-infra ↔ prow-configs

  • 接口: 文件系统 / Kubernetes ConfigMap
  • 方向: prow-configs → test-infra
  • 内容: config.yaml(ConfigAgent)、plugins.yaml(PluginAgent)、Job YAML(PresubmitsStatic/PostsubmitsStatic)

test-infra ↔ prow-images

  • 接口: Docker 镜像引用(字符串)
  • 方向: prow-images → ProwJob spec → plank
  • 内容: hub.tess.io/prowimages/<name>:latest

cimaster ↔ test-infra (manual-trigger)

  • 接口: HTTP REST API
  • 方向: cimaster → manual-trigger
  • 内容:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    POST https://prow.tess.io/manual-trigger
    {
    "org": "tess",
    "repo": "tessops",
    "base_ref": "master",
    "prowtype": "postsubmit",
    "prowjob": "sddz-e2e-k8s-1.32",
    "user": "john"
    }

prow-images/e2e ↔ cimaster

  • 接口: HTTP REST API
  • 方向: e2e Pod → cimaster
  • 内容:
    1
    2
    GET http://cimaster.tess.io/getvacant?build=123&job=e2e-test
    GET http://cimaster.tess.io/finishtest?cluster=cluster-01

cimaster ↔ Kubernetes ConfigMap

  • 接口: Kubernetes API
  • 方向: 双向读写
  • 内容: ci/clusters ConfigMap,存储集群池状态 JSON

十二、总结

这四个项目构成了一个完整的 CI/CD 闭环:

1
2
3
4
5
6
7
prow-configs ──定义Job──→ test-infra ──调度──→ Pod (prow-images镜像)
│ │ │
│ │ 申请/释放集群
│ 手动触发 │
│ ↓ ↓
校验工具 ←──────────── prow-images cimaster ←→ K8s ConfigMap
集群池管理
  • test-infra: 系统的大脑——框架、调度、编排
  • prow-configs: 系统的配置中枢——Job 定义、行为规则
  • prow-images: 系统的工具箱——各种 CI 能力封装为镜像
  • cimaster: 系统的资源管家——E2E 集群资源的统一调度

作者: Tashen
日期: 2026-04-17
标签: #Kubernetes #Prow #CI/CD #DevOps #架构