iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
0
DevOps

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

Day22 - GitLab CI 控制工作終止因素的各種方法,談 retry、timeout

在 GitLab CI 中,流水線上每道關卡每個工作順利執行與否,都是控制著整條流水線如何進行的依據關鍵之一;工作可能因為當下的環境因素無法執行,但重新執行即可;也有可能執行時間超過預期想像,導致流水線執行時間過長,那麼這些因素該怎麼控制呢?

下一次會更好?讓工作重新試試 retry

有些時候部分工作的 GitLab Runner 在承接工作之後,可能因為 Runner 當下的一時的環境因素,一時之間無法正確的執行工作,這時候通常會嘗試著手動重新執行該工作確認,而 GitLab CI 可以怎麼設定工作自動重新執行呢?

在 GitLab CI 中,系統在 GitLab 9.5 之後即提供了 retry 這個參數,並且在 GitLab 11.5 之後擴充了參數功能,增加了判斷條件的機制,首先先來看第一個 retry 的例子:

retry-job:
  image: ubuntu:20.04
  script:
    - echo 'Try Retry Feature'
    - exit 1
  retry: 2

上面的這個範例,刻意設計了一定會讓工作認為執行錯誤的情境,在 script 中,放置了 exit 1 的指令。其中 retry 參數代表這個工作在執行失敗後,最多會再重新執行 2 次。如底下的畫面,包含第一次執行之後失敗後,系統再次的重新嘗試了 2 次:

工作重新執行

PS. retry 參數必須是一個大於等於 0 且 小於等於 2 的整數。

另外,當工作執行失敗啟用重新執行機制時,重新執行的 GitLab Runner 並不一定會是原本執行失敗的 Runner,因為重新執行機制啟動,會再將該工作加入到 GitLab Server 上的工作佇列中,等待可以 Runner 來領取工作,所以只要可以執行該工作的 Runner 都有機會領取到該工作。

更細部的設定 retry 參數

當只設定 retry 參數時,預設是只要有任何因素導致工作執行失敗,就會進行重新執行的動作。而可以限定一些因素嗎?在 GitLab 11.5 之後,新增了一些條件來限縮重新執行的條件,因此增加了兩個屬於 retry 的子參數:

  • max: 最多可重新執行的次數
  • when: 工作執行失敗的條件,可以有多個條件

以上方的範例改寫成增加兩個子參數的例子:

retry-job:
  image: ubuntu:20.04
  script:
    - echo 'Try Retry Feature'
    - exit 1
  retry:
    max: 2
    when:
      - always

如上方的這個例子,可以看出 when 參數,是允許設定多個條件的,那麼 when 支援哪些條件呢?

  • always:工作發生任何錯誤 (預設值)。
  • unknown_failure:工作發生未知原因的錯誤。
  • script_failure:當工作的 script 發生錯誤。
  • api_failure:當使用 API 發生錯誤。
  • stuck_or_timeout_failure:當發生阻塞或執行時間過長。
  • runner_system_failure:當 Runner 的執行系統發生錯誤,如工作啟動失敗。
  • missing_dependency_failure:當設定相依的工作不存在。
  • runner_unsupported:當 Runner 無法支援時
  • stale_schedule:設定延遲執行的工作無法執行時
  • job_execution_timeout:當工作的 script 執行時間超過設定的最大執行時間時。
  • archived_failure: 當工作被封存而無法執行失敗時。
  • unmet_prerequisites:當工作的無法完成前置工作時。
  • scheduler_failure:當排程工作無法成功將工作交給 GitLab Runner 時。
  • data_integrity_failure:當判斷到結構完整性問題時。

工作必須在一定時間內完成才算成功執行 timeout

GitLab CI 的工作當下執行失敗,可以透過重新執行來驗證是否是永久性的錯誤,但工作如果設計在一定時間內執行成功才算成功,在 GitLab CI 中可以怎麼設定?在 GitLab 12.3 之後,提供了 timeout 這個參數,可以供設定該工作執行超過多久後,即判斷為執行失敗。如下第一個例子:

timeout-job:
  image: ubuntu:20.04
  script:
    - echo 'Try timeout Feature'
    - sleep 60
  timeout: 30s

如上範例,在 script 中,設定了讓工作停止 60 秒,但 timeout 設定了超過 30 秒算超時,因此這一工作會執行失敗

執行失敗示意

那麼,timeout 參數的時間設置格式有哪些呢?timeout 的時間設置格式,與之前談工作成品產出的過期時間格式是一致的,沒填單位時,預設一樣為秒,概略如下:

  • '42'
  • 42 seconds
  • 3 mins 4 sec
  • 2 hrs 20 min
  • 2h20min
  • 6 mos 1 day
  • 47 yrs 6 mos and 4d
  • 3 weeks and 2 days

注意事項:

  1. 通常專案上預設 60 分鐘為超時(timeout)時間,因此如果該工作已知會執行超過 60 分鐘,也可以透過 timeout 參數來覆寫預設的 timeout 時間。當然也可以透過專案上的「settings -> CI/CD -> General pipelines settings」中設定預設的超時時間。
  2. 在工作中設定的 timeout 不得超過 GitLab Runner Server 上設定的 runner 最大可執行時間。

專案上設定 timeout 的方法

總結:

當啟用 retry 機制時,可能就需要稍微思考一下,這個環境因素是否是可以避免的?retry 的設置是否真的是有必要的?畢竟,透過 retry 來再次執行就可能獲取成功,一個程度上也表示著,這個工作不是每次都可以成功,代表著它並非穩定的。

下一篇會繼續介紹關於在 GitLab CI 上關於終止工作的相關條件及參數。我是墨嗓(陳佑竹),期待這系列的文章能夠讓人有些幫助。


上一篇
Day21 - GitLab CI 選擇指定的 runner 來承接工作,談標籤 tags
下一篇
Day23 - GitLab CI 新的流水線啟動,已經在執行的流水線工作是否停止?談 interruptible
系列文
用 GitLab CI 玩轉自動化測試與佈署31

尚未有邦友留言

立即登入留言