將節點遷移至 containerd 2

Google Kubernetes Engine (GKE) 叢集會使用 containerd 節點映像檔,所有執行 1.24 以上版本的 worker 節點都會使用這個映像檔。工作節點會根據作業系統和 GKE 子版本,使用特定版本的 containerd:

  • Container-Optimized OS 和 Ubuntu 節點 (Linux):
    • 如果 Linux 節點執行 GKE 1.32 以下版本,並使用 containerd 節點映像檔,則會使用 containerd 1.7 以下版本。
    • 執行 GKE 1.33 的 Linux 節點會使用 containerd 2.0。
  • Windows Server 節點:
    • 如果 Windows Server 節點執行的是 GKE 1.34 以下版本,且使用 containerd 節點映像檔,則會使用 containerd 1.7 以下版本。
    • 執行 GKE 1.35 的 Windows Server 節點會使用 containerd 2.0。

將 GKE 節點升級至對應的 GKE 子版本時,節點會從使用 containerd 1.7 遷移至新的主要版本 containerd 2.0。您無法變更 GKE 版本使用的 containerd 版本。

如果您確定工作負載在 containerd 2 上能正常運作,可以略過這個頁面。

GKE 如何轉換至 containerd 2

請參閱下列時間表,瞭解 GKE 如何將現有叢集轉換為使用 containerd 2:

  • 對於 Linux 節點 (1.32 版) 和 Windows Server 節點 (1.34 版),GKE 使用 containerd 1.7。containerd 1.7 已淘汰 Docker 結構定義 1 映像檔和 Container Runtime Interface (CRI) v1alpha2 API。如要瞭解先前版本中已淘汰的其他功能,請參閱「已淘汰的設定屬性」。
  • 對於 1.33 版的 Linux 節點和 1.35 版的 Windows Server 節點, GKE 使用 containerd 2.0,因此不再支援 Docker 結構定義 1 映像檔和 CRI v1alpha2 API。
  • CRI 外掛程式中的下列 containerd 設定屬性已淘汰,並將在 containerd 2.4 以上版本中移除 (GKE 版本尚未公布):registry.auths、registry.configs、registry.mirrors。不過,containerd 2.0 已移除 registry.configs.tls。

如要瞭解自動升級至後續子版本的大約時間,請參閱「預估發布時間表 (發布管道)」。

遷移至 containerd 2 的影響

請參閱下節,瞭解這項轉換對 containerd 2 的影響。

已暫停自動升級

GKE 會視叢集目前的子版本,以及叢集中的節點是 Linux 節點還是 Windows Server 節點,以不同方式暫停自動升級。

已暫停 Linux 節點的自動升級

如果 GKE 偵測到叢集使用已淘汰的功能,就會暫停 Linux 節點叢集的自動升級程序,避免升級至 1.33 版。不過,如果叢集節點使用這些功能,建議您建立維護排除項目,防止叢集升級。如果 GKE 未偵測到叢集用量,維護作業排除時段可確保叢集不會升級。

從使用這些功能遷移後,如果符合下列條件,GKE 會繼續自動次要升級至 1.33:

  • GKE 在 14 天內未偵測到使用已淘汰的功能,或是已淘汰的 CRI registry.configs 屬性在 3 天內未偵測到使用情況。
  • 1.33 是叢集的自動升級目標。
  • 沒有其他阻礙因素。詳情請參閱「自動升級的時間」。

您也可以手動升級叢集。

暫停 Windows Server 節點的自動升級作業

無論叢集是否使用已淘汰的功能,只要叢集含有 Windows Server 節點,GKE 就會暫停自動升級至 1.35 版。GKE 無法偵測 Windows Server 節點是否使用已淘汰的功能。

如要將含有 Windows Server 節點的叢集升級至 1.35 版,請先按照說明從已淘汰的功能遷移。按照這些操作說明完成後,即可手動將叢集升級至 1.35 版。

支援服務終止日期,以及未做好遷移準備的影響

GKE 會暫停自動升級,直到標準支援期結束為止。如果叢集已註冊至延長版,節點可繼續使用該版本,直到延長版支援服務結束為止。如要進一步瞭解支援終止後的自動節點升級作業,請參閱「支援終止後的自動升級作業」。

