如何處理 Kubernetes 無法 Pull 私有鏡像庫的問題?
私有鏡像庫無法拉取
Private Image Repository 通常會因為不安全的關係而導致無法正常拉取。所以在拉取之前需要先行設定。這件事情分成兩個面向,也因此有兩個地方要進行設定。
Docker
透過 docker pull image 來取得 Image
將不信任的鏡像庫加入到信任清單中
需要先調整 docker 的設定檔,信任這個私有的 Repository。我們可以先進入
/etc/docker
。進入後如果沒有daemon.json
則需要自行建立。1
2
3
4// IP和PORT自行更換
{
"insecure-registries": ["[IP]:[PORT]"]
}調整 docker.service 啟動帶入的參數
sudo vi /usr/lib/systemd/system/docker.service
- 在 restart=always 下方加入
EnvironmentFile=/etc/docker/daemon.json
重啟 docker.service
1
2
3sudo systemctl daemon-reload
systemctl restart docker.service
systemctl status docker.service執行登入
1
sudo docker login [IP:Port] -u [UserName]
Pull Image
1
docker pull [IP:Port]/[Image Name]:[tag]
K8S Containerd
因為剛才已經利用 docker pull 拉取過 Image。在後續的 yaml 檔中,我們都需要有個認證能夠讓 K8S 使用,而非透過在每一個 Worker node 執行 docker login 。
在這裡我們使用剛才 docker login 所產生的檔案來建立 K8S 的 Secret File。或不利用檔案而是指定好帳號密碼來產生 Secret File。
產生 secret
- 利用 docker login 產生的檔案
1
2
3kubectl create secret generic regcred \
--from-file=.dockerconfigjson=autoConf.json \
--type=kubernetes.io/dockerconfigjson- 自行輸入資訊產生
1
kubectl create secret docker-registry insecure-registry \ --docker-server=[IP:Port] --docker-username=[User Name] \ --docker-password='[Password]' --docker-email=[User Email]
可以嘗試使用上面任一種方式產生,或兩種都行。在產生 Secret 後執行下面的語法,在
Auth
的欄位應該要完全相同。1
kubectl get secret [Secret Name] --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
1
2# decode opaque
kubectl get secrets/mongodb-secret --template='{{ index .data "填入secret內欄位的名稱" | base64decode}}'產生 secret 之後將其套用進 deploy yaml 中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22apiVersion: apps/v1
kind: Deployment
metadata:
name: dockerdemo-deployment
spec:
selector:
matchLabels:
app: uat-example
replicas: 3
template:
metadata:
labels:
app: uat-example
spec:
containers:
- name: uat-example-api
image: 10.1.23.49:8082/example-api:dev
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8034
imagePullSecrets:
- name: regcred #secret namek8s deploy
kubectl apply -f [File Name]
POD 失敗, Images 無法成功拉取
這時候可能會遭遇到問題,當你執行 kubectl get pods
的時候會發現沒有任何一個 pod 被啟動成功。再次執行 kubectl describe pods [pod name]
則會看見:
錯誤訊息:http: server gave HTTP response to HTTPS client 的相關錯誤
你可能會好奇,我 docker pull image 都能成功了,為什麼由 k8s 執行 pull 反而就失敗了?
原因是因為 K8S 是透過使用 Container Runtime Interface(CRI)作為介面與容器執行時引擎(container runtime)進行通信。而在我們這個架構,我們的 CRI 是 Containerd,所以要為 Containerd 加入 Registry 的映射。
進入
/etc/containerd
,開啟config.toml
,如果沒有則自行建立。在裡面填入
1
2
3
4
5# Config file is parsed as version 1 by default.
# To use the long form of plugin names set "version = 2"
[plugins.cri.registry.mirrors]
[plugins.cri.registry.mirrors."IP:PORT"]
endpoint = ["http://IP:PORT"]這個用意是指當遇到指定的 IP 和 PORT 的時候,轉成使用
http
去呼叫,而非預設的https
。重啟 containerd
1
sudo systemctl restart containerd
接著刪除原本的 deploy,重新 apply 一次就可以正常拉取 image。
- 標題: 如何處理 Kubernetes 無法 Pull 私有鏡像庫的問題?
- 作者: Larry Lai
- 撰寫于 : 2024-04-24 18:00:00
- 更新于 : 2024-07-17 17:01:39
- 連結: https://redefine.ohevan.com/2024/04/24/k8s-pulling-image-failed/
- 版權宣告: 本作品采用 CC BY-NC-SA 4.0 进行许可。