再戰 Jenkins CI Pipeline: Parallel 加速

Keith Yang
iCHEF
Published in
5 min readDec 20, 2018

在上篇【重返 Jenkins CI 榮耀 ||】之間,iCHEF 的 Backend CI 也從千百個 tests 翻倍了,一年半載之間從不用半小時的 CI 也到了需要跑一個小時的等級,這怎麼受得?

於是發了一個 pull-request (PR),大意就是做了一堆精緻化的工來加快 CI 並縮短 timeout(之前 timeout 一等就是兩小時),同時維持不動 legacy code 假裝沒事的姿態:

  • Split tests and coverage for parallel testing in CI.
  • Allow PR branch to have Cobertura coverage report on Jenkins.
  • Add docker-compose target development to speed up docker image build.
  • Wait also PostgreSQLs up during docker-compose up.
  • Refine timeout in deeper stages in Jenkinsfile.
  • Use Jenkins pipeline stash to publish Cobertura coverage report of parallel tests.
  • Remove rarely used HTML report of Python coverage.
  • (On AWS) Use dedicated docker image builder instance to speed up build.
  • Move all frontend to the same place with backend parallel tests since backend build can be much faster than frontend all now.
  • Always remove unused old built docker images to save disk storage on builder instance.
  • Pretty some console output with the current timestamp.
  • (On AWS) Daily rotate EC2 fleet backend builder instance to keep disk-full away.

PR 沒寫到之前不這樣做的難點,在於 iCHEF backend 的 legacy tests 無法直接用 pytest-xdist 套件跑成功,即便切 apps 跑不同的測試連著同一個 docker-compose network 都會失敗。

要點

  1. 開出獨立的 docker image builder,讓 build 盡可能吃到 cache,Build 完 push 到 AWS ECR 讓新開的機器只要拉下去跑測試就好。之前是可能在剛開出來的 EC2-Fleet 新機器上整個重頭花時間 build。
  2. 大方地讓 docker-compose 在每台機器上開出兩個 cluster 來跑,四個 cluster 分在兩台機器上跑。測試過這樣就算四個 cluster 都跑在同一台上還是比一個快約 20 分鐘。然後還不能開太多台,會有 EC2-Fleet plugin 一個個開太慢出來或 fleet 機器太常被關掉的後遺症。
  3. JUnit plugin 與 Codecov 都可以分別吃下 parallel 的結果,Cobertura 則需要用到 `stash` & `unstash` 大法。

心法如上,工法歡迎一起來看 PR,iCHEF 現正徵【各端工程師】。

Hint: 天下沒有白吃的午餐;如果有,就是跑 docker-compose build 時幫 docker multi-stage builds 加上 target。

沒圖沒真相?好啦目前 Cloud CI Workflow 的樣子

Before: 1h 1m 29s

After: 15m 30s

Q & A

  1. Check Security stage 怎麼一直被跳過?
    答:就 Python 套件 bandit & safety 所做的安全檢查,是可能隨時更新而造成許多 branch 不必要地同時在 build 階段失敗的,所以實務上除非是毀滅性的問題,否則會在回到 develop 與 master 時再執行這個步驟;另外這也同時為 PR 省下了近 10 分鐘的 build。
  2. Tests 是怎麼切的?
    答:用工人智慧手切,還沒用到 AI。讓各個 Django app 可以平均地跑完,避免等待。新加的 app 會先排入特定的 queue 裡去跑,有明顯差距再來調整。
  3. Timeout 可能隨著 app 增加,到時總是會超過怎麼辦?
    答:到時再用工人智慧調一下即可,假設到每個月都有新 app 產出的規模時,再來考慮用紅黑樹(誤)來 balance 吧。
  4. 用 spot 生個大機器可以加速嗎?
    答:一般也許可以,這邊已經用 EC2-Fleet 開出不算小的 spot instance,就是邊際效益,沒什麼明顯的加速囉。

延伸閱讀

相信看過這上下篇你對 Jenkins Pipeline 已感到興趣無比?那不能錯過 c9s 寫的【精通 Jenkins Pipeline 系列】目前出到 「Groovy 以及 Jenkinsfile」、「Transform, Node Step 以及 Declarative Pipeline」,以及「Declarative Pipeline and its implementation」,以及期待以及待續,特別那 Jenkins Artwork。

看到這邊相信你也對 iCHEF iOS team 的 legacy Jenkins 1 CI,神奇地無大礙升到 Jenkins 2 的過程與結果感到興趣,frontend team 的 React 組合技,或著 QE team 的自動化整合測試各種,敬請期待,下一位謝謝。

--

--