排解映像檔提取問題


本頁面說明如何解決 Google Kubernetes Engine (GKE) 中的映像檔提取程序問題。如果您使用圖片串流,請參閱「排解圖片串流問題」一文。本頁內容著重於標準映像檔提取作業。

本頁面適用於應用程式開發人員,可確保應用程式順利部署;也適用於平台管理員和營運人員,可瞭解映像檔提取失敗的根本原因,並驗證平台設定。如要進一步瞭解我們在 Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見的 GKE Enterprise 使用者角色和工作」。

映像檔提取程序是 Kubernetes (因此也是 GKE) 從登錄檔擷取容器映像檔的方式。如果映像檔提取失敗,您可能會發現應用程式速度變慢,或完全無法運作。

如要判斷映像檔提取作業是否導致應用程式無法運作,請參閱本頁內容,找出並瞭解相關錯誤訊息,診斷映像檔提取失敗問題。接著,您將瞭解如何解決下列常見的映像檔提取失敗原因:

  • 驗證設定:叢集缺少存取容器映像檔登錄檔的必要權限。
  • 網路連線:由於 DNS 問題、防火牆規則,或使用網路隔離的叢集缺少網際網路存取權,因此叢集無法連線至登錄檔。
  • 註冊資料庫中找不到映像檔:指定的映像檔名稱或標記不正確、映像檔已刪除,或註冊資料庫無法使用。
  • 效能限制:圖片過大、磁碟 I/O 速度緩慢或網路壅塞,都可能導致提取速度緩慢或逾時。
  • 映像檔架構不相容:映像檔是為與 GKE 節點集區不同的 CPU 架構所建構。
  • 不相容的結構定義版本:您可能使用 containerd 2.0 以上版本搭配 v1 Docker 結構定義,但這類組合不受支援。

如果您已看到特定事件訊息,請在這頁面中搜尋該訊息,然後按照列出的疑難排解步驟操作。如果沒有看到訊息,請依序完成下列各節的步驟。如果問題仍未解決,請與 Cloud Customer Care 團隊聯絡

瞭解映像檔提取作業

開始排解問題前,建議先進一步瞭解圖片的生命週期,以及圖片的代管位置。

映像檔生命週期

建立 Pod 時,kubelet 會收到 Pod 定義,其中包含映像檔的規格。kubelet 需要這個映像檔,才能根據該映像檔執行容器。kubelet 會先檢查容器執行階段,確認映像檔是否存在,再進行映像檔拉取作業。kubelet 也會檢查 Pod 的映像檔提取政策。如果容器執行階段的快取中沒有該映像檔,或映像檔提取政策要求,kubelet 會指示容器執行階段 (containerd) 從登錄檔提取指定映像檔。如果映像檔提取失敗,Pod 中的容器就無法啟動。

成功提取映像檔後,容器執行階段會解壓縮映像檔,為容器建立唯讀的基礎檔案系統。容器執行階段會儲存這個映像檔,只要執行中的容器參照該映像檔,映像檔就會保留。如果沒有執行中的容器參照映像檔,該映像檔就會符合垃圾收集資格,kubelet 最終會移除該映像檔。

圖片代管選項

建議您使用下列其中一個選項來代管圖片:

  • Artifact Registry:Artifact Registry 是 Google 的全代管套件管理工具。Artifact Registry 可與其他 Google Cloud服務緊密整合,並提供精細的存取權控管機制。詳情請參閱 Artifact Registry 說明文件中的「使用容器映像檔」。

  • 自行託管的儲存庫:自行託管的儲存庫可讓您進一步掌控,但您也必須管理儲存庫。如果您有 Artifact Registry 無法滿足的特定法規遵循或安全性需求,請考慮使用這個選項。

診斷映像檔提取失敗問題

如要診斷映像檔提取失敗問題,請按照下列各節的詳細說明進行調查:

  1. 查看 Pod 狀態和事件。
  2. 瞭解狀態的意義。
  3. 使用事件訊息找出映像檔提取失敗的原因。
  4. 查看記錄檔探索工具記錄。

查看 Pod 狀態和事件

為協助您確認映像檔提取作業失敗,GKE 會記錄 Pod 的下列狀態:

  • ImagePullBackOff
  • ErrImagePull
  • ImageInspectError
  • InvalidImageName
  • RegistryUnavailable
  • SignatureValidationFailed

