將節點遷移至 containerd 2

Google Kubernetes Engine (GKE) 叢集會使用 containerd 節點映像檔,搭配執行 1.24 以上版本的所有工作站節點。工作站節點會根據作業系統和 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.2 中移除,GKE 版本尚未公布:registry.authsregistry.configsregistry.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 天內未偵測到已淘汰功能的使用情形,或在 3 天內未偵測到已淘汰的 CRI registry.configs 屬性。
  • 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

取得洞察資料和建議

按照指示查看洞察資料和建議。 您可以使用 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 映像檔遷移至其他選項

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

受此問題影響的 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:使用支援的結構定義 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 映像檔的工作負載,必須將這些工作負載遷移至 Docker 結構定義 2 映像檔,或開放容器倡議 (OCI) 映像檔。請考慮下列遷移選項:

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

從 CRI v1alpha2 API 遷移

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

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

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

使用洞察資料和建議

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

在 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 呼叫端

如要更明確地找出在 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 用量。

如需部署及使用這些工具的詳細操作說明,以及如何解讀記錄,請參閱「追蹤 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 設定屬性的 Linux 節點叢集。這項功能有最低 GKE 版本需求。如要進一步瞭解這種做法,請參閱「找出受影響的叢集」。

在 Google Cloud 控制台中查看洞察資料時,請參閱側邊欄面板「將 containerd 設定從已淘汰的 CRI 儲存庫 auths 欄位遷出」或「將 containerd 設定從已淘汰的 CRI 儲存庫 mirrors 欄位遷出」。如要找出可能存取 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 呼叫的來源,且建議仍處於有效狀態,請考慮採取下列後續步驟: