如何處理 Kubernetes 無法 Pull 私有鏡像庫的問題?

Larry Lai Lv1

私有鏡像庫無法拉取

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
    3
    sudo 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

    1. 利用 docker login 產生的檔案
    1
    2
    3
    kubectl create secret generic regcred \
    --from-file=.dockerconfigjson=autoConf.json \
    --type=kubernetes.io/dockerconfigjson
    1. 自行輸入資訊產生
    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
    22
    apiVersion: 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 name
  • k8s 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 的映射。

  1. 進入/etc/containerd,開啟 config.toml,如果沒有則自行建立。

  2. 在裡面填入

    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

  3. 重啟 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 进行许可。
 留言
此頁目錄
如何處理 Kubernetes 無法 Pull 私有鏡像庫的問題?