ImagePullBackOffErrImagePull 是最常見的狀態。

除了這些狀態,Kubernetes 事件也有助於找出映像檔提取失敗的原因。

如要確認圖片提取作業是否失敗,請檢查狀態訊息,然後選取下列其中一個選項,讀取事件訊息:

控制台

操作步驟如下:

  1. 前往 Google Cloud 控制台的「Workloads」(工作負載) 頁面。

    前往「Workloads」(工作負載)

  2. 選取要調查的工作負載。如果不確定要檢查哪個工作負載,請查看「狀態」欄。這個資料欄會指出哪些工作負載發生問題。

  3. 在工作負載的「詳細資料」頁面中,找出「代管的 Pod」部分,然後按一下狀態顯示映像檔提取失敗的 Pod 名稱。

  4. 在 Pod 的「Details」(詳細資料) 頁面中,按一下「Events」(事件) 分頁標籤。

  5. 查看表格中的資訊。「訊息」欄會列出 Kubernetes 事件,其中會顯示有關映像檔提取失敗的詳細資訊。「原因」欄會列出 Pod 狀態。

kubectl

操作步驟如下:

  1. 查看 Pod 的狀態:

    kubectl get pods -n NAMESPACE
    

    NAMESPACE 替換為 Pod 執行的命名空間。

    輸出結果會與下列內容相似:

    NAME         READY   STATUS       RESTARTS      AGE
    POD_NAME_1   2/2     Running      0             7d5h
    POD_NAME_2   0/1     ErrImagePull 0             7d5h
    

    Status」欄會指出哪些 Pod 發生映像檔提取失敗。

  2. 查看映像檔提取失敗的 Pod 事件:

    kubectl describe POD_NAME -n NAMESPACE
    

    POD_NAME 替換為您在上一個步驟中識別的 Pod 名稱。

    Events」部分會顯示更多資訊,說明圖片提取失敗的原因。

    輸出結果會與下列內容相似:

    ...
    Events:
      Type    Reason    Age               From           Message
      ----    ------    ----              ----           -------
      Warning  Failed   5m (x4 over 7m)   kubelet, NODE  Failed to pull image "IMAGE_ADDRESS": rpc error: code = Unknown desc = Error response from daemon: repository IMAGE_ADDRESS not found
      Warning  Failed   5m (x4 over 7m)   kubelet, NODE  Error: ErrImagePull
      Normal   BackOff  5m (x6 over 7m)   kubelet, NODE  Back-off pulling image "IMAGE_ADDRESS"
      Warning  Failed   2m (x20 over 7m)  kubelet, NODE  Error: ImagePullBackOff
    

    在這個輸出內容中,IMAGE_ADDRESS 是圖片的完整地址。例如:us-west1-docker.pkg.dev/my-project/my-repo/test:staging

瞭解狀態的意義

如要進一步瞭解不同狀態的意義,請參閱下列說明:

  • ImagePullBackOff:kubelet 無法提取映像檔,但會持續重試,延遲時間 (或退避) 最長可達五分鐘。
  • ErrImagePull:圖片提取程序發生一般錯誤,無法復原。
  • ImageInspectError:容器執行階段在嘗試檢查容器映像檔時發生問題。
  • InvalidImageName:Pod 定義中指定的容器映像檔名稱無效。
  • RegistryUnavailable:無法存取登錄。這通常是網路連線問題。
  • SignatureValidationFailed:無法驗證容器映像檔的數位簽章。

使用事件訊息找出映像檔提取失敗的原因

下表列出與映像檔提取失敗相關的事件訊息,以及發現這些訊息時應採取的疑難排解步驟。

與映像檔提取失敗相關的訊息通常有下列前置字元:

Failed to pull image "IMAGE_ADDRESS": rpc error: code = CODE = failed to pull and unpack image "IMAGE_ADDRESS": failed to resolve reference "IMAGE_ADDRESS":

這則訊息包含下列值:

  • IMAGE_ADDRESS:圖片的完整地址。例如:us-west1-docker.pkg.dev/my-project/my-repo/test:staging
  • CODE:與記錄訊息相關聯的錯誤碼。例如 NotFoundUnknown

