状态:草案(2026-10-17),仓库文档 + 文件实测。 基于 KubeVirt
v1.9.0(提交79d34c17)的CONTRIBUTING.md,docs/reviewer-guide.md,docs/getting-started.md、OWNERS 文件和 PR 模板。未运行测试与构建。
KubeVirt 源码阅读 8:贡献入门
目录
1. 直觉:人的判断与机器人的标签
KubeVirt 的 PR 必须经过两人的判断才能合并。 reviewer 认为“代码很好”(/lgtm), approver 认为“可以引入本仓库”
(/approve)。谁是 reviewer 和 approver 由 PR 所触及文件夹的 OWNERS 文件决定,而表态则是通过 PR 评论中的斜杠命令来进行的。将表态转换为标签、运行测试通道、并在条件全部满足时进行合并的,是一个名为 prow 的机器人集合。由于采用与 Kubernetes 相同的方式,因此在一边学会后另一边也能使用。
2. 图表
3. 通过 OWNERS 重新审视地图
v1.9.0 中有 141个 OWNERS 文件(实测)。根目录下的 OWNERS 将所有文件的默认 reviewer 和 approver 指定为别名 code-reviewers·approvers ,而构建文件(BUILD.bazel, Makefile 等)则单独交由 sig-buildsystem 处理。各个文件夹的 OWNERS 则会进一步收窄范围。例如第 3 篇中的
pkg/virt-controller/watch/vm/OWNERS 如下所示。
reviewers:
- sig-compute-reviewers
approvers:
- sig-compute-approvers
labels:
- area/controller
- sig/compute
来源:kubevirt/kubevirt v1.9.0 pkg/virt-controller/watch/vm/OWNERS(不含注释行,Apache-2.0)。触及该文件夹的 PR 会带有 prow 的
sig/compute·area/controller 标签,并从 sig-compute 中挑选评审者。别名的真实姓名位于 OWNERS_ALIASES 中。
清点人数结果如下(v1.9.0,实测)。
| 别名 | 人数 | 别名 | 人数 | |
|---|---|---|---|---|
| approvers(全体) | 24 | code-reviewers | 11 | |
| sig-compute-approvers | 8 | sig-compute-reviewers | 7 | |
| sig-storage-approvers | 4 | sig-storage-reviewers | 6 | |
| sig-network-approvers | 3 | sig-network-reviewers | 4 | |
| sig-buildsystem-approvers | 3 | sig-control-plane-reviewers | 7 |
这张表格正是 代码地图的另一面。第 4、5 篇的网络代码(pkg/network, converter/network)由 sig-network 负责,第 6 篇的存储端(gpkg/storage)由 sig-storage 负责,其余大部分则由 sig-compute 负责。如果想快点收到评审,最好让 PR 局限在某个 SIG 的文件夹内。如果触及多个 SIG,则需要多个 approver。
4. 命令与标签
| 命令 | 人员 | 效果 |
|---|---|---|
/ok-to-test |
组织成员 | 解除附加在首个贡献者 PR 上的 needs-ok-to-test 以允许运行测试通道(CONTRIBUTING.md 第 67 行) |
/test <레인> · /retest |
成员 · 作者 | 重新运行单个通道 / 重新运行失败的通道 |
/lgtm |
reviewer | lgtm 标签。提交新 commit 时通常会移除 |
/approve |
该文件夹的 approver | approved 标签。触及的每个 OWNERS 领域都需要 |
/hold · /unhold |
任何人 | 暂缓合并 |
/cc @이름 · /assign |
任何人 | 呼叫人员 |
合并并非由人点击按钮,而是由 tide 来完成。当两个标签和测试通过均已具备且没有阻止合并的标签(do-not-merge/…, /hold)时,就会进入队列。草案(Draft)PR 不会运行 CI 也不分配评审者,因此如果想咨询方向,以草案形式打开是比较礼貌的做法。
PR 必须具备三项内容。
- 所有 commit 的
Signed-off-by:— DCO。通过git commit -s附加。如果没有,DCO 检查将会拦截。 - PR 模板的
release-note块 — 针对用户可见的变化写一行,或者NONE。发布说明会从此块生成。 - 测试 — 评审指南的底线是“新代码应有单元测试,新功能和 bug 修复应至少有一个 e2e 测试” (reviewer-guide.md:103 附近)。
提交信息需遵循 Kubernetes 规范(docs/commit-message-guidelines.md)。标题 50 字左右、祈使语气、无句号,正文在 72 字符处换行,
正文需说明做了什么以及 为什么,诸如 Fixes #123 这样的关键词应写在 PR 描述中而不是提交中。文档中有在前缀加上 net, vmi: 等区域前缀的示例。并且 v1.9.0 的 PR 模板检查清单中
包含一个询问是否遵守 KubeVirt AI 贡献政策的项目。如果是借助工具编写的 PR,请先阅读该政策。
5. 评审指南关注的内容
docs/reviewer-guide.md 虽短,但它反向解释了前面七篇中看到的设计背后的原因。你可以提前知道在接受评审时会被问到什么。
- 不要向节点组件添加 Informer(:43)。这就是第 4 篇中 virt-handler 通过节点标签过滤查看 VMI 的原因。相反,virt-api 中要求使用 GET 代替 Informer。因为 virt-api 是可以自由扩展的组件,如果引入缓存会导致对象传输激增。
- 未创建的对象用 PATCH,已创建的对象用 UPDATE。 这就是第 2 篇中的子资源使用 JSON patch 修改 VM 的原因。如果多个组件共享 status,则应使用收窄字段的 PATCH(第 3、4 篇的 VMI status)。
- 事件只在状态改变时触发一次。 每次 reconcile 都发送事件会拥堵 API Server。
- 遵循列表的顺序。 如果两个控制器以不同的顺序使用相同的条件列表,就会产生“更新风暴”,这就是 virt-controller 和 virt-handler 的 VMI 条件示例。
- 需要特权的节点操作应交给 virt-handler 而非 virt-launcher。 正如第 4、5 篇的分工一样。
- 考虑升级路径。 新的 virt-handler 必须能够与旧的 virt-launcher 通信(第 4 篇的 proto)。
- 编码风格遵循
goimports·shfmt,Go 语言中常见的失误会被 Bazel 的nogo分析器在构建时拦截。
6. 适合首次贡献的切入点
从本系列的蓝图来看,一开始选择 只修改单个文件及其测试的位置最好。
- 通过标签筛选。
good-first-issue·help-wanted·kind/bug标签(CONTRIBUTING.md第 49 行指南)。 - 文档与代码的不一致。 编写本系列时我们实际发现了一个。
docs/components.md将 Pod 内的 libvirt 守护进程解释为libvirtd,但 v1.9.0 启动的是virtqemud(第 1、5 篇)。文档 PR 的测试负担较小,并且在修改过程中能够仔细阅读代码。CDI 侧在文档中补充大小计算的 PR (#4318) 也属于此类(第 6 篇)。 - converter 的一个配置器。
pkg/virt-launcher/virtwrap/converter/compute/的文件对应一个设备,旁边就是_test.go(第 5 篇)。 这是一个无需伪集群、仅查看 VMI → 域结构体的单元测试,因此非常容易运行。 - Webhook 的验证与消息。
admitters/的函数具有明确的输入(Spec)和输出(StatusCause 列表)(第 2 篇)。优化错误消息的字段路径或措辞也是评审指南中所要求的“合理的错误消息”。 - 日志与事件。 如果学会了如何通过
pos日志查找代码(第 1 篇),你就可以在真实集群中发现同一行被打印得过于频繁的地方(例如第 7 篇中的设备检查日志)。在修改之前,最好先通过 Issue 询问。
7. 如何运行测试及所需工具
在编写本文时我没有运行测试,也没有下载以下工具。只记录必要的内容。
单元测试。 最稳妥的途径是仓库指定的构建器容器。
make test # Bazel 로 전체(빌더 컨테이너 안)
make go-test WHAT=./pkg/virt-controller/... # Bazel 없이 go test (역시 컨테이너 안)
需要 Docker 或 Podman、rsync,以及首次拉取的构建器镜像(quay.io/kubevirt/builder:<판>, hack/dockerized 第 19 行)。
如果想在容器外直接运行 go test ,则需要与 go.mod 的 go 1.26.0 匹配的 Go 版本,以及 virt-launcher 侧包通过 cgo 使用的 libvirt 开发头文件
(libvirt.org/go/libvirt)。由于需要顺着 import 才能知道容器外能够运行到哪个包,这次没有进行验证
(未验证)。刚开始时使用容器会更方便。
单元测试也是基于 Ginkgo 的,因此当只运行单个测试时,可以传入 -ginkgo.focus='문자열' 。
功能测试。 make cluster-up 这会通过 kubevirtci 创建一个将节点作为 VM 启动的集群, make cluster-sync 会上传我的构建产物,
make functest 运行 tests/ 。当只运行一部分时,使用 FUNC_TEST_ARGS='--focus-file=…' (docs/getting-started.md 第 221 行)。
需要的是 支持嵌套虚拟化的 Linux 机器(在 Mac 上很难实现)、充足的内存以及 kubevirtci 获取的节点镜像。
在 PR 中,Prow 会按 SIG 代为运行此测试,因此一开始你可以在本地运行到单元测试为止,功能测试则通过阅读 Prow 的运行结果来开始。
8. 局限性
- Prow lane 的名称和数量、tide 的具体合并条件在
kubevirt/project-infra仓库中,本次未打开查阅(未验证). - 别名人员为 v1.9.0 时文件的状态。在 main 分支中可能会有所不同。
- 构建和测试时间为 未测。
Titi 的寄语。 第一个 PR 越小越好。一个文件、一个测试、一个说明为什么修改的段落!而且评审意见不是攻击,而是在填补地图上的空白。只要说声谢谢然后逐个修改即可!
参考
全部访问于 2026-10-17。
CONTRIBUTING.md: https://github.com/kubevirt/kubevirt/blob/v1.9.0/CONTRIBUTING.md- 评审指南: https://github.com/kubevirt/kubevirt/blob/v1.9.0/docs/reviewer-guide.md
- 提交信息规范: https://github.com/kubevirt/kubevirt/blob/v1.9.0/docs/commit-message-guidelines.md
- PR 模板: https://github.com/kubevirt/kubevirt/blob/v1.9.0/.github/PULL_REQUEST_TEMPLATE.md
- Prow 命令列表: https://prow.ci.kubevirt.io/command-help
- KubeVirt AI 贡献政策: https://github.com/kubevirt/community/blob/main/ai-contribution-policy.md
- 开发指南(测试): https://github.com/kubevirt/kubevirt/blob/v1.9.0/docs/getting-started.md