Google Kubernetes Engine (GKE) 节点上的容器运行时的问题可能会导致各种工作负载失败,从而阻止容器启动或可靠运行。这些问题通常是由网络配置错误、权限问题或容器运行时之间的差异等问题引起的。
您可以使用本页面来排查 GKE 节点池上容器运行时的常见问题。查找以下问题的解决方案:Windows 上装载路径错误、从私有注册表拉取映像失败、缺少文件系统指标、CNI 初始化错误以及在执行探测中出现行为差异。
对于在 GKE 集群上管理和部署工作负载的平台管理员和运维人员以及应用开发者来说,此信息非常重要。了解这些问题排查步骤有助于确保您的容器在不同的节点映像和配置中可靠运行。如需详细了解我们在 内容Google Cloud 中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和 任务。
Windows Server 节点池上的问题
以下部分介绍了特定于运行 Windows Server 节点池的 GKE 集群的容器运行时问题。
包含裸盘符的装载路径失败
此问题已在 containerd 1.6.6 版及更高版本中得到解决。
运行使用低于 1.6.6 版的 containerd 运行时的 Windows Server 节点池的 GKE 集群可能会遇到类似于以下内容的错误:
failed to create containerd task : CreateComputeSystem : The parameter is incorrect : unknown
此错误是由指定不带尾部反斜杠的盘符(例如,D: 而不是 `D:`)引起的。如需了解详情,请参阅 GitHub 问题 #6589。
解决方案
如需解决此问题,请将节点池升级到使用 containerd 运行时 1.6.6 版或更高版本的最新 GKE 版本。
在使用 Containerd 的 Windows 节点池上,具有非数组预转义 CMD 或 ENTRYPOINT 命令行的容器映像失败
此问题已在 containerd 1.6 版及更高版本中得到解决。
在启动容器时,运行使用 containerd 运行时 1.5.X 的 Windows Server 节点池的 GKE 集群可能会遇到以下错误:
failed to start containerd task : hcs::System::CreateProcess : The system cannot find the file specified.: unknown
如需了解详情,请参阅 GitHub 问题 #5067 和 GitHub 问题 #6300。
解决方案
如需解决此问题,请将节点池升级到使用 containerd 运行时 1.6.6 版或更高版本的最新 GKE 版本。
在使用 Containerd 的 Windows 节点池上,具有不存在的路径或 Linux 格式(正斜线)路径的容器映像卷失败
此问题已在 containerd 1.6 版及更高版本中得到解决。
在启动容器时,运行使用 containerd 运行时 1.5.X 的 Windows Server 节点池的 GKE 集群可能会遇到以下错误:
failed to generate spec: failed to stat "<volume_path>": CreateFile : The system cannot find the path specified.
如需了解详情,请参阅 GitHub 问题 #5671。
解决方案
如需解决此问题,请将节点池升级到使用 containerd 运行时 1.6.x 版或更高版本的最新 GKE 版本。
在 GKE Windows Server 节点池上容器运行时重启后,基于挂接的操作将无法正常运行
受影响的 GKE 版本: 1.21 到 1.21.5-gke.1802、1.22 到 1.22.3-gke.700
如果 GKE 集群运行使用 Containerd 运行时(版本 1.5.4 和 1.5.7-gke.0)的 Windows Server 节点池,则在容器运行时被强制重启时,可能会遇到问题:对现有运行容器的挂接操作无法再次绑定 IO。此问题不会导致 API 调用失败,但系统不会发送或接收数据。这包括通过集群 API 服务器挂接和记录 CLI 与 API 的数据。
解决方案
如需解决此问题,请升级到具有更高 GKE 版本的修补后容器运行时版本 (1.5.7-gke.1)。
/etc/mtab:不存在此类文件或目录
Docker 容器运行时默认在容器内填充此符号链接,但 containerd 运行时不会填充。
如需了解详情,请参阅 GitHub 问题 #2419。
解决方案
如需解决此问题,请在构建映像期间手动创建符号链接 /etc/mtab。
ln -sf /proc/mounts /etc/mtab
映像拉取错误:不是目录
受影响的 GKE 版本:全部
使用 kaniko 构建映像时,可能无法使用 containerd 拉取该映像,并显示错误消息“不是目录”。如果映像以特殊方式构建,则以下情况下会发生此错误:当上一个命令删除一个目录,而下一个命令在该目录中重新创建相同的文件。
以下是带有 npm 的 Dockerfile 示例,说明了此问题。
RUN npm cache clean --force
RUN npm install
如需了解详情,请参阅 GitHub 问题 #4659。
解决方案
如需解决此问题,请使用 docker build 构建映像,此问题不会影响该映像。
如果 docker build 不适合您,请将多个命令组合成一个命令。以下 Dockerfile 示例将 RUN npm cache clean --force 和 RUN npm install 组合:
RUN npm cache clean --force && npm install
某些文件系统指标缺失且指标格式不同
受影响的 GKE 版本:全部
Kubelet /metrics/cadvisor 端点提供 Prometheus 指标,如 Kubernetes 系统组件的指标中所述。如果您安装依赖于该端点的指标收集器,可能会看到以下问题:
- Docker 节点上的指标格式为
k8s_<container-name>_<pod-name>_<namespace>_<pod-uid>_<restart-count>,但 containerd 节点上的指标格式为<container-id>。 containerd 节点上缺少一些文件系统指标,如下所示:
container_fs_inodes_free container_fs_inodes_total container_fs_io_current container_fs_io_time_seconds_total container_fs_io_time_weighted_seconds_total container_fs_limit_bytes container_fs_read_seconds_total container_fs_reads_merged_total container_fs_sector_reads_total container_fs_sector_writes_total container_fs_usage_bytes container_fs_write_seconds_total container_fs_writes_merged_total
解决方案
您可以使用 cAdvisor 作为独立守护进程集来缓解此问题。
- 查找名称模式为
vX.Y.Z-containerd-cri的最新 cAdvisor 版本(例如v0.42.0-containerd-cri)。 - 按照 cAdvisor Kubernetes Daemonset 中的步骤创建守护进程集。
- 让已安装的指标收集器指向使用 cAdvisor
/metrics端点,该端点提供全套 Prometheus 容器指标。
替代方案
- 将监控解决方案迁移到 Cloud Monitoring,后者提供了一整套容器指标。
- 使用端点
/stats/summary从 Kubelet 摘要 API 收集指标。
探测超出超时后的执行探测行为差异
受影响的 GKE 版本:全部
containerd 映像上的执行探测行为与 dockershim 映像上的行为不同。如果为 Pod 定义的 exec 探测超过 dockershim 映像上声明的 Kubernetes timeoutSeconds 阈值,则该探测会被视为失败。在 containerd 映像上,系统会忽略声明的 timeoutSeconds 阈值后返回的探测结果。
解决方案
在 GKE 中,特性门控 ExecProbeTimeout 设置为 false,并且无法更改。如需解决此问题,请提高所有受影响的执行探测的 timeoutSeconds 阈值,或在探测逻辑中实现超时功能。
排查私有注册表问题
本部分提供了 containerd 中的私有注册表配置的问题排查信息。
映像拉取失败并显示 x509 错误:证书由未知授权机构签名
如果 GKE 找不到特定私有注册表网域的证书,则会出现此问题。您可以使用以下查询在 Cloud Logging 中检查此错误:
前往 Google Cloud 控制台中的 Logs Explorer 页面:
请运行以下查询:
("Internal error pulling certificate" OR "Failed to get credentials from metadata server" OR "Failed to install certificate")
如需解决此问题,请尝试执行以下操作:
在 GKE Standard 中,打开位于以下路径的配置文件:
/etc/containerd/hosts.d/DOMAIN/config.toml将
DOMAIN替换为注册表的 FQDN。验证您的配置文件是否包含正确的 FQDN。
验证配置文件的
secretURI字段中的证书路径是否正确。验证 Secret Manager 中是否存在证书。
证书不存在
如果 GKE 无法从 Secret Manager 拉取证书以在您的节点上配置 containerd,则会出现此问题。 如果 GKE 无法访问证书,则节点会在没有证书的情况下启动。在该节点上运行的工作负载无法访问您的私有注册表。
如需解决此问题,请尝试执行以下操作:
- 确保受影响的节点在运行 Container-Optimized OS。不支持 Ubuntu 和 Windows 节点。
- 在配置文件中,确保
secretURI字段中的 Secret 路径正确无误。 - 检查集群的 IAM 服务账号是否具有访问 Secret 的正确权限。
- 检查集群是否具有
cloud-platform访问权限范围。如需了解相关说明, 请参阅检查访问权限范围。 使用以下方法之一重新创建节点:
- 将节点池升级 到其已在使用的 GKE 版本。
- 将工作负载迁移到有权访问证书的 节点池。
- 排空问题节点, 然后 在 Compute Engine 中删除主机实例。
没有为本地网络 (10.0.0.0/8) 配置不安全的注册表选项
受影响的 GKE 版本:全部
在 containerd 映像上,没有为本地网络 10.0.0.0/8 配置不安全的注册表选项。如果使用不安全的私有仓库,您可能会看到以下错误:
pulling image: rpc error: code = Unknown desc = failed to pull and unpack image "IMAGE_NAME": failed to do request: Head "IMAGE_NAME": http: server gave HTTP response to HTTPS client
如需解决此问题,请尝试执行以下操作:
- 使用 Artifact Registry
- 如果您的使用场景支持此选项,请在私有注册表上配置 TLS。您可以使用 containerd 配置文件指示 GKE 使用存储在 Secret Manager 中的证书来访问私有注册表。如需查看相关说明,请参阅使用私有 CA 证书访问私有注册表。
配置特权 DaemonSet 以修改 containerd 配置
对于 Standard 集群,请尝试以下步骤。此解决方法不适用于 Autopilot,因为特权容器存在安全风险。如果您的环境向互联网公开,则在部署此解决方案之前,请考虑您的风险容忍度。 在所有情况下,我们都强烈建议您为私有注册表配置 TLS,并改用 Secret Manager 选项。
请查看以下清单:
在
.spec.containers.env字段中,将ADDRESS变量的REGISTRY_ADDRESS值替换为本地 HTTP 仓库的地址,格式为DOMAIN_NAME:PORT。例如,containers: - name: startup-script ... env: - name: ADDRESS value: "example.com:5000"部署 DaemonSet:
kubectl apply -f insecure-registry-ds.yaml
DaemonSet 会将不安全的仓库添加到每个节点上的 containerd 配置中。
containerd 忽略特权 Pod 的任何设备映射
受影响的 GKE 版本:全部
对于特权 Kubernetes Pod,容器运行时会忽略 volumeDevices.devicePath 传递给它的所有设备映射,改为让主机上的每台设备都可供 /dev 下的容器使用。
当节点面临 I/O 压力时,containerd 泄露 shim 进程
受影响的 GKE 版本:1.25.0 至 1.25.15-gke.1040000、1.26.0 至 1.26.10-gke.1030000、1.27.0 至 1.27.6-gke.1513000,以及 1.28.0 至 1.28.3-gke.1061000
当 GKE 节点面临 I/O 压力时,containerd 在删除 Pod 后可能无法删除 containerd-shim-runc-v2 进程,从而导致进程泄露。当节点上发生泄露时,您会看到节点上的 containerd-shim-runc-v2 进程数大于该节点上的 Pod 数。您可能还会看到内存和 CPU 用量增加以及额外的 PID。如需了解详情,请参阅 GitHub 问题修复由高 IO 压力导致的 shim 泄露。
如需解决此问题,请将节点升级到以下版本或更高版本:
- 1.25.15-gke.1040000
- 1.26.10-gke.1030000
- 1.27.6-gke.1513000
- 1.28.3-gke.1061000
在运行 containerd 的 Pod 上启用 IPv6 地址系列
受影响的 GKE 版本:1.18、1.19、1.20.0 至 1.20.9
为使用 containerd 运行的 Pod 启用了 IPv6 映像系列。dockershim 映像会在所有 Pod 上停用 IPv6,而 containerd 映像不会。例如,localhost 会先解析为 IPv6 地址 ::1。这通常不是问题,但在某些情况下可能会导致意外行为。
解决方案
如需解决此问题,请明确使用 IPv4 地址(如 127.0.0.1),或将 Pod 中运行的应用配置为同时用于两个地址系列。
与 172.17/16 IP 地址范围冲突
受影响的 GKE 版本:1.18.0 至 1.18.14
172.17/16 IP 地址范围会被启用了 containerd 的节点虚拟机上的 docker0 接口占用。向该范围发送或来自该范围的流量可能无法正确路由(例如,Pod 可能无法连接到 IP 地址在 172.17/16 中的 VPN 连接主机)。
未收集的 GPU 指标
受影响的 GKE 版本:1.18.0 至 1.18.18
在 GKE 1.18.18 版之前,如果将 containerd 用作运行时,系统不会收集 GPU 用量指标。
解决方案
如需解决此问题,请将集群升级到 GKE 1.18.18 版或更高版本。
不能在 containerd 中使用 config.mediaType 设置为 application/octet-stream 的映像
受影响的 GKE 版本:全部
不能在 containerd 中使用 config.mediaType 设置为 "application/octet-stream" 的映像。如需了解详情,请参阅 GitHub 问题 #4756。这些映像与 Open Container Initiative 规范不兼容,被视为不正确。这些映像可与 Docker 结合使用来提供向后兼容性,而在 containerd 中,这些映像不受支持。
症状和诊断
节点日志中的错误示例:
Error syncing pod <pod-uid> ("<pod-name>_<namespace>(<pod-uid>)"), skipping: failed to "StartContainer" for "<container-name>" with CreateContainerError: "failed to create containerd container: error unpacking image: failed to extract layer sha256:<some id>: failed to get reader from content store: content digest sha256:<some id>: not found"
映像清单通常可在托管它的注册表中找到。
获得清单后,请检查 config.mediaType 以确定您是否遇到了此问题:
"mediaType": "application/octet-stream",
解决方案
由于 containerd 社区决定不支持此类映像,因此所有 containerd 版本都会受到影响,并且没有修复。您必须使用 Docker 1.11 或更高版本重新构建容器映像,并且必须确保 config.mediaType 字段未设置为 "application/octet-stream"。
CNI 未初始化
受影响的 GKE 版本:全部
如果您看到类似以下内容的错误,则表示容器网络接口 (CNI) 配置尚未就绪:
Error: "network is not ready: container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized".
出现此错误的主要原因有两个:
- CNI 尚未完成安装
- webhook 配置错误
确保 CNI 已完成安装
当 GKE 安装 CNI 配置时,您可能会在节点引导期间的日志文件中看到此错误。如果您看到此错误,但 GKE 正在正确创建所有节点,则可以放心地忽略此错误。
之所以会出现这种情况,是因为 CNI 为 Pod 提供网络连接,因此 Pod 需要 CNI 才能正常运行。不过,Kubernetes 会使用污点来标记未就绪的节点,而系统 Pod 可以容忍这些污点。这意味着,系统 Pod 可以在网络就绪之前在新节点上启动,从而导致此错误。
如需解决此问题,请等待 GKE 完成 CNI 配置的安装。CNI 完成网络配置后,系统 Pod 会成功启动,无需任何干预。
修正配置错误的 webhook
如果“CNI 未初始化”错误仍然存在,并且您注意到 GKE 在升级、调整大小或其他操作期间无法创建节点,则可能是 webhook 配置错误。
如果您有一个拦截创建 Pod 的 DaemonSet 控制器命令的自定义 webhook,并且该 webhook 配置错误,那么您可能会在 Google Cloud 控制台中看到错误,即节点错误状态。此配置错误会阻止 GKE 创建 netd 或 calico-node Pod。如果当错误仍然存在时 netd 或 calico-node Pod 成功启动,请与 Customer Care 团队联系。
如需修正任何配置错误的 webhook,请完成以下步骤:
-
如果您使用的是启用了 Dataplane V1 网络政策强制执行的集群,还可以检查
calico-typhaPod 的状态,了解哪些 webhook 导致了此错误:kubectl describe pod -n kube-system -l k8s-app=calico-typha如果 Pod 存在错误,则输出类似于以下内容:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedCreate 9m15s (x303 over 3d7h) replicaset-controller Error creating: admission webhook WEBHOOK_NAME denied the request [...]在此输出中,
WEBHOOK_NAME是失败的 Webhook 的名称。您的输出可能包含有关其他类型错误的信息。 如果您想保留配置错误的 webhook,请进行问题排查。如果不需要这些文件,请运行以下命令将其删除:
kubectl delete mutatingwebhookconfigurations WEBHOOK_NAME kubectl delete validatingwebhookconfigurations WEBHOOK_NAME将
WEBHOOK_NAME替换为您要移除的配置错误的 webhook 的名称。配置 webhook 以忽略系统 Pod。
后续步骤
如果您在文档中找不到问题的解决方案,请参阅获取支持以获取进一步的帮助,包括以下主题的建议:
- 请与 Cloud Customer Care 联系,以提交支持请求。
- 通过在 StackOverflow 上提问并使用
google-kubernetes-engine标记搜索类似问题,从社区获得支持。您还可以加入#kubernetes-engineSlack 频道 以获得更多社区支持。 - 使用 公开问题跟踪器提交问题或功能请求。