部分映像檔提取失敗的原因沒有相關的事件訊息。如果沒有看到下表中的任何事件訊息,但仍遇到映像檔提取問題,建議您繼續閱讀本頁的其餘內容。

事件訊息 詳細疑難排解
驗證
  • Failed to authorize: failed to fetch oauth token: unexpected status: 403 Forbidden
  • Pulling from host HOST_NAME failed with status code: 403 Forbidden
  • Failed to authorize: failed to fetch oauth token: unexpected status: 401 Unauthorized
  • Unexpected status code [manifests 1.0]: 401 Unauthorized

網路連線
  • Failed to do request: Head "IMAGE_ADDRESS": dial tcp: lookup gcr.io on REGISTRY_IP_ADDRESS: server misbehaving
  • Failed to start Download and install k8s binaries and configurations
  • Failed to do request: Head "IMAGE_ADDRESS": dial tcp REGISTRY_IP_ADDRESS: i/o timeout
找不到映像檔
  • "IMAGE_ADDRESS": not found
  • Failed to copy: httpReadSeeker: failed open: could not fetch content descriptor sha256:SHA_HASH (application/vnd.docker.container.image.v1+json) from remote: not found
圖片逾時
  • Unknown desc = context canceled
結構定義不相容
  • Failed to get converter for "IMAGE_ADDRESS": Pulling Schema 1 images have been deprecated and disabled by default since containerd v2.0. As a workaround you may set an environment variable `CONTAINERD_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE=1`, but this will be completely removed in containerd v2.1.

查看記錄檔探索工具記錄

如要檢查過往的映像檔提取事件,或將映像檔提取失敗情形與其他元件活動建立關聯,請使用記錄檔探索工具查看記錄:

  1. 前往 Google Cloud 控制台的「Logs Explorer」頁面。

    前往記錄檔探索工具

  2. 在查詢窗格中,輸入下列查詢:

    log_id("events")
    resource.type="k8s_pod"
    resource.labels.cluster_name="CLUSTER_NAME"
    jsonPayload.message=~"Failed to pull image"
    

    CLUSTER_NAME 換成 Pod 執行所在的叢集名稱,該 Pod 發生映像檔提取錯誤。

  3. 按一下「執行查詢」並查看結果。

檢查驗證設定

以下章節說明如何確認 GKE 環境的驗證設定正確無誤,可從存放區提取映像檔。

如要檢查是否因驗證問題導致映像檔提取問題,請執行下列章節詳述的調查:

  1. 確認您有權存取圖片。
  2. 驗證 imagePullSecret 設定和 Deployment 規格。
  3. 確認節點服務帳戶是否處於啟用狀態。
  4. 確認節點的存取範圍是否適用於私人 Artifact Registry 存放區
  5. 確認 VPC Service Controls 設定,以便存取 Artifact Registry。

確認圖片存取權

如果遇到 403 Forbidden 映像檔提取錯誤,請確認必要元件可以存取容器映像檔。

驗證及套用必要角色以授予所需存取權的方法,取決於儲存映像檔的存放區類型。如要驗證並授予存取權,請選取下列其中一個選項:

Artifact Registry

如果您使用 imagePullSecret,連結至 Secret 的服務帳戶必須具備存放區的讀取權限。否則,節點集區的服務帳戶需要權限。

  1. 請按照身分與存取權管理說明文件中的操作說明,查看指派給服務帳戶的角色
  2. 如果服務帳戶沒有 Artifact Registry 讀者 (roles/artifactregistry.reader) IAM 角色,請授予該角色:

    gcloud artifacts repositories add-iam-policy-binding REPOSITORY_NAME \
        --location=REPOSITORY_LOCATION \
        --member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
        --role="roles/artifactregistry.reader"
    

    更改下列內容:

    • REPOSITORY_NAME:Artifact Registry 存放區的名稱。
    • REPOSITORY_LOCATION:Artifact Registry 存放區的區域
    • SERVICE_ACCOUNT_EMAIL:必要服務帳戶的電子郵件地址。如果您不知道地址,請使用 gcloud iam service-accounts list 指令列出專案中的所有服務帳戶電子郵件地址。

Container Registry

