Google Kubernetes Engine (GKE) 集群使用 containerd 节点映像,其中包含运行 1.24 及更高版本的所有工作器节点。工作器节点使用特定版本的 containerd,具体取决于 GKE 版本:
- 运行 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 Schema 1 映像和容器运行时接口 (CRI) v1alpha2 API。如需了解早期版本中弃用的其他功能,请参阅已弃用的配置属性。
- 在次要版本 1.33 中,GKE 使用 containerd 2.0,该版本移除了对 Docker Schema 1 映像和 CRI v1alpha2 API 的支持。
- CRI 插件中的以下 containerd 配置属性已弃用,将在 containerd 2.2 中移除,具体 GKE 版本尚未公布:
registry.auths
、registry.configs
、registry.mirrors
。不过,registry.configs.tls
已在 containerd 2.0 中移除。
如需了解自动升级到更高次要版本(例如 1.33)的大致时间,请参阅发布渠道的预计时间表。
过渡到 containerd 2 的影响
请阅读以下部分,了解此过渡到 containerd 2 的影响。
已暂停自动升级
GKE 在检测到集群使用已弃用的功能时,会暂停自动升级到 1.33 版。不过,如果您的集群节点使用这些功能,我们建议您创建维护排除项,以防止节点升级。维护排除项可确保在 GKE 未检测到使用情况时,您的节点不会升级。
在使用这些功能迁移后,如果满足以下条件,GKE 会恢复自动次要版本升级到 1.33:
- GKE 在 14 天内未检测到已弃用功能的使用情况,对于已弃用的 CRI
registry.configs
属性,则为 3 天。 - 1.33 是集群节点的自动升级目标版本。
- 没有其他阻碍因素。如需了解详情,请参阅自动升级的时间。
对于 Standard 集群节点池,您还可以手动升级节点池。
支持终止以及未做好迁移准备的影响
GKE 会暂停自动升级,直到标准支持服务结束。如果您的集群已在扩展渠道中注册,则您的节点可以一直使用某个版本,直到扩展支持服务结束日期。如需详细了解在支持终止时自动升级节点,请参阅在支持终止时自动升级。
如果您不迁移这些功能,当 1.32 版达到支持终止期限,并且您的集群节点自动升级到 1.33 版时,您的集群可能会遇到以下问题:
- 使用 Docker Schema 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
获取分析洞见和建议
按照相关说明查看分析洞见和建议。 您可以使用 Trusted Cloud 控制台获取分析洞见。您还可以使用 Google Cloud CLI 或 Recommender API,并使用以下子类型进行过滤:
DEPRECATION_CONTAINERD_V1_SCHEMA_IMAGES:
Docker Schema 1 映像DEPRECATION_CONTAINERD_V1ALPHA2_CRI_API:
CRI v1alpha2 APIDEPRECATION_CONTAINERD_V2_CONFIG_REGISTRY_CONFIGS
:已弃用的 CRIregistry.configs
属性,包括registry.configs.auth
和registry.configs.tls
从已弃用的功能迁移
请查看以下内容,了解如何从 containerd 2 中已弃用的功能迁移。
从 Docker Schema 1 映像迁移
确定使用必须迁移的映像的工作负载,然后迁移这些工作负载。
查找要迁移的映像
您可以使用不同的工具来查找必须迁移的映像。
使用分析洞见和建议或 Cloud Logging
如确定受影响的集群部分中所述,如果您的集群运行的是最低版本或更高版本,则可以使用分析洞见和建议来查找使用 Docker Schema 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 Schema 1 映像的工作负载,您必须将这些工作负载迁移到 Schema 2 Docker 映像或 Open Container Initiative (OCI) 映像。 您可以考虑采取以下迁移方案:
- 查找替换映像:您或许可以找到公开提供的开源映像或供应商提供的映像。
- 转换现有映像:如果您找不到替换映像,可以按照以下步骤将现有 Docker Schema 1 映像转换为 OCI 映像:
- 将 Docker 映像拉取到 containerd 中,后者会自动将其转换为 OCI 映像。
- 将新的 OCI 映像推送到您的注册表。
从 CRI v1alpha2 API 迁移
CRI v1alpha2 API 已在 Kubernetes 1.26 中移除。您必须找出访问 containerd 套接字的工作负载,然后更新这些应用以使用 v1 API。
确定可能受影响的工作负载
您可以使用不同的技术来识别可能需要迁移的工作负载。这些技术可能会生成假正例,您必须进一步调查以确定是否需要采取任何措施。
使用分析洞见和建议
如果您的集群运行的是最低版本或更高版本,则可以使用分析洞见和建议来查找使用 v1alpha2 API 的集群。如需了解详情,请参阅确定受影响的集群。
在 Trusted Cloud 控制台中查看分析洞见时,请参阅边栏面板将工作负载从已弃用的 CRI v1alpha2 API 迁出。此面板中的要验证的工作负载表格列出了可能会受到影响的工作负载。此列表包含任何不受 GKE 管理且具有包含 containerd 套接字路径(例如 /var/run/containerd/containerd.sock
或 /run/containerd/containerd.sock
)的 hostPath
卷的工作负载。
请务必了解以下几点:
- 此列表可能包含误报。此列表中显示的工作负载并不一定意味着它正在使用已弃用的 API。它仅表示工作负载引用了包含 containerd 套接字的
hostPath
卷。例如,监控代理可能会包含节点的根文件系统 (/
) 以收集指标。从技术上讲,包含节点的根文件系统会包含套接字的路径,但指标代理可能不会实际调用 CRI v1alpha2 API。 - 此列表可能为空或不完整。如果使用已弃用 API 的工作负载生命周期较短,并且在 GKE 执行定期检查时未运行,则可能会出现空列表或不完整列表。建议本身的存在意味着在集群的至少一个节点上检测到了 CRI v1alpha2 API 的使用。
因此,我们建议您使用以下方法进一步调查,以确认实际的 API 使用情况。
检查受影响的第三方工作负载
对于部署到集群的第三方软件,请验证这些工作负载是否未使用 CRI v1alpha2 API。您可能需要联系相应供应商,以确认其软件的哪些版本兼容。
使用 kubectl
以下命令通过查找访问 containerd 套接字的工作负载,帮助您找到可能受到影响的工作负载。其使用的逻辑与 Trusted 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 的时间。
这些工具使用扩展型伯克利包过滤器 (eBPF) 来跟踪与 containerd
套接字的连接,并将这些连接与实际的已弃用 API 调用相关联。
通过关联这两个工具中的时间戳,您可以精确定位发出已弃用 API 调用的确切工作负载。与仅检查 hostPath
音量相比,此方法可提供更高的置信度,因为它会观察实际的套接字连接和 API 使用情况。
如需详细了解如何部署和使用这些工具,以及如何解读其日志,请参阅跟踪 containerd 套接字连接。
如果您在使用这些工具后仍无法确定已弃用的 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 暂停集群的自动升级。
请按以下步骤搜索和更新应用代码:
运行以下命令搜索 v1alpha2 导入路径,以识别有问题的 golang 应用:
grep -r "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
如果此命令的输出显示该文件中使用了 v1alpha2 库,您必须更新该文件。
例如,替换以下应用代码:
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
更新代码以使用 v1:
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
从已弃用的 containerd 配置属性迁移
CRI 插件中的 registry.auths
、registry.configs
和 registry.mirrors
containerd 配置属性已弃用,将在 containerd 2.2 中移除,但 GKE 版本尚未公布。
不过,registry.configs.tls
已在 containerd 2.0 中移除。
确定工作负载
您可以使用不同的技术来确定必须迁移的工作负载。
使用分析洞见和建议
作为初始方法,您可以使用分析洞见和建议来查找使用已弃用的 containerd 配置属性的集群。这需要最低 GKE 版本。如需详细了解此方法,请参阅确定受影响的集群。
在 Trusted 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 注册数据库 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
字段
- 按照从私有注册表中拉取映像的说明,创建一个包含上一部分中身份验证详细信息的 Secret。
运行以下命令,确定哪些工作负载需要迁移到
imagePullSecrets
字段:kubectl get pods -A -o json | jq -r ".items[] | select(.spec.containers[] | .image | startswith(\"$REGISTRY_DOMAIN\")) | .metadata.namespace + \"/\" + .metadata.name"
您必须为来自此注册数据库网域的映像的工作负载所使用的每个命名空间创建一个 Secret。
更新工作负载,以使用您在上一步中创建的 Secret 的
imagePullSecrets
字段。或者,如果您需要迁移大量工作负载,可以实现 MutatingAdmissionWebhook 来添加
imagePullSecrets
字段。
更新 containerd 配置,以停止设置注册数据库身份验证
将工作负载迁移为使用 imagePullSecrets
字段后,您必须更新会修改 containerd 配置的工作负载,以停止设置注册表身份验证。对于您标识为修改配置的任何工作负载,请修改工作负载以停止设置注册数据库授权。
使用新节点池进行测试并将工作负载迁移到新节点池
如需降低导致工作负载出现问题的风险,请执行以下操作:
- 创建新的节点池。
- 将修改 containerd 配置的更新的工作负载调度到新节点池中的节点。
- 按照在节点池之间迁移工作负载的说明,将剩余的工作负载迁移到新节点池。
从 CRI 注册数据库 configs.tls
属性迁移
如果您的工作负载使用 registry.configs.tls
属性,则必须迁移这些工作负载,以便使用私有 CA 证书访问私有注册数据库。
按照说明从配置 DaemonSet 迁移。此过程通过以下步骤完成:
- 更新会修改 containerd 配置的工作负载,以停止设置 TLS 详细信息。
- 将证书存储在 Secret Manager 中。
- 创建指向证书的运行时配置文件。
- 创建新的节点池,并测试使用私有注册数据库中托管的映像的工作负载是否按预期运行。
- 将配置应用到新集群,并开始在该集群上运行工作负载,或者将配置应用到现有集群。将配置应用于现有集群可能会中断其他现有工作负载。如需详细了解这两种方法,请参阅创建运行时配置文件。
迁移后,请务必停止对 registry.configs
字段应用任何更改,否则可能会遇到 containerd 问题。
获取支持
如果您仍然无法确定已弃用的 API 调用的来源,并且建议仍然处于有效状态,请考虑执行以下后续步骤:
如果您在文档中找不到问题的解决方案,请参阅获取支持以获取进一步的帮助,包括以下主题的建议:
- 请与 Cloud Customer Care 联系,以提交支持请求。
- 通过在 StackOverflow 上提问并使用
google-kubernetes-engine
标记搜索类似问题,从社区获得支持。您还可以加入#kubernetes-engine
Slack 频道,以获得更多社区支持。 - 使用公开问题跟踪器提交 bug 或功能请求。