如果您未從這些功能遷移,當 1.32 (適用於 Linux 節點) 或 1.34 (適用於 Windows Server 節點) 支援期結束,且叢集節點自動升級至 1.33 或 1.35 時,叢集可能會發生下列問題:

  • 使用 Docker 結構定義 1 映像檔的工作負載會失敗。
  • 呼叫 CRI v1alpha2 API 的應用程式會發生 API 呼叫失敗情形。

找出受影響的叢集

GKE 會監控叢集,並使用 Recommender 服務,透過洞察和建議提供指引,協助您找出叢集中使用這些已淘汰功能的 Linux 節點。GKE 無法偵測 Windows Server 節點的使用量。

版本需求

如果叢集執行下列版本或更新版本,就會收到這些洞察和建議:

  • 1.28.15-gke.1159000
  • 1.29.9-gke.1541000
  • 1.30.5-gke.1355000
  • 1.31.1-gke.1621000

取得洞察資料和建議

按照操作說明查看洞察資料和建議。 您可以使用 Cloud de Confiance 控制台取得洞察資料。您也可以使用 Google Cloud CLI 或 Recommender API,並依下列子類型篩選:

  • DEPRECATION_CONTAINERD_V1_SCHEMA_IMAGES: Docker 結構定義 1 映像檔
  • DEPRECATION_CONTAINERD_V1ALPHA2_CRI_API: CRI v1alpha2 API
  • DEPRECATION_CONTAINERD_V2_CONFIG_REGISTRY_CONFIGS:已淘汰的 CRI registry.configs 屬性,包括 registry.configs.auth 和 registry.configs.tls

停止使用已淘汰的功能

請參閱下列內容,瞭解如何從 containerd 2 中已淘汰的功能遷移。

從 Docker 結構定義 1 映像檔遷移至其他選項

找出必須遷移的工作負載 (使用映像檔),然後遷移這些工作負載。

Google 提供的圖片受到這個問題影響: gcr.io/google-containers/startup-script。

  • gcr.io/google-containers/startup-script:v1:使用已淘汰的 Schema 1 格式,且無法在 Linux 節點的 GKE 1.33 以上版本中提取。
  • gcr.io/google-containers/startup-script:v2:使用支援的 Schema 2 格式,且可順利擷取。

如果您在任何工作負載 (例如 DaemonSet 或 Deployment) 中使用 gcr.io/google-containers/startup-script:v1,請務必將映像檔參照更新為 gcr.io/google-containers/startup-script:v2。

找出要遷移的圖片

您可以使用不同工具找出必須遷移的圖片。

使用深入分析和建議或 Cloud Logging

如「找出受影響的叢集」一節所述,如果叢集執行的是最低版本或更新版本,您可以使用洞察資料和最佳化建議,找出使用 Docker 結構定義 1 映像檔的 Linux 節點叢集。此外,您可以在 Cloud Logging 中使用下列查詢,檢查 containerd 記錄,找出叢集中的 Docker Schema 1 映像檔:

jsonPayload.SYSLOG_IDENTIFIER="containerd"
"conversion from schema 1 images is deprecated"

如果圖片已擷取超過 30 天,您可能不會看到圖片的記錄。

直接在節點上使用 ctr 指令

如要查詢特定節點,傳回以 Schema 1 形式提取的所有未刪除映像檔,請在節點上執行下列指令:

  ctr --namespace k8s.io images list 'labels."io.containerd.image/converted-docker-schema1"'

舉例來說,如果您要排解特定節點的疑難,但自提取映像檔以來已超過 30 天,因此 Cloud Logging 中沒有記錄項目,這個指令就很有用。

使用 crane 開放原始碼工具

您也可以使用開放原始碼工具 (例如 crane) 檢查映像檔。

執行下列 crane 指令,檢查圖片的結構定義版本:

crane manifest $tagged_image | jq .schemaVersion

準備工作負載

如要準備執行 Docker 結構定義 1 映像檔的工作負載,必須將這些工作負載遷移至結構定義 2 Docker 映像檔,或開放容器倡議 (OCI) 映像檔。請考慮下列遷移選項:

  • 尋找替代圖片:您或許可以找到公開的開放原始碼或供應商提供的圖片。
  • 轉換現有映像檔:如果找不到替代映像檔,可以按照下列步驟將現有的 Docker 結構定義 1 映像檔轉換為 OCI 映像檔:
    1. 將 Docker 映像檔拉取至 containerd,系統會自動將其轉換為 OCI 映像檔。
    2. 將新的 OCI 映像檔推送至登錄檔。