如果您使用 imagePullSecret,與 Secret 連結的服務帳戶必須具備存放區的讀取權限。否則,節點集區的服務帳戶需要權限。

  1. 請按照 IAM 說明文件中的操作說明,查看指派給服務帳戶的角色
  2. 如果服務帳戶沒有「Storage 物件檢視者」(roles/storage.objectViewer) IAM 角色,請授予該角色,讓服務帳戶可以從 bucket 讀取資料:

    gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
        --member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
        --role=roles/storage.objectViewer
    

    更改下列內容:

    • SERVICE_ACCOUNT_EMAIL:必要服務帳戶的電子郵件地址。您可以使用 gcloud iam service-accounts list 指令,列出專案中的所有服務帳戶。
    • BUCKET_NAME:包含圖片的 Cloud Storage bucket 名稱。您可以使用 gcloud storage ls 指令,列出專案中的所有值區。

如果登錄管理員在 Artifact Registry 中設定 gcr.io 存放區,用於儲存 gcr.io 網域的映像檔 (而非 Container Registry),您必須授予 Artifact Registry 讀取權限,而非 Container Registry。

自行託管的登錄檔

視您設定自行代管登錄檔的方式而定,您可能需要金鑰、憑證或兩者才能存取映像檔。

如果您使用金鑰,請使用 imagePullSecret。imagePullSecret 可安全地為叢集提供存取自代管登錄檔所需的憑證。如需設定 imagePullSecret 的範例,請參閱 Kubernetes 說明文件中的「從私人登錄檔提取映像檔」。

如要確保與登錄檔的 HTTPS 連線安全無虞,您可能還需要憑證,用來驗證與遠端伺服器的連線完整性。建議您使用 Secret Manager 管理自己的自簽憑證授權單位。詳情請參閱「使用私人 CA 憑證存取私人登錄檔」。

驗證 imagePullSecret 設定和 Deployment 規格

如果您使用 imagePullSecret,請務必建立保存用於提取映像檔的驗證憑證的 Secret,並確保所有 Deployment 都指定您定義的 Secret。詳情請參閱 Kubernetes 說明文件的「在 Pod 上指定 imagePullSecrets」。

確認節點服務帳戶是否處於啟用狀態

如果遇到 401 Unauthorized 映像檔提取錯誤,請確認節點服務帳戶是否處於啟用狀態。即使權限設定正確,停用的帳戶仍會顯示這項錯誤。如要驗證節點服務帳戶的有效狀態,請選取下列其中一個選項:

控制台

  1. 找出節點使用的服務帳戶名稱:

    1. 前往 Google Cloud 控制台的「Clusters」(叢集) 頁面。

      前往「Clusters」(叢集) 頁面

    2. 在叢集清單中,按一下要檢查的叢集名稱。

    3. 找出節點服務帳戶的名稱。

      • 如為 Autopilot 模式叢集,請在「安全性」部分中,找出「服務帳戶」欄位。
      • 如果是 Standard 模式叢集,請執行下列操作:
      1. 按一下「Nodes」(節點) 分頁標籤。
      2. 在「節點集區」表格中,按一下節點集區名稱。「節點集區詳細資料」頁面隨即開啟。
      3. 在「安全性」部分,找到「服務帳戶」欄位。

      如果「服務帳戶」欄位中的值為 default,節點就會使用 Compute Engine 預設服務帳戶。如果這個欄位的值「不是」default,表示節點使用自訂服務帳戶。

  2. 檢查節點服務帳戶是否已停用:

    1. 前往 Google Cloud 控制台的「Service accounts」(服務帳戶) 頁面。

      前往「Service accounts」(服務帳戶)

    2. 選取專案。

    3. 找出您在上一個步驟中識別的服務帳戶名稱。

    4. 查看該帳戶的「狀態」欄。如果服務帳戶已停用,帳戶狀態會顯示為 Disabled

gcloud

  1. 找出節點使用的服務帳戶名稱:

    • 如果是 Autopilot 模式叢集,請執行下列指令:
    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --flatten=autoscaling.autoprovisioningNodePoolDefaults.serviceAccount
    
    • 如果是標準模式叢集,請執行下列指令:
    gcloud container clusters describe CLUSTER_NAME \
        --location=LOCATION \
        --format="table(nodePools.name,nodePools.config.serviceAccount)"
    

    如果輸出內容為 default,表示節點使用 Compute Engine 預設服務帳戶。如果輸出不是 default,表示節點使用自訂服務帳戶。

  2. 檢查節點服務帳戶是否已停用:

    gcloud iam service-accounts list --filter="email:SERVICE_ACCOUNT_NAME AND disabled:true" \
    --project=PROJECT_ID
    

    如果指令傳回輸出內容,表示服務帳戶已停用。

