从 Docker 迁移到 containerd 节点映像


本页面介绍如何将 Google Kubernetes Engine (GKE) Standard 集群和节点池从 Docker 迁移到使用 containerd 容器运行时的节点映像。

概览

Kubernetes 节点使用容器运行时启动、管理和停止 Pod 中运行的容器。containerd 运行时是 GKE 支持的行业标准容器运行时。

containerd 运行时提供了分层抽象,可实现 gVisor映像流式传输等一组丰富的特征来扩展 GKE 功能。与 Docker 运行时相比,containerd 运行时被认为更省资源且更安全。

如需迁移容器运行时,请执行以下操作:

  • 识别使用 Docker 运行时的节点
  • 验证迁移的影响
  • 更改节点映像

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。

识别使用 Docker 运行时的节点

您可以采用以下方法检查哪些节点使用基于 Docker 的节点映像:

  • 使用脚本遍历 Google Cloud 项目内所有 GKE 集群中的所有节点。
  • 使用 Google Cloud CLI、kubectl 或 Google Cloud 控制台来识别节点映像。
  • 使用弃用提示和建议来识别 Google Cloud 项目中特定可用区或区域的集群和节点。

我们建议您使用脚本来快速识别需要迁移的所有节点。

使用脚本识别 Docker 节点

以下脚本可以遍历可用项目内每个集群中的每个节点,并为您提供切实可行的建议,例如:

该脚本会忽略 GKE Autopilot 集群,这些集群默认使用具有 containerd 节点映像的 Container-Optimized OS。

运行以下脚本:

