作者:bbbmj(才雲軟體工程師)

編輯:bot(才雲)

編者按:如果你正在大規模進行 CI/CD,卻沒有使用 Kubernetes 原生 CD,你可能錯過了不少東西。Prow——正如這個希臘語的含義「船頭」——一直是使 Kubernetes 成為大規模執行 CI/CD 的優秀平臺的強大助力。多年來,它也始終處在原生 Kubernetes CD 的最前沿。

如果你經常混跡於 Kubernetes 上游社區,你一定知道 k8s-ci-bot??,它能幫助管理上游的 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 ?? 我所在的公司 ??
  • 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 的實力毋庸置疑??

工作原理

作為 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 鏈接: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 有所重複,擇一即可)。

來源:github.com/kubernetes/t

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 操作的方法)、KubeClientConfig(Prow 相關配置)。

trigger plugin 在 init 方法中註冊了 GenericCommentEvent,hook 會把 event 分發給它處理。

trigger plugin 中有一個 handleGenericComment() 方法通過 event 的 body 與 PluginClient.Config 進行比較,來判斷哪些 job 需要運行,然後在集羣中創建對應的 ProwJob。到這裡,hook 的一次 webhook 處理就結束了,之後它會繼續下一次 sync。

一個 ProwJob 的 YAML 文件表示可能如下:

然後 Plank 會根據預先設定的週期,去 list CreatedByProwProwJobAgent = "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 視頻,有條件的讀者可以科學上網看一看:

youtube.com/watch?

下面,我們通過一個示例—— 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

官方 :github.com/kubernetes/t

參考資料

[1]Prow 生命週期:github.com/kubernetes/t

[2]webhook payload 示例:github.com/kubernetes/t

[3]github.com/kubernetes/t

推薦閱讀:

相關文章