成都华为云代理商:Kubernetes 镜像拉取耗时久,聊聊 DNS 层面定位与处理
Kubernetes镜像拉取超时排查:DNS问题定位与解决
在Kubernetes集群里,Pod 一直停在 ImagePullBackOff 或 ErrImagePull 状态,kubectl describe pod 输出里反复出现 context deadline exceeded,很多时候并不是镜像仓库本身不可用,而是节点在解析镜像仓库域名时卡住。围绕 Kubernetes 镜像拉取超时排查,先要理解几条不同路径,避免一上来就改错地方。

理解Kubernetes镜像拉取超时的常见原因
为什么镜像拉取会超时,而不是直接报错?
镜像拉取超时和镜像拉取失败在 Kubelet 日志里经常被混在一起,但成因不同。Kubelet 调用容器运行时去拉镜像,如果 DNS 解析请求发出去后一直没有响应,或者上游 DNS 响应极慢,容器运行时不会立刻返回错误,而是等到默认超时时间耗尽才抛出 context deadline exceeded。这个阶段 Pod 会反复从 ContainerCreating 回到 ImagePullBackOff。从聚搜云接触到的企业运维场景来看,多数这类超时并不是仓库认证或带宽问题,而是 DNS 解析在第一个环节就拖住了。
哪些场景下最容易出现镜像拉取超时?
节点刚加入集群或横向扩容后最典型。新节点的 /etc/resolv.conf 可能与老节点不一致,指向了不同的 DNS 服务器;也可能安全组没有放行 UDP 53 端口,导致节点访问 VPC DNS 或公共 DNS 被丢弃。另一个高频场景是修改过 CoreDNS 或节点网络插件后,管理员误认为镜像拉取也走 CoreDNS,结果排查方向完全偏离。国内华为云代理商在交付 CCE 集群时,节点 DNS 配置有时会因自定义镜像、cloud-init 脚本或安全基线被覆盖,扩容后尤其容易暴露出来。

DNS 在镜像拉取链路中到底扮演什么角色?
这里要区分两条路径:Pod 内的域名解析走 CoreDNS,镜像拉取的域名解析走节点级容器运行时。Kubelet 拉起 containerd 或 Docker 后,运行时直接读取节点 /etc/resolv.conf,或者 containerd 配置中指定的 resolv.conf。华为云 VPC 默认提供内网 DNS,地址通常在 100.125.*.* 网段,节点一般指向该地址,拉取 Docker Hub 或自建仓库时再由内网 DNS 转发到公共 DNS。只要上游转发超时或 UDP 丢包,节点侧就会表现为镜像拉取超时,而 CoreDNS 日志里可能什么都看不到。
DNS排查前的准备工作
在动 CoreDNS 或节点 DNS 配置之前,先把一个关键路径说清楚:Kubernetes 节点拉取镜像时,kubelet 调用的是容器运行时,容器运行时解析镜像仓库域名时通常直接读节点 /etc/resolv.conf,并不会把请求发给集群内的 CoreDNS。聚搜云在整理这类服务器故障时发现,很多 ImagePullBackOff 的节点日志里同时出现 dial tcp: lookup ... on 10.247.x.x:53: no such host,但 CoreDNS 日志完全看不到对应查询,原因就在这里。准备阶段要按“节点 DNS → 容器运行时 DNS → 上游 DNS”这条链路收集信息,而不是一上来就改 CoreDNS。
一、需要收集哪些信息
在故障节点上至少保留四类信息:节点 /etc/resolv.conf 内容、容器运行时实际读取的 resolv.conf 路径、Docker/containerd 的 DNS 参数、镜像仓库域名。华为云 VPC 节点内网 DNS 通常为 100.125.*.*,如果节点被改成公共 DNS,或 systemd-resolved 与 NetworkManager 同时写入该文件,就容易出现偶发解析超时。用 cat /etc/resolv.conf、systemd-resolve --status、containerd config dump | grep -A5 resolv 快速比对。

