今天的案例,來自朋友的需求。在擁有多個 GitLab Runner 執行環境中,有一個維運自動化 Pipeline 流程,希望 Pipeline 在啟動之後 Pipeline 裡的所有 Job 都可以在相同的 Runner 上執行,即當 Pipeline 上第一個 Job 被 Runner 領走後,後續的所有 Job ,都希望可以以該 Runner 執行,在 GitLab CI/CD 中,該如何辦到?
在 GitLab CI/CD 的架構中,GitLab Server 在建立 Pipeline 之後,會依據 CI/CD YAML 的內容,開始將待執行的 Job 放到佇列中,等待 GitLab Runner 來領工作去執行。而 Runner 可以領走 Job 的條件是,必須符合 CI/CD YAML 上宣告的 Tags
資格。所謂 Tags
資格,比喻成求職資格,就像,承接特定工作職缺,必須擁有什麼認證、通過什麼考試,如通過認證、考試符合資格的求職者很多,則這些求職者都可以徵求這個工作職缺,因此無法確認,最終會是誰取得工作。
而這個題目遇到的問題就像,系統中有多個 GitLab Runner,擁有 Job 所需執行資格的 Runner,有好幾個,假設這個 Pipeline 有 A、B、C 三個 Job,他們都只需要基本的資格,系統上大部分的 Runner 都可以滿足,因此 A、B、C 三個工作建立後,就可能會被不同的 Runner 領去執行,而無法滿足限制 Job 都被同一個 Runner 領走的需求。
因為需求的目標是讓 Pipeline 上的所有 Job 都可以在同一個 Runner 上執行,而從限制在同一個 Runner 執行的角度來思考,可以借用 GitLab Runner 把 Job 接去執行的條件是「必須滿足 Job 宣告的條件(Tags)」來往下延伸,那麼是不是讓 Pipeline 建立後,透過第一個 Job 的 Script 取得該 Runner 可以決定性的 Tags 條件後,接著再透過後續的 Job 加入這個決定性條件就可以了?
什麼是 Runner 可以決定性的條件呢 ? 在 Predefined CI/CD variables 手冊中,可以注意到與 GitLab CI Runner 相關的 variable 有:
Variable | Availability | Description |
---|---|---|
CI_RUNNER_DESCRIPTION |
Job-only | Runner 的描述。The description of the runner. |
CI_RUNNER_EXECUTABLE_ARCH |
Job-only | Runner 所在作業系統的執行架構。The OS/architecture of the GitLab Runner executable. Might not be the same as the environment of the executor. |
CI_RUNNER_ID |
Job-only | Runner 的唯一 ID。The unique ID of the runner being used. |
CI_RUNNER_REVISION |
Job-only | The revision of the runner running the job. |
CI_RUNNER_SHORT_TOKEN |
Job-only | The runner’s unique ID, used to authenticate new job requests. The token contains a prefix, and the first 17 characters are used. |
CI_RUNNER_TAGS |
Job-only | Runner 的 Tags。A JSON array of runner tags. For example ["tag_1", "tag_2"] . |
CI_RUNNER_VERSION |
Job-only | Runner 的版本。The version of the GitLab Runner running the job. |
從與 GitLab CI Runner 相關的 Pre-Defined Variables 中可以發現,看起來可以確認是哪個 Runner 的變數有:
CI_RUNNER_ID
: Runner 的唯一 IDCI_RUNNER_SHORT_TOKEN
:Runner 的 Short TokenCI_RUNNER_TAGS
可能是可以用來滿足指定條件的變數,因為執行 Job 的時候,可以設定該 Job 要使用的 Tags,只要這些 Tags 足以定義到預期的 Runner,就可以拿來做宣告使用什麼 Runner 。
所以接下來只需要在建立 GitLab Runner 的時候,為專案中可以使用的 Runner 們,都建立一個可以用來識別該 Runner 的 Tag。例如流水號: Runner01、Runner02...,只要可以確保 Tag 沒有重複的 Runner 使用。
定義好 Runner 的 Tags,讓 Tag 足以定義唯一的 Runner 後,看似已經可以實作了,也確定 Job 中的 Tags
可以以變數作為定義,因此看起來可以如下宣告:
job:
tags: $CI_RUNNER_TAGS
script: echo "do something"
正式編輯 GitLab CI/CD YAML 時,會發現在 Pipeline editor的介面上直接顯示錯誤,無法直接在 tags 上直接使用 CI_RUNNER_TAGS
變數,這是為什麼呢?
回顧上方的 Runner 相關變數的表格,看到所有 Runner 變數的相關欄位後方,都標注了 Job-only
代表 CI_RUNNER_TAGS
的有效區段是 Job-only
,只在 Job 建立之後才存在,因此就算 tags
支援變數,這邊還是無法直接置入 CI_RUNNER_TAGS
變數。
Job-only: These variables are only made available to each job when a runner picks up the job and runs it, and:
Can be used in job scripts.
Cannot be used with trigger jobs.
Cannot be used with workflow, include or rules.
我們在定義好可以指定 Runner,又知道可以使用 CI_RUNNER_TAGS
來找到指定的 Runner後,因為 CI_RUNNER_TAGS
屬於 Job-only 的變數,只在 Job 建立之後才有效,那麼我們還可以怎麼實作讓所有的 Job 可以在同一個 Runner 上執行呢? 下一篇我們會繼續實驗。如果我們的題目要再加上這些 Job 之間還要可以傳遞 Artifact、傳遞變數,又該怎麼實作?
我是墨嗓(陳佑竹),期待這次的內容能帶給你實用的啟發與幫助。