如果服務帳戶已停用,請啟用節點服務帳戶

確認節點的存取權範圍是否適用於私人 Artifact Registry 存放區

如果將容器映像檔儲存在私人 Artifact Registry 存放區,節點可能沒有正確的存取範圍。發生這種情況時,您可能會注意到 401 Unauthorized 映像檔提取錯誤。

如要驗證存取範圍並視需要授予存取權,請按照下列步驟操作:

  1. 找出執行 Pod 的節點:

    kubectl describe pod POD_NAME | grep "Node:"
    

    POD_NAME 替換為發生映像檔提取失敗的 Pod 名稱。

  2. 確認上一個步驟中識別的節點具有正確的儲存空間範圍:

    gcloud compute instances describe NODE_NAME \
        --zone="COMPUTE_ZONE" \
        --format="flattened(serviceAccounts[].scopes)"
    

    更改下列內容:

    • NODE_NAME:您在上一個步驟中識別的節點名稱。
    • COMPUTE_ZONE:節點所屬的 Compute Engine 區域

    輸出內容應包含下列至少一個存取範圍:

    • serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/devstorage.read_only
    • serviceAccounts[0].scopes[0]: https://www.googleapis.com/auth/cloud-platform

    如果節點不包含其中一個範圍,映像檔提取作業就會失敗。

  3. 重新建立節點所屬的節點集區,並提供足夠的範圍。 由於您無法修改現有節點,因此必須使用正確的範圍重新建立節點。

    建議您使用 gke-default 範圍建立節點集區。這個範圍可存取下列範圍:

    • https://www.googleapis.com/auth/devstorage.read_only
    • https://www.googleapis.com/auth/logging.write
    • https://www.googleapis.com/auth/monitoring
    • https://www.googleapis.com/auth/service.management.readonly
    • https://www.googleapis.com/auth/servicecontrol
    • https://www.googleapis.com/auth/trace.append

    如果 gke-default 範圍不適用,請授予節點集 devstorage.read_only 範圍,這樣就能存取唯讀資料。

    gke-default

    使用 gke-default 範圍建立節點集區:

    gcloud container node-pools create NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION \
        --scopes="gke-default"
    

    更改下列內容:

    • NODE_POOL_NAME:新節點集區的名稱。
    • CLUSTER_NAME:現有叢集的名稱。
    • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。為地區叢集提供地區,或為區域叢集提供區域。

    devstorage.read_only

    使用 devstorage.read_only 範圍建立節點集區:

    gcloud container node-pools create NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION \
        --scopes="https://www.googleapis.com/auth/devstorage.read_only"
    

    更改下列內容:

    • NODE_POOL_NAME:新節點集區的名稱。
    • CLUSTER_NAME:現有叢集的名稱。
    • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。為地區叢集提供地區,或為區域叢集提供區域。

確認 VPC Service Controls 設定,以便存取 Artifact Registry

如果您使用 VPC Service Controls,請確認服務範圍允許存取 Artifact Registry。詳情請參閱 Artifact Registry 說明文件中的「保護服務範圍內的存放區」。

調查網路連線

在提取映像檔期間,網路連線可能會導致程序無法完成。

如要檢查網路連線問題是否導致映像檔提取問題,請執行下列章節中詳述的調查:

  1. 調查 DNS 解析。
  2. 調查防火牆設定。
  3. 調查外部登錄端點的網際網路連線。
  4. 調查與 Google API 的連線是否逾時。

調查 DNS 解析

如果看到 server misbehaving 圖片提取錯誤,可能是 DNS 解析導致圖片提取失敗。