從 CRI v1alpha2 API 遷移

Kubernetes 1.26 版已移除 CRI v1alpha2 API。您必須找出會存取 containerd 通訊端的工作負載,並更新這些應用程式,才能使用 v1 API。

找出可能受影響的工作負載

您可以運用各種技巧,找出可能需要遷移的工作負載。這些技術可能會產生誤報,您必須進一步調查,確認是否不需要採取任何行動。

使用洞察資料和建議

如果叢集執行的是最低版本或更新版本,您可以使用洞察和建議,找出使用 v1alpha2 API 的 Linux 節點叢集。詳情請參閱「找出受影響的叢集」。

在 Cloud de Confiance 控制台中查看洞察資料時,請參閱側邊欄面板「將工作負載從已淘汰的 CRI v1alpha2 API 遷移至其他選項」。這個面板中的「Workloads to Verify」表格會列出可能受影響的工作負載。這份清單包含所有未由 GKE 管理的工作負載,這些工作負載具有包含 containerd Socket 路徑的 hostPath 磁碟區 (例如 /var/run/containerd/containerd.sock 或 /run/containerd/containerd.sock)。

請務必瞭解下列事項:

  • 要驗證的工作負載清單可能包含誤判結果。僅供調查使用。清單中顯示的工作負載不一定使用已淘汰的 API,且出現偽陽性不會暫停自動升級。系統只會根據實際觀察到的已淘汰 API 用量暫停服務。
  • 這份清單可能沒有內容或不完整。如果使用已淘汰 API 的工作負載生命週期較短,且在 GKE 執行定期檢查時未執行,就可能出現空白或不完整的清單。如果系統顯示建議,表示叢集內至少有一個節點偵測到 CRI v1alpha2 API 用量。如果系統在 14 天內未偵測到已淘汰的 API 用量,就會恢復自動升級。

因此,建議您使用下列方法進一步調查,確認實際的 API 用量。

檢查受影響的第三方工作負載

如果是部署至叢集的第三方軟體,請確認這些工作負載未使用 CRI v1alpha2 API。您可能需要與相關供應商聯絡,確認軟體版本是否相容。

使用 kubectl

下列指令會尋找存取 containerd Socket 的工作負載,協助您找出可能受影響的工作負載。這項功能使用的邏輯與 Cloud de Confiance 控制台建議中「待驗證的工作負載」資料表所用的邏輯類似。系統會傳回未由 GKE 管理,但具有 hostPath 磁碟區 (包括插槽路徑) 的工作負載。與建議一樣,這項查詢可能會傳回誤判結果,或遺漏生命週期較短的工作負載。

執行下列指令:

kubectl get pods --all-namespaces -o json | \
jq -r '
  [
    "/", "/var", "/var/","/var/run", "/var/run/",
    "/var/run/containerd", "/var/run/containerd/", "/var/run/containerd/containerd.sock",
    "/run", "/run/", "/run/containerd", "/run/containerd/",
    "/run/containerd/containerd.sock"
  ] as $socket_paths |
  [
    "kube-system", "kube-node-lease", "istio-system", "asm-system",
    "gatekeeper-system", "config-management-system", "config-management-monitoring",
    "cnrm-system", "hnc-system", "gke-managed-system", "gke-gmp-system",
    "gmp-system", "gke-managed-cim"
  ] as $excluded_namespaces |
  .items[] |
  select(
    (.spec.volumes[]?.hostPath.path as $p | $socket_paths | index($p))
    and
    ([.metadata.namespace] | inside($excluded_namespaces) | not)
  ) |
  .metadata.namespace + "/" + .metadata.name
'
使用 eBPF 追蹤功能找出 API 呼叫端

如要更明確地找出在 Linux 節點上執行的哪些工作負載呼叫 CRI v1alpha2 API,您可以部署兩個專用 DaemonSet:

  • containerd-socket-tracer 會記錄開啟與 containerd 插座連線的任何程序,以及 Pod 和容器詳細資料。
  • cri-v1alpha2-api-deprecation-reporter 會記錄上次呼叫 CRI v1alpha2 API 的時間。

這些工具會使用擴充 Berkeley 封包篩選器 (eBPF) 追蹤與 containerd 插座的連線,並將連線與實際已淘汰的 API 呼叫建立關聯。

您無法在 Windows Server 節點上部署這些 DaemonSet。

