0%

DevOps 工具链之 Prow

前言

如果你正在大规模进行 CI/CD,却没有使用 Kubernetes 原生 CD,你可能错过了不少东西。Prow——正如这个希腊语的含义“船头”——一直是使 Kubernetes 成为大规模执行 CI/CD 的优秀平台的强大助力。多年来,它也始终处在原生 Kubernetes CD 的最前沿。

如果你经常混迹于 Kubernetes 上游社区,你一定知道 k8s-ci-bot, 它能帮助管理上游的 PR & Issue,几乎无处不在。今天,我们就来探究一下它背后的项目 Prow。

更新历史

2020 年 10 月 22 日 - 初稿

扩展阅读


关于 Prow

在 Kubernetes、Istio 等知名项目的 Github 仓库中,我们经常会看到 xxx-bot 用户,给 issues 添加标签、合并 PR 。这个机器人账户就是被 Prow 驱动的。

Prow 是 Kubernetes 测试特别兴趣小组的项目,目前是 kubernetes/test-infra 的一部分。Prow 是一个基于 Kubernetes 使用各类事件驱动执行 Job 的 CI/CD 系统。

除了执行 Job ,Prow 还能通过以下方式,实现 GitHub 的自动化功能:

  • 策略配置,权限控制等
  • /label 形式的 chat-ops 命令
  • 自动合并 PR

使用 Prow ,我们可以将研发流程自动化,极大地提升了开发体验。

工作原理

Prow 采用的是微服务架构。核心组件如下:

  • hook 是核心无状态服务,负责监听 Github Webhook 并将其分发到指定的插件
  • plank 是控制器,负责管理作业的生命周期
  • deck 是系统的 Dashboard
  • horologium 用来创建周期型的 Job
  • sinker 定时清理无用的 Job

工作流程:

在 issues 中,评论 /assign @someone 。Github 通过 Webhook 将该事件发送给 Prow 。事件到达 hook 组件,再传给各个 PlugIn 。 PlugIn 通过解析事件的 body 数据,判断是否需要创建 ProwJob 。Prowjob 是一个 Job 的 CRD 。最终执行 Job ,将相关的内容指派给 someone ,将文本转换为行为。

关于插件:

prow/plugins 仓库中,我们可以找到一些内置的插件。当然,我们也可以通过扩展插件定制 Prow 的行为。

在 Kubernetes 集群部署 Prow

  • 准备机器人账户

在生产环境,通常会使用一个类似 xxx-bot 的账户专用于 Prow 的行为,以区分人的操作。如果仅是测试,使用个人账户也可以。

将机器人账户添加为仓库管理员。

  • 生成用于 Github 访问的 token

登陆机器人账户,在 settings/tokens 页面,新建一个 token: xxxTokenxxx ,勾选 repo:status 和 public_repo 权限。

  • 使用 Github token 创建集群 secret
1
2
echo "xxxTokenxxx" > oauth-token
kubectl create secret generic oauth-token --from-file=oauth=./oauth-token
  • 在集群生成 hmac ,用于 Github 的 Webhook 认证
1
2
openssl rand -hex 20 > hmac-token
kubectl create secret generic hmac-token --from-file=hmac=./hmac-token

查看 hmac 值,将用于 Github 中 Webhook 的配置。

1
2
3
cat ./hmac-token

xxxHmacxxx
  • 部署 Prow
1
kubectl apply -f https://raw.githubusercontent.com/kubernetes/test-infra/master/prow/cluster/starter.yaml
  • 查看全部 Pod 是否全部 Running
1
kubectl get pod
  • 查看服务访问的端口
1
2
3
4
5
6
7
kubectl get svc

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
deck NodePort 10.233.52.176 <none> 80:32284/TCP 16m
hook NodePort 10.233.30.53 <none> 8888:30381/TCP 16m
kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 4h31m
tide NodePort 10.233.26.103 <none> 80:30855/TCP 16m

这里由于仅用于测试,没有配置 Ingress ,下面会以 ServiceIp + NodePort 的形式进行配置,其中 ServiceIp 为部署的主机 IP 。

  • 查看页面

访问 deck 组件提供的 Dashboard :http://ServiceIP:32284/

新仓库配置

  • 给 Github 仓库添加 Webhook 配置

Payload URL 需要带上 /hook 路由。Content Type 需要选择 application/json 。Secret 是上面生成的 xxxHmacxxx 值。

  • 给 Github 仓库添加 OWNERS 文件

OWNERS 文件用于申明模块的 approvers 和 reviewers ,在 PR 流程中会用到。每个目录都可以使用 OWNERS 进行控制,这里在仓库根目录下添加该文件并提交。其中的 someone 用户,将可以通过评论 /lgtm ,合并 PR 。这里 Prow 中定义的规则是,同时存在 /lgtm 和 /approve 标签时,PR 将会被合并。但是存在一个特例,approver 可以省略 /approve 而直接使用 /lgtm 合并 PR。

OWNERS 文件:

1
2
3
4
5
approvers:
- someone

reviewers:
- someone
  • 启用指定插件

创建插件描述文件 plugins.yaml ,这里以 xuecanlong/prow-test 仓库为例。如果是多个仓库,可以按照 yaml 语法,列在 plugins 下。

plugins.yaml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
plugins:
xuecanlong/prow-test:
- size
- lgtm
- approve
- label
- trigger
- hold
- verify-owners
- wip
- milestone
- welcome
- heart
- help
- assign

执行命令:

1
2
3
kubectl create configmap plugins \
--from-file=plugins.yaml=./plugins.yaml --dry-run -o yaml \
| kubectl replace configmap plugins -f -
  • 配置 Tide

Tide 用于 PR 的合并,多个仓库可以按照 yaml 语法新增在 repos 字段下。

config.yaml

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
tide:
merge_method:
kubeflow/community: squash

target_url: http://ServiceIp:30855/tide
queries:
- repos:
- xuecanlong/prow-test
labels:
- lgtm
- approved
missingLabels:
- do-not-merge
- do-not-merge/hold
- do-not-merge/work-in-progress
- needs-ok-to-test
- needs-rebase

context_options:
from-branch-protection: true
skip-unknown-contexts: true
orgs:
org:
required-contexts:
- "check-required-for-all-repos"
repos:
repo:
required-contexts:
- "check-required-for-all-branches"
branches:
branch:
from-branch-protection: false
required-contexts:
- "required_test"
optional-contexts:
- "optional_test"

执行命令:

1
kubectl create configmap config --from-file=config.yaml=./config.yaml --dry-run -o yaml | kubectl replace configmap config -f -
  • 定制标签(可选)

通过 /xxx xxx 评论,能够给 issues 或 PR 添加标签。前提是仓库中已经新建了相关的二维标签。 如果需要定制标签,可以参考 内置标签 定义自己的 labels.yaml 。

执行命令:

1
2
3
kubectl create configmap label-config \
--from-file=labels.yaml=labels.yaml --dry-run -o yaml \
| kubectl replace configmap config -f -
  • bazel 和 add-hook 工具

克隆 Prow 的代码仓库 kubernetes/test-infra/prow ,使用 bazel 可以检测配置是否正确

1
bazel run prow/cmd/checkconfig -- --plugin-config=path/to/plugins.yaml --config-path=path/to/config.yaml

kubernetes/test-infra/experiment 中提供了一个 add-hook 工具,可以免去在 Github 页面配置 Webhook 。

1
add-hook  --hmac-path=h-mac --github-token-path=oauth -hook-url http://ServiceIp:30381/hook -repo xuecanlong/prow-test -confirm=true