如要調查 DNS 解析問題,請嘗試下列解決方案:

  1. 排解中繼資料伺服器問題。 節點的中繼資料伺服器會解析所有 DNS 查詢。如果這個伺服器發生任何問題,可能會中斷名稱解析作業,導致無法連線至存放區,並造成映像檔提取作業失敗。
  2. 如果您使用 Cloud DNS 進行 DNS 解析,請確保 Cloud DNS 代管不公開區域、轉送區域、對等互連區域和回應政策已正確設定。如果這些區域設定錯誤,可能會導致 DNS 無法解析。如要進一步瞭解 Cloud DNS,請參閱「將 Cloud DNS 用於 GKE」。如需在 GKE 中排解 Cloud DNS 問題的建議,請參閱「在 GKE 中排解 Cloud DNS 問題」。
  3. 如果您使用 kube-dns 進行 DNS 解析,請確認 kube-dns 運作正常。如需排解 kube-dns 問題的建議,請參閱「排解 GKE 中的 kube-dns 問題」。
  4. 如果叢集的節點沒有外部 IP 位址 (使用網路隔離時很常見),請在叢集使用的子網路上啟用私人 Google 存取權,並確保符合網路需求。如果您使用 Cloud NAT, Google Cloud 系統會自動啟用私人 Google 存取權。

調查防火牆設定

如果防火牆問題導致映像檔提取失敗,您可能會看到以下錯誤訊息:

Failed to start Download and install k8s binaries and configurations

診斷防火牆問題

如果您使用標準叢集,並想確認防火牆問題是否導致映像檔提取問題,請按照下列步驟操作:

  1. 使用 SSH 連線至發生問題的節點:

    gcloud compute ssh NODE_NAME --zone=ZONE_NAME
    

    更改下列內容:

  2. kube-node-installation.servicekube-node-configuration.service 服務的最新記錄傳送至名為 kube-node-installation_status.txtkube-node-configuration_status.txt 的文字檔:

    systemctl status kube-node-installation.service > kube-node-installation_status.txt
    systemctl status kube-node-configuration.service > kube-node-configuration_status.txt
    

    如果這些記錄未包含圖片提取失敗時的資訊,請產生完整的記錄副本:

    sudo journalctl -u kube-node-installation.service > kube-node-installation_logs.txt
    sudo journalctl -u kube-node-configuration.service > kube-node-configuration_logs.txt
    
  3. 查看 kube-node-installation_status.txtkube-node-configuration_status.txt 的內容,以及檔案。如果輸出內容顯示 i/o timeout,問題可能出在防火牆。

解決防火牆設定問題

如要解決防火牆問題,請嘗試下列方法:

  1. 找出並解決任何封鎖網路流量的防火牆規則。 舉例來說,您可能有一項規則會封鎖前往儲存映像檔的登錄檔流量。

    1. 存取虛擬私有雲流量記錄:

      1. 前往 Google Cloud 控制台的「Logs Explorer」頁面。

        前往記錄檔探索工具

      2. 在查詢窗格中,輸入下列查詢:

        resource.type="gce_subnetwork"
        logName="projects/PROJECT_ID/logs/[compute.googleapis.com%2Fvpc_flows](http://compute.googleapis.com%2Fvpc_flows)"
        resource.labels.subnetwork_name="SUBNET_NAME",
        

        更改下列內容:

        • PROJECT_ID:您的 Google Cloud 專案 ID。
        • SUBNET_NAME:子網路名稱。

        詳情請參閱虛擬私有雲說明文件中的「使用查詢存取流量記錄檔」。

    2. 如果發現任何防火牆規則封鎖了必要流量,請更新這些規則

  2. 如果叢集的節點沒有外部 IP 位址 (使用網路隔離時很常見),請在叢集使用的子網路上啟用私人 Google 存取權,並確保符合網路需求。如果您使用 Cloud NAT, Google Cloud 系統會自動啟用私人 Google 存取權。

調查外部登錄端點的網際網路連線

如果網路設定將流量導向外部登錄檔端點,該端點可能無法連上網際網路。如果端點缺少存取權,映像檔提取作業可能會失敗,並顯示 i/o timeout 映像檔提取錯誤。

如要檢查從外部登錄端點到登錄的網路連線,請使用 pingtraceroute

ping REGISTRY_ENDPOINT

traceroute REGISTRY_ENDPOINT

REGISTRY_ENDPOINT 替換為登錄端點。這個值可以是主機名稱或 IP 位址。

