Registry Mirror

最近在建置 container image 時,常會踩到 exceeded 的錯誤,這是因為 docker 在 2020 時,公告了新的收費機制,並為拉取 container image 的 API 加上了限制,沒有登入的使用者現在每6個小時只能有 100 個 pull requests可用;有登入且採用免費方案的使用者,每6個小時有 200 個 pull requests 可用。這在初期測試 pipeline 時,根本很容易就用超過。

上網搜尋看有沒有方法可以避過這限制,後來在 gitlab 網站上找到文章:Caching Docker images to reduce the number of calls to DockerHub from your CI/CD infrastructure | GitLab

文章裡有提到兩個方法,第一個簡單的方法就是登入,這樣可以提升到 200 個 pull requests。

因為大部分的 executor 都是使用 docker 或 docker + machine,所以設定方法可以單純的在 pipeline 裏面作 docker login,但這樣還要多塞指令跟 credential 。gitlab 很貼心的提供了一個內建的變數,要用這個變數,需要在 gitlab 專案的 settings > CI/CD > Variables 裡,去增加 DOCKER_AUTH_CONFIG ,那在執行 pipeline 時,gitlab-runner 看到有這個變數,就會自動做 login 的動作。

DOCKER_AUTH_CONFIG 的內容可以透過以下方式取得:

  1. 在終端機用指令先登入 index.docker.io: docker login
  2. 用 docker 指令登入後,在家目錄的 .docker 目錄下就會出現 config.json : cat ~/.docker/config.json
  3. 用 jq 指令讓內容變成一行: jq -c "." ~/.docker/config.json

輸出的結果,就可以拿來填了。

第二個方法,則是建置 Registry mirror。

找一台已經安裝 docker 的主機,然後使用 docker 啟動 registry container。在啟動的時候帶入環境參數 REGISTRY_PROXY_REMOTEURL

docker run -d -p 6000:5000 \
    -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \
    --restart always \
    --name registry registry:2

然後登入到 gitlab-runner 所在的主機,修改 /etc/docker/daemon.json ,內容如下

{
  "registry-mirrors": ["http://<your-registry-mirror-server:6000"]
}

修改完以後,讓 dockerd 重新載入設定:

sudo systemctl reload docker

再用 docker info | grep -A 1 -B 1 Mirror 確認。

這樣就設定完成了。

那要怎麼知道 gitlab-runner 在建置時有使用這個 registry mirror 呢?這時可以用 curl 指令來檢查

watch -n 60 curl -s http://<your-registry-server>:6000/v2/_catalog

輸出結果大致會是這樣

{"repositories":["library/docker","library/python"]}

至此,就可以算是解決了 exceeded 的問題啦。

Run ansible in gitlab runner

在 gitlab runner 裡想要執行 ansible playbook 進行佈署,幾個問題以及我的應對:

  1. ansible 的安裝:是可以自己加 ansible 的 package repository ,然後用 apt 安裝,但已經有好心人打包了裝好 ansible 的 docker image ,只要在 .gitlab-ci.yml 加入 image 設定即可:
    image: williamyeh/ansible:ubuntu14.04
  2. playbook 要放在哪裡?因為要直接在專案進行佈署,所以 playbook 也要放在專案裡,我在專案裡建立了一個 ansible 的目錄,把 playbook 放在這裡。
  3. 私密資料如何保存?gitlab 在專案設定裡提供了 variables,可以用來存放這些私密的資料,在 .gitlab-ci.yml 裡,只要用 $VAR_NAME 就可以使用這些變數。.gitlab-ci.yml 裡也可以自訂 variables ,但這些 variables 是進到 git repository 的,要視情況使用。
  4. Ansible 連到目的機器需要 SSH Key:這比較麻煩一點,好在 gitlab 有提供如何使用 SSH key 的文件,步驟很詳細,簡述如下:
    1. 在專案設定的 variables 裡新增有 SSH private key 的變數。
    2. 檢查 ssh-agent ,如果沒有就安裝 openssh-client
    3. 執行 ssh-agent
    4. 用 ssh-add 匯入第一個步驟所設定好的變數
    5. 在 ~/.ssh/config 裡加入不檢查 host key 的設定:
      Host *
          StrictHostKeyChecking no

參考資料:

gitlab-ci-multi-runner 在 archlinux 上的設定

gitlab-ce 到 8.0 以後,就把 gitlab-ci 整進去了,要用 gitlab-ci ,需要安裝 gitlab-ci-multi-runner。

archlinux AUR 裡已經有人包進去了:

  1. 用 yaourt -S gitlab-ci-multi-runner 安裝。
  2. 用 sudo systemctl enable gitlab-ci-multi-runner 啟用
  3. 執行 gitlab-ci-multi-runner register 進行設定,設定時會問:
    1. gitlab-ci coordinator URL :請到 gitlab 專案設定裡的 runner 畫面取得
    2. gitlab-ci token for this runner:跟上面一樣,到 gitlab 專案設定裡的 runner 畫面取得
    3. gitlab-ci description for this runner: 隨便填,能認得就好
    4. gitlab-ci tags for this runner:隨便填,不填就按 enter
    5. executor:這邊就看需求,我是填了 docker
    6. Docker image:應該是選了 docker 的關係,這邊需要填,主要是問要以哪個 image 為基底,ruby 可以填 ruby:2.1,python 可以填 python:2.7,日後有用到再去找。
    7. 其他:問 mysql, postgresql, redis, mongodb 要用哪個版本。
  4. 設定完,gitlab-ci-multi-runner 服務會自動載入新設定,不放心的話,用 sudo systemctl restart gitlab-ci-multi-runner 重新啟動。

到 gitlab 專案設定裡的 runner 畫面去看,應該就會看到剛剛新增的 runner。

使用上可以參考這篇 gitlab ci quickstart 來做,大致就是在專案裡新增 .gitlab-ci.yml ,裏面填好要執行的步驟,加入 repository、提交、push,之後每次 push 時,就會執行 .gitlab-ci.yml 裡的步驟了。