[濫用] GitLab CI/CD 的 cache 機制


感謝網友提醒,根據官方《Cache vs artifacts》的說法,看來 Heresy 這邊把 build 階段產生的檔案透過 cache 傳遞到 test 階段,應該是嚴重的誤解/誤用了。 XD


之前在《GitLab 簡單的 C++ 專案腳本範例》和《GitLab 的 C++ CI/CD 腳本:使用 PowerShell》這兩篇文章,有分享了 Heresy 這邊目前 GitLab CI/CD 的腳本寫法了。

而當時也有提到,在 build 階段到 test 階段,Heresy 沒有玩出比較正規的檔案傳遞方法。

最近 Heresy 又開始測試這部分的東西。理論上,要在不同的 job 間傳遞檔案,是要透過在 .gitlab-ci.yml 裡面加上 cache官網)來做。

在有加入 cache 的狀況下,GitLab Runner 會在 job 開始、透過 git 取得檔案後,就試著把 cahce 的檔案抓下來;而當腳本執行完後,則會再把 cache 指定的檔案打包,放到 Gitlab-runner 上。

Heresy 目前加上 cache 後的 .gitlab-ci.yml 大致上會像下面這樣:

stages:
  - build
  - test

build-linux:
  stage: build
  variables:
    GIT_SUBMODULE_STRATEGY: none
  script:
  - git submodule sync --recursive
  - git submodule update --recursive --init --remote external_linux
  - make -j
  cache:
    key: "linux-$CI_COMMIT_REF_SLUG"
    policy: push
    paths:
    - bin64/
    - lib64/*.a
  tags:
  - gcc

test-linux:
  stage: test
  variables:
    GIT_SUBMODULE_STRATEGY: none
  script:
  - echo testing...
  cache:
    key: "linux-$CI_COMMIT_REF_SLUG"
    policy: pull
    paths:
    - bin64/
    - lib64/*.a
  tags:
  - gcc

這邊可以看到,在 cache 下有 keypolicypaths 三個參數。其中 key 是用來區隔 cache 的,key 的值一樣的話,那檔案會被後面的 job 取代。

policy 則是可以用來設定 cache 的動作;如果是 push 的話,就不會去抓之前的檔案,而如果是 pull 的話,則不會把檔案上傳。
像這邊建置階段之前沒有需要使用的 cache,所以就設定成 push;測試階段也只需要取得建置階段的檔案、而不需要把檔案再做快取,所以就設定成 pull

path 的部分,就是指定要快取的檔案了。


理論上這樣的腳本寫法應該是沒錯的,但是 Heresy 這邊在測試的時候,卻會一直出現「Skipping cache archiving due to empty cache key」這個錯誤訊息…

本來 Heresy 一直以為是 .gitlab-ci.yml 裡面的 cachekey 沒給好,但是後來又研究了好一陣子,才發現這個錯誤和 .gitlab-ci.yml 的內容根本無關,而是 GitLab Runner 需要額外設定 cache_dir 才行(參考)。

gitlab-runner 在設定好之後,會把相關的設定資料儲存在 config.toml 這個檔案裡(參考);Windows 的檔案會和執行檔在一起,Linux 則是會放在 /etc/gitlab-runner/config.toml

而要讓 cache 可以正常運作的話,這邊至少要在 [[runners]] 的區塊下,加入 builds_dircache_dir,指定相關的路徑。

例如:

[[runners]]
  ...
  executor = "shell"
  builds_dir = "/mnt/codebuild/gitlab-runner/"
  cache_dir = "/mnt/codebuild/gitlab-runner/cache/"

不過另一方面,在只有指定 cache_dir 的狀況下,cache 只能在同一個 runner 上傳遞、而沒辦法跨不同的 runner…如果要能跨 Runner 的話,那就需要 S3 或 GCS 才行了…

這樣修改好了之後,前面的 CI/CD 腳本就可以正常運作了。在 job 的紀錄裡面,也會看到類似下面的訊息:

Version:      12.1.0
Git revision: de7731dd
Git branch:   12-1-stable
GO version:   go1.8.7
Built:        2019-07-19T13:52:54+0000
OS/Arch:      windows/amd64
Checking cache for windows-enginev2-1...
Runtime platform                                    arch=amd64 os=windows pid=8720 revision=de7731dd version=12.1.0
No URL provided, cache will not be downloaded from shared cache server. Instead a local version of cache will be extracted.
Successfully extracted cache

理論上,這樣至少可以解決同一台 runner 上的檔案傳遞。但是如果真的要增加 runner 的數量、並讓 cache 可以跨 runner 的話,那大概還是得自己搞一個 S3 server 起來玩了…

對「[濫用] GitLab CI/CD 的 cache 機制」的想法

  1. GitLab CI 上用來在 job 之間傳遞檔案的應該是 artifacts,不是 cache。兩者的使用情境並不相同。

    • 感謝提醒。
      根據官方的《Cache vs artifacts 》(https://docs.gitlab.com/ee/ci/caching/#cache-vs-artifacts)的說法,看來 Heresy 應該是嚴重的誤解/誤用了 XD

發表留言

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料