如果發現連線錯誤,請檢查虛擬私有雲路徑:

  1. 前往 Google Cloud 控制台的「Routes」(路徑)

    前往「Routes」(路徑)

  2. 查看「優先順序」欄,確認優先順序最高的路徑會前往可存取登錄檔的來源。值越小,優先順序越高。

調查與 Google API 的連線是否逾時

如果您使用網路隔離,連線至 Google API 和服務時可能會發生逾時錯誤,導致 i/o timeout 映像檔提取錯誤。

發生這項錯誤的原因是,節點嘗試從登錄檔提取映像檔時,無法連線至下列其中一個 API:

  • containerregistry.googleapis.com
  • artifactregistry.googleapis.com

如要確保可以連線至必要 API,請嘗試下列解決方案:

  1. 啟用「私人 Google 存取權」。沒有外部 IP 位址的節點需要私人 Google 存取權,才能存取 Google API 和服務的外部 IP 位址。
  2. 使用支援的網域
  3. 查看防火牆政策:

    1. 前往 Google Cloud 控制台的「防火牆政策」頁面。

      前往「Firewall policies」(防火牆政策) 頁面

    2. 確認是否有任何規則封鎖通訊埠 443 上前往 199.36.153.4/30199.36.153.8/30所選網域用於 Google API 和服務的任何 IP 位址範圍的輸出 TCP 流量。IP 位址範圍 199.36.153.4/30199.36.153.8/30 分別用於私人 Google 存取權和受限 Google 存取權。通訊埠 443 上前往這些範圍的 TCP 流量,是用於存取 Google API 和服務。

      如果發現任何這類規則,請建立輸出防火牆規則,允許這類流量。

  4. 如果您使用 Artifact Registry,請確認您的環境符合規定,才能將 Artifact Registry 與網路隔離功能搭配使用。

  5. 確認虛擬 IP 位址 (VIP) (199.36.153.4/30199.36.153.8/30) 已設定虛擬私有雲路徑:

    1. 在 Google Cloud 控制台中,前往 VPC 網路。

      前往「VPC networks」(虛擬私有雲網路)

    2. 在「Name」(名稱) 欄中,按一下「default」(預設)

    3. 在 VPC 網路詳細資料頁面中,按一下「路徑」分頁標籤。

    4. 查看路線表。

      如果虛擬私有雲網路包含預設路徑 (目的地 0.0.0.0/0::0/0),且該路徑的下一個躍點為預設網際網路閘道 (網路預設),請使用該路徑,讓 VIP 存取 Google API 和服務。

      如果您將預設路徑替換為下一個躍點不是預設網際網路閘道的自訂路徑,請使用自訂路徑,以符合 Google API 和服務的轉送需求。

調查 kubelet 無法找到映像檔的原因

如果 kubelet 找不到映像檔,您可能會看到 image not found 錯誤,並發生映像檔提取失敗的情況。

如要協助 kubelet 尋找映像檔,請嘗試下列解決方案:

  1. 檢查 Pod 的資訊清單,確認映像檔名稱和映像檔標記的拼字正確無誤。如果出現任何拼字或格式錯誤,系統就會無法提取圖片。
  2. 確認映像檔仍存在於您儲存的登錄檔中。 如果映像檔有完整的註冊資料庫路徑,請到您使用的 Docker 註冊資料庫中確認有該映像檔。若您僅提供映像檔名稱,請檢查 Docker Hub 註冊資料庫。
  3. 如果叢集使用網路隔離,請嘗試下列解決方法:
    1. 啟用私人 Google 存取權
    2. 確認服務周邊設定正確無誤

調查映像檔提取逾時或提取速度緩慢的原因

如果 GKE 工作負載使用非常大的映像檔,映像檔提取作業可能會逾時,並導致 context cancelled 錯誤。雖然圖片沒有明確的大小限制,但 context cancelled 錯誤通常表示圖片大小是造成問題的原因。

您也可能會發現圖片提取作業不會失敗,但所需時間比平常長得多。如要瞭解一般映像檔提取時間的基準,請查看 Successfully pulled image 記錄項目。舉例來說,下列記錄訊息顯示圖片提取作業耗時 30.313387996 秒:

Successfully pulled image "IMAGE_ADDRESS" in 30.313387996s.

