使用 Kind 部署 Prow 手记

4 mins to read

Prow 是 Kubernetes 使用的云原生 CI/CD 系统(https://github.com/kubernetes/test-infra/tree/master/prow),用于管理 Kubernetes 的 Issue 和 PullRequest 以支持开源协同。Prow 通过 GitHub 事件触发 job,通过处理事件状态实现自动化的 ChatOps。

实验环境:

Linux VM-16-11-debian 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2+deb10u2 (2019-11-11) x86_64 GNU/Linux Docker Version 20.10.1

Install kubectl

# 下载 kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
# 下载 kubectl.sha256
curl -LO "https://dl.k8s.io/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"
# 校验
echo "$(<kubectl.sha256) kubectl" | sha256sum --check
# sudo 安装
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

或者用户安装

mkdir -p ~/.local/bin/kubectl
mv ./kubectl ~/.local/bin/kubectl
# and then add ~/.local/bin/kubectl to $PATH

参考文档 https://kubernetes.io/docs/tasks/tools/install-kubectl/

Install Kind

curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.10.0/kind-linux-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/kind

参考文档 https://kind.sigs.k8s.io/docs/user/quick-start/#advanced

创建集群

kind create cluster

这将使用一个预编译好的节点镜像快速启动一个 Kubernetes 集群,默认集群名称为 kind ,可以使用 —name 参数指定自定义名称。

参考文档 https://kind.sigs.k8s.io/docs/user/quick-start/#installation

自定义创建集群参数

创建集群时候,可通过 —config 参数指定配置文件,示例配置见 kind-example-config

kind create cluster --config example.yaml

可通过指定节点角色的数量配比,实现不同需求。如下面示例配置则会创建一个双 master + 三worker 节点的高可用集群 

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker

部署 Prow

创建 prow namespace

kubectl create ns prow

GitHub 创建机器人用令牌

调试的时候可以直接用自己的 GitHub 帐号创建Token 使用,在正式使用的时候,为区分操作人,建议使用单独的机器人Github 帐号。

  • Token 需要有 repo:statuspublic_repo 权限
  • 项目仓库需将机器人帐号加入合作者中
  • 私有仓库则必须要有 repo 全部权限
  • 如果是 GitHub 组织接入,则额外需要勾选 admin:org_hook

创建 GitHub Token 对应的 secret

echo "my-github-token" > ./github-token
kubectl create secret -n prow generic github-token --from-file=./github-token

创建一个用于 Github WebHook 认证的 hmac 令牌,并创建 kubernetes secret

openssl rand -hex 20 > ./secret
kubectl create secret -n prow generic hmac-token --from-file=hmac=./secret

创建集群 Role Binding

kubectl create clusterrolebinding cluster-admin-binding-"${USER}" \
  --clusterrole=cluster-admin --user="${USER}"

应用 yaml 配置部署

下载 https://github.com/kubernetes/test-infra/blob/master/config/prow/cluster/starter-s3.yaml 配置,修改

  • 替换 Github token:<<insert-token-here>> 
  • 替换生成的 hmac token: << insert-hmac-token-here >>
  • 替换域名: << your-domain.com >>
  • 如果有使用证书管理器,则需更新 cert-manager.io/cluster-issuer:
  • 替换目标组织/项目: << your_github_org >>(如 wayjam/test-repoan-org/test-repo
tide:
      queries:
      - labels:
        - lgtm
        - approved
        missingLabels:
        - needs-rebase
        - do-not-merge/hold
        - do-not-merge/work-in-progress
        - do-not-merge/invalid-owners-file
        orgs:
        - << your_github_org >>
				repos:
				- wayjam/prow-test

应用了配置之后,发现部分 pods 启动失败(CrashLoopBackOff)

{"component":"prow-controller-manager","error":"tide query (index 0) is invalid: 'orgs' and 'repos' cannot both be empty","file":"prow/cmd/prow-controller-manager/main.go:123","func":"main.main","level":"fatal","msg":"Error starting config agent.","severity":"fatal","time":"2021-02-24T14:20:54Z"}

发现是有部份目标没有完全替换,重新修改配置,应用则全部 pods 可以正常启动。

配置外网访问

所有 pod 运行成功之后,上面的 starter.yaml 只包含了 ingress,但是没有包含 ingress controller,这里选择官方的 nginx ingress 作为流量入口,由于是测试,则不额外添加 LB。

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/kind/deploy.yaml

但是应用后发现 nginx pod 一直 pending,排查日志发现是由于我初始化的 kind 集群只有一个master 节点,不满足上面 yaml 配置的调度规则

Warning  FailedScheduling  76s (x5 over 100s)  default-scheduler  0/1 nodes are available: 1 node(s) didn't match Pod's node affinity

先把 Deployment 中的 tolerations 去掉,然后给 master 节点打上所需标签:

kubectl label node kind-control-plane ingress-ready=true

最好就是在集群初始化的时候按照 https://kind.sigs.k8s.io/docs/user/ingress/ 文档指引预先配置好集群,集群创建之后则不能再更改配置

除了节点标签之外,集群的端口还需对外暴露以提供服务,初始化集群的时候需按上面文档使用 extraPortMappings 参数指定转发的端口。

如果集群已经创建并已经部署好了服务,也像我一样不想重新创建集群,也可通过下面方法做快速端口转发。当然自行通过 Nginx 容器 link 到 kind 网络的 kind-control-plane 容器即可( nodeport 监听所在)。

root@VM-debian:~/$ kubectl -n ingress-nginx describe service ingress-nginx-controller
Name:                     ingress-nginx-controller
Namespace:                ingress-nginx
Labels:                   app.kubernetes.io/component=controller
                          app.kubernetes.io/instance=ingress-nginx
                          app.kubernetes.io/name=ingress-nginx
Annotations:              <none>
Selector:                 app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
Type:                     NodePort
IP Families:              <none>
IP:                       10.96.250.65
IPs:                      10.96.250.65
Port:                     http  80/TCP
TargetPort:               http/TCP
NodePort:                 http  32291/TCP
Endpoints:                10.244.0.107:80
Port:                     https  443/TCP
TargetPort:               https/TCP
NodePort:                 https  32191/TCP
Endpoints:                10.244.0.107:443
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

# 将 ingress-nginx 服务的 NodePort 32291 端口映射到本地 80 端口
$ docker run -itd --name ingress --network kind -p 80:80 --link kind-control-plane zhangsean/nginx-port-proxy kind-control-plane:32291
# 将 ingress-nginx 服务的 NodePort 32191 端口映射到本地 443 端口
$ docker run -itd --name ingress-https --network kind -p 443:80 --link kind-control-plane zhangsean/nginx-port-proxy kind-control-plane:32191

配置 WebHook

首先测试公网请求是否能通:

http POST https://prow.lockthedoor.ltd/hook --verify no

到 GitHub 项目设置添加 WebHook

  1. Payload URL: 填入公网地址,如 https://prow.lockthedoor.ltd/hook
  2. Content Type: application/json
  3. Secrets: 刚才随机生成的 HMAC
  4. Which events would you like to trigger this webhook: Send me everything
  5. SSL verification: 如果没有使用可信证书,则选择 Disable

配置webhook

新建一个 issue(如 https://github.com/wayjam/prow-test/issues/1),在评论框输入 /meow 机器人收到时间则会发送一个猫咪评论。

image-20210301010751579