Kubernetes 原生 CI/CD 系統 Prow 簡介
作者:bbbmj(才雲軟體工程師)
編輯:bot(才雲)
如果你正在大規模進行 CI/CD,卻沒有使用 Kubernetes 原生 CD,你可能錯過了不少東西。Prow——正如這個希臘語的含義“船頭”——一直是使 Kubernetes 成為大規模執行 CI/CD 的優秀平臺的強大助力。多年來,它也始終處在原生 Kubernetes CD 的最前沿。
如果你經常混跡於 Kubernetes 上游社群,你一定知道 k8s-ci-bot:point_down:,它能幫助管理上游的 PR & Issue,幾乎無處不在。今天,我們就來探究一下它背後的專案 Prow。
什麼是 Prow
Prow 的出現稱得上是順勢而為。在它誕生前夕,Kubernetes 正值快速發展,開發者們每天需要在數個 GitHub 組織的 100 多個程式碼庫中執行超過 10,000 個 CI/CD job。為了簡化工作,Kubernetes 測試特別興趣小組(sig-testing)建立了一系列工具和服務,其中就包括 Prow。
在官方文件中,Prow 被描述為是一個 Kubernetes 原生 CI/CD 系統,可以通過各種型別的 GitHub 事件觸發 job,並將其狀態報告給不同的服務 (如 Gerrit、Google Cloud Pubsub 和 GitHub 等)。除了執行 job,它還能通過以下形式提供 GitHub 自動化:
-
策略驅動(科學的策略,讓 GitHub 許可權管理更嚴謹、安全)
-
/foo 樣式命令的 chat-ops
-
自動合併 PR
注:GitHub 自動化包括 issue 管理、PR 管理(Review 程式碼、Approval、自動化測試、自動化合並、自動化檢測程式碼測試覆蓋率)和 Release 管理三類內容。
目前,Prow 已被超過 140 個專案使用,下面是一些典型組織和專案:
-
Kubernetes
-
OpenShift
-
Istio
-
Knative
-
Jetstack
-
Kyma
-
Prometheus
-
Caicloud :point_left: 我所在的公司 :sunglasses:
-
Kubeflow
-
Azure acs-engine
-
tensorflow/minigo
-
helm/charts
作為一種基於事件的解決方案,Prow 提供了適合雲原生世界的鬆散耦合架構,被許多 Kubernetes 專案用於 CI/CD。例如,Tekton 目前正在使用 Prow 構建和測試 Tekton Pipeline;Istio 在其早期就集成了 Prow;Jenkins X 把 Prow 作為 Serverless Jenkins 的一部分;Knative 不僅為 Prow 提供了一個 CI/CD job 執行引擎,它也把 Prow 作為自己的 CI。
完整的專案生態,多次 KubeCon 登臺經歷,Prow 的實力毋庸置疑 :exclamation:️
工作原理
作為 Kubernetes 測試特別興趣小組(sig-testing)的頂級專案之一,現在 Prow 是 Kubernetes test-infra 專案的一部分。但截至目前,它還沒有自己的獨立 GitHub repo,只是作為 kubernetes/test-infra 目錄下的一個子目錄。
下圖是 Prow 的微服務架構,其中每一個元件都是單獨的 Docker Image,在 Kubernetes 中以 Deployment 的形式執行。
為方便讀者理解 ,我從 GitHub 上翻譯了官方的一部分文件內容,用以解釋 圖中 Prow 各個元件, 具體如下:
Projob
Prowjob :使用 Kubernetes CustomResourceDefinition 實現,以下我會用 job 指代 Prowjob。
GitHub
GitHub :將 PR / issue 等狀態變化的事件傳送到使用者指定的 Webhook URL。
核心元件
Hook :Prow 最核心的元件,它是一個無狀態服務,開啟 /hook
路由接收 GitHub webhooks (events),驗證 hmac secret 並根據 event type 分發任務到不同的 plugin 中執行。plugin 負責觸發 jobs、實現 /foo
樣式命令的 chat-ops、通知到 Slack 等工作。Prow 在部署時,可以配置你的 repo 使用哪些 plugin。
Plank :Prowjob controller,負責管理在 Kubernetes 中 job 的執行與生命週期。
Deck :一個 dashboard,展示 job、PR 的狀態資訊,還有各種 Hook Plugins 對應的 chat-ops 命令幫助資訊。Kubernetes 官方的 Deck 連結:https://prow.k8s.io。
Horologium :根據策略建立 Periodics 型別的 job。
Sinker :定時清理舊的 job 和相關聯的 job 狀態是 finished
的 Pod,清理週期可配置。
自動化合入 PR
Tide :自動重新測試 PR,並根據預先設定的合併標準,自動化合並 PR。
輔助元件
Crier :Prowjob controller,負責 watch job status,並更新 reporter 的 status。reporter 目前支援 Gerrit、Pubsub、GitHub。(功能上與 Plank 有所重複,擇一即可)。
來源: https://github.com/kubernetes/test-infra/blob/master/prow/cmd/README.md
Prowjob 生命週期
關於 Prow 是如何執行 job 的,官方在 GitHub 上其實有簡要介紹,詳見[1], 這裡再基於原始碼做具體解讀 。
在 PR 中評論 /test all
,Github 將建立一個表示該事件的 JSON 物件,併發送 webhook 到 Prow。webhook payload 示例見[2]。
webhook 在 ingress
的幫助下進入叢集, ingress
中有一條規則 /hook
指向 hook。
hook 反序列化 payload 到 go 結構體,然後傳給各個 plugin。對於每一個 plugin,hook 會傳兩個物件,plugin client 和反序列化的 github event(這裡是 IssueCommentEvent)。plugin client 結構體中包含 GithubClient
(對 GitHub 操作的方法)、 KubeClient
和 Config
(Prow 相關配置)。
trigger
plugin 在 init
方法中註冊了 GenericCommentEvent
,hook 會把 event 分發給它處理。
trigger
plugin 中有一個 handleGenericComment()
方法通過 event 的 body 與 PluginClient.Config 進行比較,來判斷哪些 job 需要執行,然後在叢集中建立對應的 ProwJob
。 到這裡,hook 的一次 webhook 處理就結束了,之後它會繼續下一次 sync。
ProwJob
的 YAML 檔案表示可能如下:
然後 Plank
會根據預先設定的週期,去 list CreatedByProw
和 ProwJobAgent = "kubernetes"
的 Pod,根據 Prowjob 的狀態分成兩種型別:pending job、triggered job,再分別 sync 兩種型別的 job,維護其生命週期和狀態,並傳到 report 的 go channel 中。最終讀取 report channel 中的資料並更新 GitHub status。
最後, Sinker
會根據預先設定的週期,定期清理舊的 job 和相關聯的 job 狀態是 finished
的 Pod。
如何寫一個 Prow plugin
關於 Prow 的部署,看視訊會比看文字更直觀,所以這裡我給大家推薦一個 Youtube 視訊,有條件的讀者可以科學上網看一看 :
https://www.youtube.com/watch?v=eMNwB96A1Qc
下面,我們通過一個示例—— cat
plugin ,來描述 plugin 的實現和使用,原始碼見[3]。
新增 plugin 程式碼需要在 plugins 目錄下。
首先定義 plugin 的名字
在 init 方法中註冊需要處理的 event 對應的 handler
,當發生該 event,hook 會分發給你處理。
根據需要對 GitHub 有哪些操作,定義對應的方法:
實現 helpProvider:
實現 handleGenericComment 的具體邏輯:
然後在 hook/plugins.go 中 import "k8s.io/test-infra/prow/plugins/cat"
。
最後在 plugins.yaml 中新增這個 plugin,就大功告成了。
plugin 相關部分配置:
最後的最後,如果可以的話,記得寫上測試。
最終效果:
這裡我只描述了 cat
plugin 的實現原理,比較簡單。如果你對這方面的實踐感興趣,只要大膽發揮想象,自定義外掛可以做到更多~
寫在最後
篇幅所限,我在這篇文章裡只分享了 Prow 的部分內容,關於它的核心策略及更深層次的內容,讀者可以自行了解。除此之外,test-infra 還有很多功能和有用的小工具, 如果有問題或是心得體會,歡迎進 K8sMeetup 中國社群的微信群找我 ,或上 GitHub 多擼幾下:)
進群小助手:kubernetes-china
官方 : https://github.com/kubernetes/test-infra/tree/master/prow
--
參考資料
[1]Prow 生命週期: https://github.com/kubernetes/test-infra/blob/master/prow/life_of_a_prow_job.md
[2] webhook payload 示例: https://github.com/kubernetes/test-infra/blob/92c3881f49/prow/cmd/phony/examples/lgtm_comment.json
[3] https://github.com/kubernetes/test-infra/blob/92c3881f49/prow/plugins/cat/cat.go
推薦閱讀:
在看點一下
寫留言