逾時和圖片提取速度緩慢的原因有許多相同之處。如要解決這些問題,請嘗試下列解決方案:

  1. 檢查服務中斷情形。如果只有在特定時間範圍內發生這個問題,請檢查是否有任何 Google Cloud 服務中斷
  2. 檢查磁碟效能。磁碟 I/O 速度緩慢可能會導致映像檔提取時間變長。 建議升級至搭載 SSD 的永久磁碟 (pd-ssd),或使用較大的磁碟來提升效能。如需更多建議,請參閱「排解磁碟效能問題」。
  3. 縮小圖片。舉例來說,您或許可以將部分資料從容器映像檔移至 Persistent Volumes。
  4. 善用映像檔快取功能,縮短 Pod 啟動時間。 GKE 會在節點上快取映像檔。提取映像檔時,容器執行階段只會下載快取中尚未存在的層。為盡量發揮這項快取機制的效用,並縮短映像檔提取時間,請調整 Dockerfile 的結構,將映像檔中經常變更的部分 (例如應用程式程式碼) 放在檔案結尾,並使用較小的基礎映像檔。
  5. 啟用映像檔串流。這項功能可加快 Pod 啟動速度和映像檔下載速度。詳情請參閱「使用映像檔串流來提取容器映像檔」。
  6. 請確認預設服務帳戶具備必要權限。修改指派給預設服務帳戶的角色可能會中斷工作負載,包括映像檔提取作業。如需更多建議,請參閱「找出缺少重要權限的節點服務帳戶叢集」。
  7. 檢查 Proxy 設定。如果 GKE 叢集與非 Google 管理的存放區之間有 Proxy,可能會導致延遲。
  8. 檢查第三方軟體。部分第三方軟體可能會干擾映像檔提取作業。調查最近安裝的工具是否可能造成衝突。

確認圖片資訊清單使用正確的架構

如果您嘗試提取的映像檔是為不同於節點集區所用的電腦架構而建構,映像檔提取作業就會失敗。

如要確認映像檔資訊清單是否使用正確的架構,請按照下列步驟操作:

  1. 如要確認映像檔使用的架構,請查看映像檔的資訊清單。舉例來說,如要查看 Docker 映像檔,請執行下列指令:

    docker manifest inspect --verbose IMAGE_NAME
    

    IMAGE_NAME 替換為要查看的圖片名稱。

    輸出結果會與下列內容相似:

    ...
    "Platform": {
              "architecture": "amd64",
              "os": "linux"
      }
    ...
    

    在本範例中,支援的架構為 amd64

  2. 查看節點集區使用的機器類型:

    gcloud container node-pools list --cluster CLUSTER_NAME --location CONTROL_PLANE_LOCATION
    

    更改下列內容:

    • CLUSTER_NAME:發生映像檔提取錯誤的 Pod 執行所在叢集名稱。
    • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。為地區叢集提供地區,或為區域叢集提供區域。

    輸出結果會與下列內容相似:

    NAME: example-node-pool
    MACHINE_TYPE: e2-standard-2
    DISK_SIZE_GB: 100
    NODE_VERSION: 1.30.8-gke.1162000
    

    在本例中,機器類型為 e2-standard-2

  3. 比較 architectureMACHINE_TYPE 欄位中的值,並確認兩個值都相容。舉例來說,如果映像檔的架構為 amd64,則會與使用 e2-standard-2 做為機器類型的節點集區相容。不過,如果節點集區使用 t2a-standard-1 (以 Arm 為基礎的機器類型),這個機器類型就會導致失敗。

  4. 如果映像檔架構與節點集區的機型不相容,請重建映像檔,以指定所需架構。

確認圖片結構定義版本是否相容

在 GKE 1.33 中,containerd 2.0 已移除對 Docker 結構定義 1 映像檔的支援,因此使用 containerd 2.0 搭配 Docker 結構定義 1 映像檔會導致映像檔提取作業失敗。如果這個問題導致映像檔提取失敗,您可能會看到下列錯誤訊息:

Failed to get converter for "IMAGE_ADDRESS": Pulling Schema 1 images have been deprecated and disabled by default since containerd v2.0. As a workaround you may set an environment variable `CONTAINERD_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE=1`, but this will be completely removed in containerd v2.1.

如要解決這個問題,請按照「從 Docker 結構定義 1 映像檔遷移」一文中的操作說明,找出並遷移這些映像檔。

後續步驟