iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 29
0
DevOps

用 GitLab CI 玩轉自動化測試與佈署系列 第 29

Day29 - GitLab CI 如何讓工作流程流水線跑快一點?之三 讓 Runner 執行更快一點

上一篇談到從 .gitlab-ci.yml 開始建立關卡及工作,而後依序分派到工作佇列,等待 GitLab Runner Server 上的 Runner 來承接工作的這段過程,可以怎麼讓流水線跑得更快一些。接下來將繼續往下談,當 Runner 接到工作之後,可以怎麼讓它更快地完成工作?

首先,可以先思考,當 GitLab Runner 承接到工作後,直到工作執行完成,期間它做了哪些事情?

一、以 Docker Runner 為例,從接到工作開始,到完成工作做了些什麼事情?

在官方的文件上尋覓了許久,一直沒能找到談論各種 GitLab Runner 在承接工作後做了哪些事情的生命週期 (Lifecycle) 描述,所以這邊挑了個人比較熟悉的 Docker 作為 Runner executor ,手動作了一個簡單的實驗,把目前已知在 .gitlab-ci.yml 上有配置設定後,Runner 上就需要跟著做一些工作的流程全都加在一起,像是下載工作成品、建立工作成品、重置快取、建立快取等等的都湊在一個工作之中(有興趣可以直接查看執行結果)。

一個 Docker 承接工作之後可能有這些工作需要完成

如上圖的工作程序,在這個 Runner 承接了工作之後,總共有這幾個階段:

  • Resolving secrets
  • Preparing the “docker” executor:配置 docker 執行環境,包含下取得 docker image
  • Preparing environment:啟動 docker
  • Get source from Git repo:從 Git Repository 取得原始碼
    • fetching change:更新 Git 原始碼紀錄
    • checking out xxx as master:清理原始碼的環境
    • submodules setup:如果有 submodule 則下載及配置
  • Restoring cache:如有配置 cache 則重置回來
  • Download artifacts:如有工作成品則下載並且解壓縮
  • Executing before script:執行前置 Script
  • Executing script:執行主要 Script
  • Executing after script:執行後置 Script
  • Saving cache:儲存 Cache
  • Uploading artifacts:上傳工作成品
  • Cleaning up file base variables:清除檔案型態變數

有了這些程序的過程,就可以逐一討論這每一個階段可以怎麼加速:

二、每個階段可以怎麼加速?

1. 最重要的網路環境狀況是否可以更好?(Network Performance)

當 GitLab Runner 承接工作之後,僅只是在該 Runner 上執行工作,這些工作可能還需要一些外部支援,以 Docker Executor 來說,如果執行的環境沒有工作需要的 Docker Image,那就必須透過網路將 Docker 下載回來;如系統定義的快取檔案不放在 Runner 本地,也需要再次的從網路下載,這些都需要透過網路連線,因此 Runner 與需要的外部資源間的網路環境、品質會影響到整個 Runner 完整將工作執行完成的速度。

2. docker image 是否可以小一點? (Docker image size)

如上一段提到的,當本地沒有使用到的 Docker image 的暫存系統就需要再次的從 Docker registry 上面取得,除網路環境好可以加速取得的速度外,使用的 Docker Image 如果也可以小一點,那麼對於整個 Runner 的執行效率也是有幫助的。

image 大小的對照

在這邊以 GitLab 官方提供的免費 Runner 為例,其提供的通常預設是 ruby:2.5 的 Docker Image,如執行的 Docker Image 可以替換成如 ubuntu:20.04 執行速度上就會有一個層級的差異,如下圖,執行相同 script,僅差別在用不同 Docker Image 的兩個工作,ruby:2.5 執行了 43 秒,但使用 ubuntu:20.04 僅花費 19 秒。

速度的比較

3. Git Repo 的尺寸大小影響?

在小型的專案中 Git 物件可能不多,一旦變成大型專案光是 Git Commit 的數量動輒上萬個,這樣的專案如要完整的 clone 可能都需要花費很長一段時間,如果需要在較大型的 Repo 上建立建立 CI 流程,那麼 Runner 從 Git Repo 上取得原始碼的這段時間就必須要重視。

Git shallow clone 選項畫面

在 GitLab 的「Settings -> CI/CD -> General pipelines」段落下,有一個 「Git shallow clone」選項,其就是在設定,每次只取得該分支最後的幾個變更,GitLab 目前預設為 50 個,如果是可以調整的。

4. 相依套件的大小 Dependence Package Size ?

現階段許多程式語言都會有自己的相依套件管理工具,在 Script 執行時都會再次的執行套件下載動作,使用的套件們的大小也關係著工作完整執行完成的速度。因此也可以思考:

  • 使用到的套件是否都是必要的?
  • 這些套件是否可以套用快取機制?
  • 如果使用了快取機制,快取存放在哪邊?怎麼存放?下載及重置快取的速度會不會比沒使用快取還慢?

快取的設定可以參考:Day 24

5. 工作再次拆分,或平行化處理

有些時候,執行的工作是可以考慮拆組後使用 GitLab 的平行化執行處理的。像是大型的單元測試案例,像是單元測試,小專案數量不多的測試案例可能無感,但專案持續的變大如果單元測試數量多到全部執行完成需要一小段時間,那麼就可以開始思考,這些單元測試是否可以拆分?是否都是必要執行的測試?如可以拆分,則可以思考,使用的單元測試是否可以套用 GitLab 提供的平行化處理機制。

平行處理可以參考:Day 17

總結

GitLab Runner 上面調教的方法其實還有蠻多還沒談論到的,在這篇會持續的更新,把各種可以讓 Runner 跑得更快的方法統一記錄在這裡,也期待如果有朋友有其他的想法也歡迎分享。

我是墨嗓(陳佑竹),期待這系列的文章能夠讓人有些幫助。

參考資料:


上一篇
Day28 - GitLab CI 如何讓工作流程流水線跑快一點?之二 逐一調整
下一篇
Day30-1 - GitLab CI 可以怎麼重構及整理 .gitlab-ci.yml 讓內容更好瞭解?
系列文
用 GitLab CI 玩轉自動化測試與佈署31

尚未有邦友留言

立即登入留言