為何映像檔無法從登錄取回時發生 ImagePullBackOff 或授權錯誤?

虛擬私有雲 經典基礎架構

當您部署工作負載從 IBM Cloud Container Registry 取回映像檔時,您的 Pod 會失敗並處於 ImagePullBackOff 狀態。

kubectl get pods
NAME         READY     STATUS             RESTARTS   AGE
<pod_name>   0/1       ImagePullBackOff   0          2m

當您說明 Pod 時,您會看到類似下列的鑑別錯誤。

kubectl describe pod <pod_name>
Failed to pull image "<region>.icr.io/<namespace>/<image>:<tag>" ... unauthorized: authentication required
Failed to pull image "<region>.icr.io/<namespace>/<image>:<tag>" ... 401 Unauthorized
...
Failed to pull image "<image>:<tag>" ... Manifest for <image>:<tag> not found

您的群集使用儲存於 影像拉取秘訣 中的 API 金鑰,授權群集從 IBM Cloud Container Registry 拉取影像,或具有特定標籤的影像不存在於儲存庫中。

依預設,新叢集具有使用 API 金鑰的映像檔取回密碼,以讓叢集可從已部署至 icr.io Kubernetes 名稱空間之容器的任何地區 default 登錄中取回映像檔。

  1. 驗證您在部署 YAML 檔案中使用映像檔的正確名稱和標籤。

    ibmcloud cr images
    
  2. 檢查取回資料流量及儲存空間配額。 如果達到限制,請釋放使用的儲存空間,或要求登錄管理者增加配額。

    ibmcloud cr quota
    
  3. 取得失敗 Pod 的 Pod 配置檔,並尋找 imagePullSecrets 區段。

    kubectl get pod <pod_name> -o yaml
    

    輸出範例

    ...
    imagePullSecrets:
    - name: all-icr-io
    ...
    
  4. 如果未列出任何映像檔取回密碼,請在名稱空間中設定映像檔取回密碼。

    1. 驗證 default 名稱空間是否具有用於要使用的每個地區登錄的 icr-io 映像檔取回密碼。 如果命名空間中未列出任何 icr-io 密鑰, 請使用 ibmcloud ks cluster pull-secret apply --cluster <cluster_name_or_ID> 指令在 default 命名空間中建立映像拉取密鑰。
      kubectl get secrets -n default | grep "icr-io"
      
    2. 將 default Kubernetes 命名空間中的 all-icr-io 映像拉取密鑰,複製到您要部署工作負載的命名空間中。
    3. 將映像檔取回密碼新增至此 Kubernetes 名稱空間的服務帳戶,以便該名稱空間中的所有 Pod 都能使用映像檔取回密碼認證。
  5. 如果 Pod 中列出映像檔取回密碼,請確定用於存取 IBM Cloud Container Registry 的認證類型。

使用 API 金鑰的影像拉取密鑰疑難排解

如果您的 Pod 配置具有使用 API 金鑰的映像檔取回密碼,請檢查是否正確設定 API 金鑰認證。

下列步驟假設 API 金鑰會儲存服務 ID 的認證。 如果您將映像檔取回密碼設為使用個別使用者的 API 金鑰,則必須驗證使用者的 IBM Cloud IAM 許可權及認證。

  1. 檢閱說明,以尋找 API 金鑰針對映像檔取回密碼所使用的服務 ID。 隨叢集建立的服務識別碼名為 cluster-<cluster_ID>,並用於 default Kubernetes 命名空間中。 如果您建立另一個服務 ID 來存取不同的 Kubernetes 名稱空間,或修改 IBM Cloud IAM 許可權,則要自訂說明。

    ibmcloud iam service-ids
    

    輸出範例

    UUID                Name               Created At              Last Updated            Description                                                                                                                                                                                         Locked
    ServiceId-aa11...   <service_ID_name>  2019-02-01T19:01+0000   2019-02-01T19:01+0000   ID for <cluster_name>                                                                                                                                         false
    ServiceId-bb22...   <service_ID_name>  2019-02-01T19:01+0000   2019-02-01T19:01+0000   Service ID for IBM Cloud Container Registry in Kubernetes cluster <cluster_name> namespace <namespace>                                                                                                                                         false
    
  2. 請確認該服務 ID 至少已獲指派一個「IBM Cloud」IAM 角色 讀者 服務存取角色政策適用於 IBM Cloud Container Registry。 如果服務 ID 沒有「Reader」服務存取角色,請編輯 IAM 政策。 如果原則正確,請繼續下一步,以查看認證是否有效。

    ibmcloud iam service-policies <service_ID_name>
    

    輸出範例

    Policy ID:   a111a111-b22b-333c-d4dd-e555555555e5
    Roles:       Reader
    Resources:
                  Service Name       container-registry
                  Service Instance
                  Region
                  Resource Type      namespace
                  Resource           <registry_namespace>
    
  3. 檢查映像檔取回密碼認證是否有效。

    1. 取得映像檔取回密碼配置。 如果該 Pod 不在 default 命名空間中,請加入 -n 選項。

      kubectl get secret <image_pull_secret_name> -o yaml [-n <namespace>]
      
    2. 在輸出中,複製 .dockerconfigjson 欄位的 base64 編碼值。

      apiVersion: v1
      kind: Secret
      data:
        .dockerconfigjson: eyJyZWdp...==
      ...
      
    3. 解碼 base64 字串。 例如,在 OS X 上,您可以執行下列指令。

      echo -n "<base64_string>" | base64 --decode
      

      輸出範例

      {"auths":{"<region>.icr.io":{"username":"iamapikey","password":"<password_string>","email":"<name@abc.com>","auth":"<auth_string>"}}}
      
    4. 比較映像檔取回密碼地區登錄網域名稱與您在容器映像檔中指定的網域名稱。 依預設,對於在 default Kubernetes 名稱空間中執行的容器,新叢集具有其中每個地區登錄網域名稱的映像檔取回密碼。 不過,如果您修改了預設值,或使用不同的 Kubernetes 名稱空間,則可能沒有地區登錄的映像檔取回密碼。 針對地區登錄網域名稱,複製映像檔取回密碼。

    5. 從您的本端機器,使用映像檔取回密碼中的 username 及 password 來登入登錄。 如果您無法登入,可能需要修正服務 ID。

      docker login -u iamapikey -p <password_string> <region>.icr.io
      
      1. 針對在 default Kubernetes 名稱空間中執行的容器,重建其叢集服務 ID、IBM Cloud IAM 原則、API 金鑰及映像檔取回密碼。
        ibmcloud ks cluster pull-secret apply --cluster <cluster_name_or_ID>
        
      2. 在 default Kubernetes 名稱空間中,重建部署。 如果您仍看到授權錯誤訊息,請使用新的映像檔取回密碼,重複步驟 1-5。 如果仍然無法登入,請 開啟 IBM Cloud 支援案例。
    6. 如果登入成功,請在本端取回映像檔。 如果指令失敗且發生 access denied 錯誤,則登錄帳戶所在的 IBM Cloud 帳戶不同於叢集所在的帳戶。 建立映像檔取回密碼以在其他帳戶中存取映像檔。 如果您能將圖片下載到本地電腦,表示您的 API 金鑰擁有正確的權限,但您在叢集中的 API 設定有誤。

      docker pull <region>icr.io/<namespace>/<image>:<tag>
      
    7. 請檢查是否直接從部署或從部署使用的服務帳戶參照取回密碼。 如果您仍然無法解決問題,請 聯絡支援中心。