將這兩項工具的時間戳記相互對照,即可找出發出已淘汰 API 呼叫的確切工作負載。相較於單純檢查 hostPath 數量,這種方法可提供更高程度的信心,因為它會觀察實際的通訊端連線和 API 用量。

如需部署及使用這些工具的詳細操作說明,以及如何解讀記錄,請參閱「Tracing containerd Socket Connections」。

如果使用這些工具後,仍無法找出已淘汰 API 呼叫的來源,但建議仍處於有效狀態,請參閱「取得支援」。

找出使用 CRI v1alpha2 API 的工作負載後 (可透過上述方法或檢查程式碼集),您必須更新其程式碼,改用 v1 API。

更新應用程式程式碼

如要更新應用程式,請移除應用程式匯入 k8s.io/cri-api/pkg/apis/runtime/v1alpha2 用戶端程式庫的位置,並修改程式碼以使用 v1 版本的 API。這個步驟包括變更匯入路徑,以及更新程式碼呼叫 API 的方式。

舉例來說,請參閱下列使用已淘汰程式庫的 Golang 程式碼:

  package main

  import (
    ...

    runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
  )

  func foo() {
    ...

    client := runtimeapi.NewRuntimeServiceClient(conn)
    version, err := client.Version(ctx, &runtimeapi.VersionRequest{})

    ...
  }

在此,應用程式會匯入 v1alpha2 程式庫,並使用該程式庫發出 RPC。如果 RPC 使用 containerd 通訊端的連線,則這個應用程式會導致 GKE 暫停叢集的自動升級。

請按照下列步驟搜尋及更新應用程式程式碼:

  1. 執行下列指令,搜尋 v1alpha2 匯入路徑,找出有問題的 golang 應用程式:

      grep -r "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
    

    如果這項指令的輸出內容顯示檔案中使用了 v1alpha2 程式庫,您就必須更新檔案。

    舉例來說,請替換下列應用程式程式碼:

      runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
    
  2. 更新程式碼以使用 v1:

      runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
    

從已淘汰的 containerd 設定屬性遷出

CRI 外掛程式中的 registry.auths、registry.configs 和 registry.mirrors containerd 設定屬性已淘汰,將在 containerd 2.4 以上版本中移除,GKE 版本尚未公布。不過,containerd 2.0 已移除 registry.configs.tls。

找出工作負載

您可以運用不同技術,找出必須遷移的工作負載。

使用洞察資料和建議

您可以先使用洞察資料和建議,找出使用已淘汰 containerd 設定屬性的 Linux 節點叢集。這項功能有最低 GKE 版本需求。如要進一步瞭解這個方法,請參閱「找出受影響的叢集」。

在 Cloud de Confiance 控制台中查看洞察資料時,請參閱側邊欄面板中的「將 containerd 設定從已淘汰的 CRI 登錄授權欄位遷出」或「將 containerd 設定從已淘汰的 CRI 登錄鏡像欄位遷出」。如要找出可能存取 containerd 設定的工作負載,請查看「要驗證的工作負載」部分。

使用 kubectl

或者,您也可以使用 kubectl 識別工作負載。

檢查具有下列屬性的工作負載,找出會修改 containerd 設定的工作負載:

  • 包含 hostPath 磁碟區的工作負載,其中包含 containerd 設定
  • 具有具備特殊權限存取權的容器 (spec.containers.securityContext.privileged: true),並使用主機程序 ID (PID) 命名空間 (spec.hostPID: true) 的工作負載

這項指令可能會傳回誤判結果,因為工作負載可能會存取這些目錄中的其他檔案,而非 containerd 設定。或者,這項指令可能不會傳回以其他較不常見方式存取 containerd 設定檔的工作負載。

執行下列指令,檢查 DaemonSet:

kubectl get daemonsets --all-namespaces -o json | \
jq -r '
  [
    "/", "/etc", "/etc/",
    "/etc/containerd", "/etc/containerd/",
    "/etc/containerd/config.toml"
  ] as $host_paths |
  [
    "kube-system", "kube-node-lease", "istio-system", "asm-system",
    "gatekeeper-system", "config-management-system", "config-management-monitoring",
    "cnrm-system", "hnc-system", "gke-managed-system", "gke-gmp-system",
    "gmp-system", "gke-managed-cim"
  ] as $excluded_namespaces |
  .items[] |
  select(
    ([.metadata.namespace] | inside($excluded_namespaces) | not)
    and
    (
      (any(.spec.template.spec.volumes[]?.hostPath.path; IN($host_paths[])))
      or
      (
        .spec.template.spec.hostPID == true and
        any(.spec.template.spec.containers[]; .securityContext?.privileged == true)
      )
    )
  ) |
  .metadata.namespace + "/" + .metadata.name