for project in $(gcloud projects list --format="value(projectId)")
do
  echo "ProjectId: $project"
  for clusters in $( \
    gcloud container clusters list \
      --project $project \
      --format="csv[no-heading](name,location,autopilot.enabled,currentMasterVersion,autoscaling.enableNodeAutoprovisioning,autoscaling.autoprovisioningNodePoolDefaults.imageType)")
  do
    IFS=',' read -r -a clustersArray <<< "$clusters"
    cluster_name="${clustersArray[0]}"
    cluster_zone="${clustersArray[1]}"
    cluster_isAutopilot="${clustersArray[2]}"
    cluster_version="${clustersArray[3]}"
    cluster_minorVersion=${cluster_version:0:4}
    cluster_autoprovisioning="${clustersArray[4]}"
    cluster_autoprovisioningImageType="${clustersArray[5]}"

    if [ "$cluster_isAutopilot" = "True" ]; then
      echo "  Cluster: $cluster_name (autopilot) (zone: $cluster_zone)"
      echo "    Autopilot clusters are running Containerd."
    else
      echo "  Cluster: $cluster_name (zone: $cluster_zone)"

      if [ "$cluster_autoprovisioning" = "True" ]; then
        if [ "$cluster_minorVersion"  \< "1.20" ]; then
          echo "    Node autoprovisioning is enabled, and new node pools will have image type 'COS'."
          echo "    This settings is not configurable on the current version of a cluster."
          echo "    Please upgrade you cluster and configure the default node autoprovisioning image type."
          echo "    "
        else
          if [ "$cluster_autoprovisioningImageType" = "COS" ]; then
            echo "    Node autoprovisioning is configured to create new node pools of type 'COS'."
            echo "    Run the following command to update:"
            echo "    gcloud container clusters update '$cluster_name' --project '$project' --zone '$cluster_zone' --enable-autoprovisioning --autoprovisioning-image-type='COS_CONTAINERD'"
            echo "    "
          fi

          if [ "$cluster_autoprovisioningImageType" = "UBUNTU" ]; then
            echo "    Node autoprovisioning is configured to create new node pools of type 'UBUNTU'."
            echo "    Run the following command to update:"
            echo "    gcloud container clusters update '$cluster_name' --project '$project' --zone '$cluster_zone' --enable-autoprovisioning --autoprovisioning-image-type='UBUNTU_CONTAINERD'"
            echo "    "
          fi
        fi
      fi

      for nodepools in $( \
        gcloud container node-pools list \
          --project $project \
          --cluster $cluster_name \
          --zone $cluster_zone \
          --format="csv[no-heading](name,version,config.imageType)")
      do
        IFS=',' read -r -a nodepoolsArray <<< "$nodepools"
        nodepool_name="${nodepoolsArray[0]}"
        nodepool_version="${nodepoolsArray[1]}"
        nodepool_imageType="${nodepoolsArray[2]}"

        nodepool_minorVersion=${nodepool_version:0:4}

        echo "    Nodepool: $nodepool_name, version: $nodepool_version ($nodepool_minorVersion), image: $nodepool_imageType"

        minorVersionWithRev="${nodepool_version/-gke./.}"
        linuxGkeMinVersion="1.14"
        windowsGkeMinVersion="1.21.1.2200"

        suggestedImageType="COS_CONTAINERD"

        if [ "$nodepool_imageType" = "UBUNTU" ]; then
          suggestedImageType="UBUNTU_CONTAINERD"
        elif [ "$nodepool_imageType" = "WINDOWS_LTSC" ]; then
          suggestedImageType="WINDOWS_LTSC_CONTAINERD"
        elif [ "$nodepool_imageType" = "WINDOWS_SAC" ]; then
          suggestedImageType="WINDOWS_SAC_CONTAINERD"
        fi

        tab=$'\n      ';
        nodepool_message="$tab Please update the nodepool to use Containerd."
        nodepool_message+="$tab Make sure to consult with the list of known issues https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd#known_issues."
        nodepool_message+="$tab Run the following command to upgrade:"
        nodepool_message+="$tab "
        nodepool_message+="$tab gcloud container clusters upgrade '$cluster_name' --project '$project' --zone '$cluster_zone' --image-type '$suggestedImageType' --node-pool '$nodepool_name'"
        nodepool_message+="$tab "

        # see https://cloud.google.com/kubernetes-engine/docs/concepts/node-images
        if [ "$nodepool_imageType" = "COS_CONTAINERD" ] || [ "$nodepool_imageType" = "UBUNTU_CONTAINERD" ] ||
           [ "$nodepool_imageType" = "WINDOWS_LTSC_CONTAINERD" ] || [ "$nodepool_imageType" = "WINDOWS_SAC_CONTAINERD" ]; then
          nodepool_message="$tab Nodepool is using Containerd already"
        elif ( [ "$nodepool_imageType" = "WINDOWS_LTSC" ] || [ "$nodepool_imageType" = "WINDOWS_SAC" ] ) &&
               [ "$(printf '%s\n' "$windowsGkeMinVersion" "$minorVersionWithRev" | sort -V | head -n1)" != "$windowsGkeMinVersion" ]; then
          nodepool_message="$tab Upgrade nodepool to the version that supports Containerd for Windows"
        elif [ "$(printf '%s\n' "$linuxGkeMinVersion" "$minorVersionWithRev" | sort -V | head -n1)" != "$linuxGkeMinVersion" ]; then
          nodepool_message="$tab Upgrade nodepool to the version that supports Containerd"
        fi
        echo "$nodepool_message"
      done
    fi # not autopilot
  done
done

# Sample output:
#
# ProjectId:  my-project-id
#  Cluster: autopilot-cluster-1 (autopilot) (zone: us-central1)
#    Autopilot clusters are running Containerd.
#  Cluster: cluster-1 (zone: us-central1-c)
#    Nodepool: default-pool, version: 1.18.12-gke.1210 (1.18), image: COS
#
#       Please update the nodepool to use Containerd.
#       Make sure to consult with the list of known issues https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd#known_issues.
#       Run the following command to upgrade:
#
#       gcloud container clusters upgrade 'cluster-1' --project 'my-project-id' --zone 'us-central1-c' --image-type 'COS_CONTAINERD' --node-pool 'default-pool'
#
#    Nodepool: pool-1, version: 1.18.12-gke.1210 (1.18), image: COS
#
#       Please update the nodepool to use Containerd.
#       Make sure to consult with the list of known issues https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd#known_issues.
#       Run the following command to upgrade:
#
#       gcloud container clusters upgrade 'cluster-1' --project 'my-project-id' --zone 'us-central1-c' --image-type 'COS_CONTAINERD' --node-pool 'pool-1'
#
#    Nodepool: winpool, version: 1.18.12-gke.1210 (1.18), image: WINDOWS_SAC
#
#       Upgrade nodepool to the version that supports Containerd for Windows
#
#  Cluster: another-test-cluster (zone: us-central1-c)
#    Nodepool: default-pool, version: 1.20.4-gke.400 (1.20), image: COS_CONTAINERD
#
#      Nodepool is using Containerd already
#

使用 Google Cloud 识别节点映像

可以使用 Google Cloud CLI、kubectl 或 Google Cloud 控制台检查现有节点的节点映像。

gcloud

运行以下命令:

gcloud container node-pools list \
    --cluster=CLUSTER_NAME \
    --format="table(name,version,config.imageType)"

CLUSTER_NAME 替换为您的集群名称。

输出内容类似如下:

NAME          NODE_VERSION    IMAGE_TYPE
default-pool  1.19.6-gke.600  UBUNTU

控制台

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 在集群列表中,点击您要验证的集群的名称。

  3. 选择节点标签页。

  4. 节点池部分中,检查映像类型列中的值。

kubectl

运行以下命令:

kubectl get nodes -o wide

输出内容类似如下:

# For Docker runtime
NAME         STATUS   VERSION             OS-IMAGE                             CONTAINER-RUNTIME
gke-node-1   Ready    v1.16.15-gke.6000   Container-Optimized OS from Google   docker://19.3.1
gke-node-2   Ready    v1.16.15-gke.6000   Container-Optimized OS from Google   docker://19.3.1
gke-node-3   Ready    v1.16.15-gke.6000   Container-Optimized OS from Google   docker://19.3.1

CONTAINER-RUNTIME 列中的值会显示运行时和版本。

使用弃用提示和建议确定集群

GKE 会检测一些已弃用的功能和 API(包括基于 Docker 的节点映像)的使用情况。如需了解详情,请参阅 GKE 弃用

在检测弃用使用情况时,GKE 会生成提示和建议,它们会使用提示子类型 DEPRECATION_K8S_1_24_DOCKERSHIM 标识使用了基于 Docker 的节点映像。

一个提示和建议配对标识一个具有使用基于 Docker 的节点映像的节点的集群。每个提示和建议都提供了集群中使用基于 Docker 的节点映像的特定节点池的列表,并且这些节点池必须迁移到 containerd 节点映像。

要开始使用,请按照相关说明查看弃用提示和建议。对于 gcloud CLI 命令,请使用以下标志以仅查看此弃用的提示:

--filter="insightSubtype:DEPRECATION_K8S_1_24_DOCKERSHIM"

确定哪个集群的节点池正在使用基于 Docker 的节点映像后,请按照相关说明将节点映像更改为 containerd 节点映像

验证迁移的影响

在将生产集群和节点池迁移到使用 containerd 的节点映像之前,我们强烈建议您在预演环境中测试迁移的影响,以最大限度地降低问题所带来的风险。

我们建议您在迁移节点时独立升级节点,以便在使用新配置验证工作负载功能时可以隔离变量。此外,如果同时将节点池升级到 1.24 版,则无法回滚更改,因为 1.24 不支持 Docker 节点,并且您也无法降级次要版本。

将节点映像更改为 containerd 映像

如果您使用脚本识别 Docker 节点,则可以使用该脚本返回的建议运行的命令将节点自动预配设置和节点映像更改为 containerd 等效项。

您还可以通过使用 gcloud CLI 或 Google Cloud 控制台更新节点池并设置其他映像,将节点从 Docker 映像类型迁移到 containerd 映像类型。

GKE 使用选定的节点升级策略和配置来迁移节点的映像。对于此迁移,我们建议您使用蓝绿升级策略,因为如果您的工作负载在升级期间遇到新节点映像的问题,您可以回滚到具有原始节点映像配置的先前环境。

gcloud

运行以下命令:

gcloud container clusters upgrade CLUSTER_NAME \
    --image-type=NODE_IMAGE \
    --node-pool=POOL_NAME \
    --cluster-version=NODE_VERSION

替换以下内容:

  • NODE_IMAGE:您想要节点使用的节点映像。
  • POOL_NAME:要迁移的节点池的名称。
  • NODE_VERSION:节点池的现有版本。我们建议设置此标志,因为不设置此标志时 GKE 会尝试将节点池的版本升级到控制平面版本,并在同一操作中更新节点映像。如果控制平面运行 1.24,则该命令会失败。如果控制平面正在运行 1.23,则该命令会成功,这样会阻止您单独测试这两种更改(版本升级和映像更新)。

输出类似于以下内容:

NAME          NODE_VERSION    IMAGE_TYPE
default-pool  1.23.6-gke.600  UBUNTU_CONTAINERD

控制台

  1. 转到 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 在集群列表中,点击您要验证的集群的名称。

  3. 点击节点标签页。

  4. 节点池部分中,点击要修改的节点池的名称。

  5. 节点池详情页面中,点击 修改

  6. 节点部分中的映像类型下,点击更改

  7. 选择其中一种 containerd 映像类型。

  8. 点击更改

回滚到 Docker 节点映像

如果您的节点已自动或手动迁移到 containerd 节点,并且您发现工作负载存在问题,请执行以下步骤以还原到 Docker 节点映像:

  1. 根据操作的状态选择以下步骤:
  2. 配置维护排除项以暂时阻止 GKE 重试迁移。
  3. 调查问题的根本原因,以便可以从 Docker 进行迁移,并确保您的集群运行的是受支持的 GKE 版本。
  4. 再次尝试将节点映像更改为 containerd 映像。如果您移除维护排除项,GKE 将再次触发操作。

更新基础架构即代码 (IaC) 工具配置

如果您使用 Terraform、Ansible 或 Pulumi 等 IaC 工具来管理 GKE 集群,请务必更新配置来使用 containerd 节点映像,以防止这些工具将新的实际状态恢复到之前需要的状态。例如,GKE Terraform 提供程序支持可配置的映像类型

更新所有配置,以避免迁移到 containerd 节点映像后工具将节点映像更新回基于 Docker 的节点映像。

更改节点自动预配的默认节点映像

如果在集群中使用节点自动预配功能,请将默认映像类型更改为 containerd 节点映像。更改默认映像类型仅适用于新的自动预配节点池。必须手动更改现有自动预配节点池的节点映像。

可以使用 gcloud CLI 或配置文件更改默认节点自动预配映像类型。

gcloud

运行以下命令:

gcloud container clusters update CLUSTER_NAME \
    --enable-autoprovisioning \
    --autoprovisioning-image-type=IMAGE_TYPE

替换以下内容:

  • CLUSTER_NAME:要更新的集群的名称。
  • IMAGE_TYPE:节点映像类型,可以是以下值之一:

    • cos_containerd
    • ubuntu_containerd

文件

可以使用 YAML 配置文件来更改节点自动预配所用的默认节点映像类型。使用文件时,您还必须指定 CPU 和内存资源的最大值。

  1. 保存以下 YAML 文件:

    resourceLimits:
      - resourceType: 'cpu'
          minimum: 4
          maximum: 10
      - resourceType: 'memory'
          maximum: 64
    autoprovisioningNodePoolDefaults:
      imageType: 'IMAGE_TYPE'
    

    IMAGE_TYPE 替换为 containerd 映像类型。

  2. 应用配置:

    gcloud container clusters update CLUSTER_NAME \
        --enable-autoprovisioning \
        --autoprovisioning-config-file=FILE_NAME
    

    FILE_NAME 替换为配置文件的路径。

问题排查

如需进行问题排查并查看存在解决方法的已知问题,请参阅排查容器运行时的问题

后续步骤