二、常用的网络诊断工具
别只拿 nslookup 下结论。dig +time=2 +tries=1 能模拟拉取时的短超时场景,直接看到是响应慢、无响应还是 SERVFAIL。需要抓容器运行时的解析行为时,可以对 crictl pull 执行 strace -e trace=network,确认请求发到了哪个 DNS 服务器;crictl info 里的 DNS 字段也能看到 containerd 最终使用的解析配置。结合 journalctl -u kubelet --since "10 minutes ago" 可以定位报错时间点。
三、如何确认DNS是否正常
正常与否要同时看解析结果、耗时和上游 IP。在节点执行 dig @<节点配置DNS> <镜像仓库域名> +time=2 +tries=1,记录 Query time,再对比 dig @100.125.1.3 <域名> +time=2 +tries=1。如果前者超过 2 秒或偶发失败,而华为云内网 DNS 稳定,基本可以判定问题在节点 DNS 配置或 VPC 出口,而不是镜像仓库域名本身。同时确认 /etc/resolv.conf 是否被动态改写,很多“今天改完明天又变回去”的现象都来自这里。
逐步排查DNS配置问题
排查 Kubernetes 镜像拉取超时时,要先分清两条链路:节点容器运行时拉取镜像走节点级 DNS,集群内 Pod 解析才走 CoreDNS。把这两条路径混在一起,很容易在错误的位置改配置。
检查CoreDNS配置
先确认 CoreDNS 不是节点拉取镜像的查询入口。Docker 和 containerd 在节点上拉镜像时,直接读取节点 /etc/resolv.conf,不会查询集群内的 CoreDNS。可以用 kubectl -n kube-system get cm coredns -o yaml 查看 forward 上游是否可达,但这一步只用于排除集群内部域名解析故障。从华为云代理商聚搜云整理的运维案例来看,不少用户修改 CoreDNS 后节点 docker pull 依然超时,问题就出在两条链路被混为一谈。
测试域名解析速度
在故障节点直接执行 dig @100.125.1.1 registry.cn-south-1.myhuaweicloud.com +time=2 +tries=1,记录解析耗时。华为云 VPC 内网 DNS 通常位于 100.125.*.* 网段,节点默认会指向该地址。如果内网 DNS 响应超过 1 秒,或者 UDP 出现丢包,kubelet 日志就会表现为 dial tcp: lookup ... i/o timeout。可再用公共 DNS 对比测试:公共 DNS 正常而内网 DNS 慢,优先检查 VPC DNS 服务状态和安全组规则,而不是继续改节点配置。
分析resolv.conf文件
节点 /etc/resolv.conf 的 nameserver 必须指向有效的内网 DNS,options 中 timeout 和 attempts 设置过小会放大瞬时丢包影响。手动修改后要确认容器运行时是否重新加载;containerd 环境可检查 /etc/containerd/config.toml 中的 resolv_conf 参数,改完执行 systemctl restart containerd。如果 kubelet 日志出现 failed to pull image ... no such host,优先怀疑该文件被 NetworkManager 或 cloud-init 覆盖。华为云代理商常见工单里,用 strace -e trace=network crictl pull hello-world 追踪实际查询的 DNS 服务器,可以快速确认是否仍走旧配置。
华为云环境下镜像拉取的特殊性
华为云 CCE 集群中,镜像拉取的 DNS 解析路径与 Pod 内域名解析并不相同。kubelet 调用容器运行时拉取镜像时,节点上的 containerd/docker 直接读取 /etc/resolv.conf,不会经过 CoreDNS。因此排查 Kubernetes 镜像拉取超时,必须把节点级 DNS、容器运行时配置和安全组规则分开检查。