'

從 CRI 登錄檔的 auths 或 configs.auth 屬性遷移

如果工作負載使用 containerd 設定中的 auths 或 configs.auth 屬性,向私人登錄檔驗證身分以提取容器映像檔,您必須改用 imagePullSecrets 欄位遷移使用這些映像檔的工作負載。詳情請參閱「從私人登錄檔提取映像檔」。

如要找出並遷移使用已淘汰 auths 或 configs.auth 屬性的工作負載,請參閱下列操作說明。

找出登錄檔的驗證詳細資料

您可以透過下列任一方式,找出登錄檔的驗證詳細資料:

  • 連線至 GKE 節點,查看 /etc/containerd/config.toml 檔案中的 CRI 登錄 auths 和 configs.auth 區段。
  • 找出會修改 containerd 設定檔的工作負載,並使用先前所述的工作負載識別方法,查看包含哪些驗證詳細資料。GKE 不會將這些設定用於系統工作負載。

如果您使用 registry.configs.auth 屬性,驗證詳細資料可能如下所示:

  [plugins."io.containerd.grpc.v1.cri".registry.configs."$REGISTRY_DOMAIN".auth]
    username = "example-user"
    password = "example-password"

請為設定中指定的每個登錄網域收集這些驗證詳細資料。

更新工作負載,使用 imagePullSecrets 欄位
  1. 按照從私人登錄檔提取映像檔的說明,使用上一節的驗證詳細資料建立 Secret。
  2. 執行下列指令,找出需要遷移至 imagePullSecrets 欄位的工作負載:

    kubectl get pods -A -o json |
    jq -r ".items[] |
      select(.spec.containers[] |
            .image | startswith(\"$REGISTRY_DOMAIN\")) |
      .metadata.namespace + \"/\" + .metadata.name"
    

    您必須為工作負載使用的每個命名空間建立 Secret,這些工作負載的映像檔來自這個登錄網域。

  3. 更新工作負載,使用 imagePullSecrets 欄位和您在上一步建立的密鑰。

    或者,如要遷移大量工作負載,可以實作 MutatingAdmissionWebhook 來新增 imagePullSecrets 欄位。

更新 containerd 設定,停止設定登錄授權

將工作負載遷移至使用 imagePullSecrets 欄位後,您必須更新會修改 containerd 設定的工作負載,停止設定登錄授權。針對您識別出的任何會修改設定的工作負載,請修改這些工作負載,停止設定登錄授權。

使用新的節點集區進行測試,並將工作負載遷移至新的節點集區

如要降低工作負載發生問題的風險,請採取下列做法:

  1. 建立新的節點集區。
  2. 排定更新後的工作負載,將修改 containerd 設定的節點排定至新的節點集區。
  3. 按照這篇文章的說明,將剩餘工作負載遷移至新的節點集區。

從 CRI 登錄檔 configs.tls 屬性遷移

如果工作負載使用 registry.configs.tls 屬性,您必須遷移這些工作負載,才能透過私人 CA 憑證存取私人登錄檔。

請按照操作說明從設定 DaemonSet 遷移。這個程序包含下列步驟:

  1. 更新會修改 containerd 設定的工作負載,停止設定 TLS 詳細資料。
  2. 將憑證儲存在 Secret Manager。
  3. 建立指向憑證的執行階段設定檔。
  4. 建立新的節點集區,並測試使用私人登錄檔中映像檔的工作負載是否正常運作。
  5. 將設定套用至新叢集,並開始在該叢集上執行工作負載,或將設定套用至現有叢集。將設定套用至現有叢集時,可能會中斷其他現有工作負載。如要進一步瞭解這兩種方法,請參閱「建立執行階段設定檔」。

遷移後,請務必停止對 registry.configs 欄位套用任何變更,否則可能會發生 containerd 問題。

取得支援

如果仍無法判斷已淘汰 API 呼叫的來源,且建議仍處於啟用狀態,請考慮採取下列後續步驟: