Table of Contents
前言
生活在台灣,總是要因為中華電信時不時海底電纜故障
連外國網路延遲超高,不是在找 VPN、就是在找替代方案…
打打遊戲無所謂,但如果是牽扯到正事,就讓人很不開心了
筆者習慣使用的 docker image registry 是 github 自帶的 ghcr.io,整合 github action 還蠻方便
這次中華電信故障後,從 ghcr.io pull image 變成非常的慢,觸發的部署也常常因為 timeout 而失敗
所以我要讓 Ansible 自動選擇 Docker registry
為什麼要選擇 Github Container Registry
大概有兩個原因
下面附上連結
以這次的案例來說
Docker hub 完全沒有受到影響
當然可能某一天兩個都會無法使用
但至少在 CI/CD 中加入一個第二選項
也是有備無患
備援策略
上面提到 Docker hub 是有下載限制的
Docker Hub limits the number of Docker image downloads (“pulls”) based on the account type of the user pulling the image. Pull rates limits are based on individual IP address. For anonymous users, the rate limit is set to 100 pulls per 6 hours per IP address. For authenticated users, it’s 200 pulls per 6 hour period. Users with a paid Docker subscription get up to 5000 pulls per day. If you require a higher number of pulls, you can also purchase an Enhanced Service Account add-on.
匿名下載是 100 times / 6 hour
註冊帳號是 200 times / 6 hour
以筆者來說,我幾乎不會在本機運行我整個架構
都是改完 code 就跑 github action 到部署
加上我整個架構有 3 個 container
每次的部署都是使用 latest tag,為了確保是最新的
都還會重新 pull
這樣的速度,很快就會達到上限
所幸 Docker 是有提供 API 可以查詢目前剩下的數量
最簡單的策略就是用數量判斷
數量太少,就使用 ghcr.io
數量足夠,就使用 docker.io
Ansible 自動選擇 Docker registry Playbook
改天再來寫寫我對 Ansible 的使用心得
今天直接上這次踩到的網路的坑
- name: Check docker hub remaining pull limit
block:
- name: Get temp docker token
ansible.builtin.uri:
url: https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull
user: "{{ github_user }}"
password: "{{ docker_password }}"
method: GET
return_content: true
register: http_response
- name: Parse token
ansible.builtin.set_fact:
temp_docker_token: "{{ http_response.content | from_json | json_query('token') }}"
- name: Get remaining
ansible.builtin.uri:
url: https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest
headers:
Authorization: "Bearer {{ temp_docker_token }}"
method: GET
return_content: true
register: http_response_remaining
- name: Parse remaining
ansible.builtin.set_fact:
docker_remaining: "{{ http_response_remaining.ratelimit_remaining | split(';') }}"
- name: Use docker hub
ansible.builtin.set_fact:
image_owner: "{{ docker_user }}"
use_registry: "docker"
when: docker_remaining[0] | int > 10
- name: Use github container registry
ansible.builtin.set_fact:
image_owner: ghcr.io/toc-taiwan
use_registry: "github"
when: docker_remaining[0] | int < 10
- name: Decide registry
ansible.builtin.debug:
msg: "Use {{ image_owner }}, remaining {{ docker_remaining[0] }}"
大致說明一下
- Get temp docker token
先透過 docker hub 的帳號、密碼取得一組查詢 API 用的 tokenhttps://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull
- Parse token
這邊就用到 ansible 中的 set_fact
將剛剛取得的 token 存到 temp_docker_token
- Get remaining
再來就可以使用剛剛的https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest
比較特別的是,Docker 沒有把剩餘數量放在 body 之中
而是放在 response 的 header
- Parse remaining
這邊簡單處理一下字串,取出數量
- Use docker hub or Use github container registry
這邊用到 ansible 的 when 語句
筆者這邊設定邊界數量是 10
本身有 3 個 image 要 pull
只要大於 3 基本就足夠
- Decide registry
這邊就是 log 一下目前被 Ansible 決定的 registry 是哪一個
總結
本篇文章很簡單的使用 docker.io 所剩下的限制來決定要使用哪個 registry
可能等到中華電信修好,也不太會有人記得這件事
但能夠在 CI/CD 中提供一個第二甚至第三個備援選項,總是不會錯的!