华为云DNS服务介绍
华为云 VPC 默认提供内网 DNS 服务器,IP 通常位于 100.125.*.* 网段,承担 VPC 内部域名和外网域名递归解析。在故障节点可执行 dig @100.125.1.1 registry.hub.docker.com +time=2 +tries=1,观察解析耗时和返回结果。聚搜云在整理这类服务器故障时发现,多数节点级解析异常并非 DNS 服务本身故障,而是 /etc/resolv.conf 被 NetworkManager 或 cloud-init 覆盖,导致实际查询地址与预期不符。确认时可对比 systemd-resolve --status 显示的当前 DNS 地址,不要只盯着配置文件。
镜像仓库加速配置
容器运行时支持配置镜像仓库 mirror,将外部镜像请求重定向至华为云 SWR 内网地址。对 containerd,可在 /etc/containerd/config.toml 中为 registry 配置 mirror 和 endpoint,例如指向 swr.cn-north-4.myhuaweicloud.com。从聚搜云接触到的企业运维场景来看,未配置内网镜像缓存时,单个节点偶发 ImagePullBackOff 的情况并不少见,配置后可减少对外部 Docker Hub 域名实时解析的依赖。修改后需执行 systemctl restart containerd,否则 kubelet 不会立即加载新配置。
安全组与防火墙限制
安全组出方向未放行 UDP 53 或 TCP 443 时,DNS 查询会被静默丢弃,表现为镜像拉取超时。扩容后新增节点出现解析异常,应优先检查同 VPC 下安全组是否已绑定到新节点网卡。节点本地 iptables 若限制 OUTPUT 链,也可能拦截 53 端口或镜像仓库非标准端口。排查时可用 dig @100.125.1.1 验证 DNS 可达性,再通过 iptables -L OUTPUT -n 检查出站规则,避免只改安全组而忽略节点防火墙。
解决DNS导致镜像拉取超时的方案
在动手改配置之前,必须先分清两条路径:Pod 内服务解析走 CoreDNS,而节点镜像拉取由容器运行时直接执行,默认读取节点的 /etc/resolv.conf 或 containerd 指定的 resolv.conf,不会经过 CoreDNS。因此,如果 crictl pull 同样超时,而 Pod 内 dig 正常,问题通常不在 CoreDNS,而在节点级 DNS 或上游解析链路。以下三个方案按优先级排序,而不是按常见度排序。
调整CoreDNS参数
调整 CoreDNS 参数对节点级镜像拉取没有直接作用,这是 Kubernetes 镜像拉取超时排查中最容易走偏的地方。只有当镜像仓库域名由 Pod 内的 initContainer 或应用进程解析时,CoreDNS 的 forward 和 cache 策略才会影响前置依赖。可在 CoreDNS ConfigMap 中把上游固定为 VPC 内网 DNS,例如 forward . 100.125.1.250 { max_concurrent 1000 },并增加 cache 30,避免每次查询穿透到公网。修改后先在 Pod 内验证解析耗时,再确认 kubelet 日志是否有改善,不要误以为改了 CoreDNS 就能解决 ImagePullBackOff。
使用镜像缓存或加速器
从华南地区华为云代理商聚搜云整理的运维案例来看,多数 Kubernetes 镜像拉取超时最终不是靠调 DNS 参数收敛,而是把公共仓库解析路径换成内网镜像缓存解决的。华为云 SWR 支持镜像同步和 pull through cache,节点 containerd 可配置 registry mirror 将 docker.io 请求指向内网地址:[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://xxxx.swr.myhuaweicloud.com"]。这样上游 DNS 抖动时,节点只需解析内网域名,响应时间和 UDP 丢包率都明显低于公网链路。自建仓库也可以在节点同 VPC 内部署 Harbor 代理,彻底绕开外部解析。
优化DNS查询策略
节点级 DNS 优化重点是降低单次解析超时成本并增加冗余。常见配置错误是 /etc/resolv.conf 只写一台内网 DNS,且无 options 控制,一旦该地址丢包,containerd 默认等待会拉长到数秒,kubelet 随即上报 ImagePullBackOff。建议在 /etc/systemd/resolved.conf 或 /etc/resolv.conf 中保留 VPC 内网 DNS 为主,增加公共 DNS 为备,并设置 options timeout:1 attempts:2 rotate。如果节点使用 containerd,最好单独生成 /etc/containerd/resolv.conf,在 config.toml 中通过 resolv_conf 指定,避免修改系统文件后未同步到容器运行时。验证时执行 time crictl pull busybox,观察解析阶段耗时是否从秒级降到毫秒级。
预防镜像拉取超时的最佳实践
在完成一轮 DNS 定位与修复后,更重要的是把“查一次”变成“持续可控”。镜像拉取超时很少是单次配置错误,多数情况是节点级 DNS 解析路径长期缺乏监控、容器运行时重试策略不合理、集群网络健康检查缺位共同叠加的结果。下面的三个方向不是独立措施,而是从节点侧、运行时侧和集群侧形成闭环,降低 ImagePullBackOff 再次出现的概率。
监控DNS性能:建立节点侧解析耗时基线
不要等 Pod 已经 ImagePullBackOff 才去手工 nslookup。建议在故障节点执行 dig @<VPC_DNS_IP> registry.hub.docker.com +time=2 +tries=1,记录解析时延和失败次数,并对比公网 DNS 的响应。从华为云代理商聚搜云接触到的企业运维场景来看,多数重复性镜像拉取超时的根因是节点继承的 VPC DNS 在某时段抖动,而团队只盯着 CoreDNS,没有对节点侧 DNS 做过基线。可借助 node-exporter 采集节点 /etc/resolv.conf 指向 DNS 的解析耗时,设置“超过 200ms 持续 5 分钟”的告警阈值,把隐性抖动暴露出来。
配置合理的重试机制:区分运行时与 kubelet 的超时参数
containerd 直接执行镜像拉取,其默认重试策略较为保守,一旦 DNS 解析阶段卡住几秒,就可能触发上层超时。可在 /etc/containerd/config.toml 的 [plugins."io.containerd.grpc.v1.cri".registry] 中为外部仓库配置本地 mirror 或缓存代理,例如将 Docker Hub 镜像同步到华为云 SWR,减少对公网 DNS 的实时依赖。同时调整 kubelet 的 --image-pull-progress-deadline 和 --serialize-image-pulls 参数,避免大量 Pod 因解析失败反复重试拖垮节点。修改后务必执行 systemctl restart containerd 或滚动重启节点,否则旧配置仍会继续生效。
定期检查集群网络健康:防止安全组与配置漂移
扩容新节点或变更安全组后,解析异常往往来自 UDP 53 端口未放行或节点 /etc/resolv.conf 被重置。建议建立巡检脚本,定期检查每个节点的 /etc/resolv.conf 内容、crictl info 中实际加载的 DNS 配置、VPC DNS 服务可达性以及 CoreDNS 上游转发状态。聚搜云在整理这类服务器故障时发现,将节点安全组入方向放行 VPC DNS 的 UDP 53 端口,能避免大量“节点 DNS 不通导致镜像拉取卡住”的问题。巡检脚本一旦发现配置漂移,应自动告警并记录节点名称,而不是等业务 Pod 无法调度后再人工介入。
- 点赞
- 收藏
- 关注作者
评论(0)