將節點遷移至 containerd 2


Google Kubernetes Engine (GKE) 叢集會使用 containerd 節點映像檔,搭配所有執行 1.24 以上版本的工作站節點。工作站節點會根據 GKE 版本使用特定版本的 containerd:

  • 如果節點執行 GKE 1.32 以下版本,並使用 containerd 節點映像檔,則會使用 containerd 1.7 以下版本。
  • 執行 GKE 1.33 的節點會使用 containerd 2.0。

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

如果您確定工作負載在 containerd 2 上正常運作,可以略過本頁內容。

GKE 如何轉換至 containerd 2

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

  • 在 1.32 次要版本中,GKE 使用 containerd 1.7。containerd 1.7 已淘汰 Docker 結構定義 1 映像檔和 Container Runtime Interface (CRI) v1alpha2 API。如要瞭解舊版中已淘汰的其他功能,請參閱「已淘汰的設定屬性」。
  • 在 1.33 次要版本中,GKE 使用 containerd 2.0,這個版本移除了對 Docker 結構定義 1 映像檔和 CRI v1alpha2 API 的支援。
  • CRI 外掛程式中的下列 containerd 設定屬性已淘汰,並將在 containerd 2.2 中移除,GKE 版本則尚未公布:registry.authsregistry.configsregistry.mirrors。不過,containerd 2.0 已移除 registry.configs.tls

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

改用 containerd 2 的影響

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

已暫停自動升級

GKE 偵測到叢集使用已淘汰的功能時,會暫停自動升級至 1.33 版。不過,如果叢集節點使用這些功能,建議您建立維護排除規則,防止節點升級。如果 GKE 未偵測到使用情形,維護排除功能可確保節點不會升級。

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

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

如果是標準叢集節點集區,您也可以手動升級節點集區

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

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

如果未遷移這些功能,當 1.32 終止支援,且叢集節點自動升級至 1.33 時,叢集可能會發生下列問題:

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

找出受影響的叢集

GKE 會監控叢集,並使用 Recommender 服務,透過深入分析和建議提供指引,協助您找出使用這些已淘汰功能的叢集節點。

版本需求

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

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

取得洞察資料和建議

按照指示查看洞察資料和建議。 您可以使用 Google Cloud 控制台取得洞察資料。您也可以使用 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.authregistry.configs.tls

停止使用已淘汰的功能

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

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

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

尋找要遷移的圖片

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

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

如「找出受影響的叢集」一節所述,如果叢集執行的是最低版本或更新版本,您可以使用洞察和建議,找出使用 Docker 結構定義 1 映像檔的叢集。此外,您可以在 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 遷移

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

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

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

使用洞察資料和建議

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

在 Google Cloud 控制台中查看洞察資料時,請參閱側欄面板「將工作負載從已淘汰的 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 的工作負載,協助您找出可能受影響的工作負載。這項功能使用的邏輯與 Google Cloud 控制台建議中的「待驗證的工作負載」表格類似。系統會傳回未由 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 呼叫端

如要更明確地判斷哪些工作負載呼叫 CRI v1alpha2 API,可以部署兩個專用 DaemonSet:

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

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

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

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

如果使用這些工具後,您仍無法找出已淘汰 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.authsregistry.configsregistry.mirrors containerd 設定屬性已淘汰,並將在 containerd 2.2 中移除,GKE 版本則尚未公布。不過,containerd 2.0 已移除 registry.configs.tls

找出工作負載

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

使用洞察資料和建議

一開始,您可以使用洞察和建議,找出使用已淘汰 containerd 設定屬性的叢集。這項操作需要最低 GKE 版本。如要進一步瞭解此方法,請參閱「找出受影響的叢集」。

在 Google Cloud 控制台中查看洞察資料時,請參閱側邊面板的「將 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 登錄檔的 authsconfigs.auth 屬性遷移

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

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

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

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

  • 連線至 GKE 節點,查看 /etc/containerd/config.toml 檔案中的 CRI 登錄 authsconfigs.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 欄位和您在上一步建立的 Secret。

    或者,如要遷移大量工作負載,可以實作 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 呼叫的來源,且建議仍處於有效狀態,請考慮採取下列後續步驟: