本文档介绍了您在使用 Google Kubernetes Engine (GKE) 节点上的容器运行时时可能会遇到的常见问题的问题排查步骤。
如果您需要其他帮助,请与 Cloud Customer Care 联系。在使用 Containerd 的 Windows 节点池上,包含简单盘符的装载路径失败
此问题已在 containerd 1.6.6 版及更高版本中得到解决。
在启动容器时,运行使用低于 1.6.6 版的 containerd 运行时的 Windows Server 节点池的 GKE 集群可能会遇到以下错误:
failed to create containerd task : CreateComputeSystem : The parameter is incorrect : unknown
如需了解详情,请参阅 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 版本。
/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 Windows 上容器运行时重启后,基于挂接的操作将无法正常运行
受影响的 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)。
Pod 显示 failed to allocate for range 0: no IP addresses available in range set
错误消息
受影响的 GKE 版本:1.24.6-gke.1500 或更早版本、1.23.14-gke.1800 或更早版本以及 1.22.16-gke.2000 或更早版本
运行使用 containerd 的节点池的 GKE 集群可能会遇到 IP 泄露问题,并耗尽节点上的所有 Pod IP。受影响的节点上安排的 Pod 会显示类似于以下内容的错误消息:
failed to allocate for range 0: no IP addresses available in range set: 10.48.131.1-10.48.131.62
如需详细了解此问题,请参阅 containerd GitHub 问题 #5438 和 GitHub 问题 #5768。
GKE Dataplane V2 中存在一个已知问题,可能会触发此问题。但是,此问题可能是由其他原因(包括 runc 卡住)触发的。
解决方案
如需解决此问题,请按照 GKE Dataplane V2 标准 GKE 集群的解决方法中所述的解决方法操作。
探测超出超时后的执行探测行为差异
受影响的 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,则会出现此问题。
如需解决此问题,请尝试执行以下操作:
- 确保受影响的节点在运行 Container-Optimized OS。不支持 Ubuntu 和 Windows 节点。
- 在配置文件中,确保
secretURI
字段中的 Secret 路径正确无误。 - 检查集群的 IAM 服务账号是否具有访问 Secret 的正确权限。
- 检查集群是否具有
cloud-platform
访问权限范围。如需了解相关说明,请参阅检查访问权限范围。
没有为本地网络 (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 中运行的应用配置为同时用于两个地址系列。
节点自动预配功能只会预配带有 Docker 节点池的 Container-Optimized OS
受影响的 GKE 版本:1.18、1.19、1.20.0 至 1.20.6-gke.1800
通过节点自动预配功能,您可以自动扩缩具有任何受支持的映像类型的节点池,但只能使用带有 Docker 的 Container-Optimized OS 映像类型创建新的节点池。
解决方案
如需解决此问题,请将 GKE 集群升级到 1.20.6-gke.1800 版或更高版本。在这些 GKE 版本中,可以为集群设置默认映像类型。
与 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 版本:全部
GKE 无法在升级、调整大小或其他操作期间创建节点。
症状和诊断
Google Cloud 控制台中的示例错误:
Error: "runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized".
此错误可能会在以下情况下发生:
- 当 GKE 安装 CNI 配置时,在节点引导期间显示在日志文件中。
- 如果拦截创建 Pod 的 DaemonSet 控制器命令的自定义网络钩子有错误,在 Google Cloud 控制台中显示为节点错误状态。这会阻止 GKE 创建
netd
或calico-node
Pod。如果当错误仍然存在时netd
或calico-node
Pod 成功启动,请与支持团队联系。
解决方案
如需解决此问题,请尝试以下解决方案:
- 等待 GKE 完成 CNI 配置的安装。
请按照以下说明移除所有配置错误的 webhook:
列出 webhook:
$ kubectl get mutatingwebhookconfigurations $ kubectl get validatingwebhookconfigurations
移除配置错误的 webhook:
kubectl delete mutatingwebhookconfigurations WEBHOOK_NAME kubectl delete validatingwebhookconfigurations WEBHOOK_NAME
将
WEBHOOK_NAME
替换为您要移除的配置错误的 webhook 的名称。配置网络钩子以忽略系统 Pod。