排查Nginx DNS解析异常需聚焦日志中间接线索:host not found in upstream(启动期解析失败)、no peer_addr(无IP导致连接失败)、resolver timeout、getaddrinfo() failed、no resolver defined等,并结合nslookup验证、检查resolver位置与作用域、确认容器网络及libc兼容性,优先用IP或hosts应急,再以变量+自定义resolver实现根治。

直接看 error.log 里有没有明确指向 DNS 解析环节的线索,重点不是找“DNS”这个词,而是识别那些看似无关、实则由解析失败引发的报错。
盯住几类典型日志关键词
这些提示不是孤立错误,而是解析失败在不同阶段暴露出来的“症状”:
- host not found in upstream:Nginx 启动或重载时就解析失败,说明 proxy_pass 或 upstream 里写了域名,但当时系统或 resolver 不可用
- no peer_addr:不是 DNS 报错本身,而是 downstream 没拿到 IP,导致连接无目标;要回溯确认上游域名是否真没解析出 A 记录
- resolver timeout 或 resolver failed:你配了 resolver,但它指定的 DNS 服务器不可达、响应慢,或被防火墙拦截 UDP 53 端口
- getaddrinfo() failed:底层调用失败,常见于变量为空(如 $upstream 未 set)、域名拼写错误、K8s 中短域名缺 search 域(比如只写 redis,没写 redis.default.svc.cluster.local)
- no resolver defined to resolve xxx:用了变量 proxy_pass,但 resolver 要么没配,要么配错位置(比如塞进 location 块,而它必须在 http 或 server 块顶层)
验证 DNS 是否真能通到那个域名
别只信 nslookup,要模拟 Nginx 的实际行为环境:
- 在 Nginx 所在机器上执行:nslookup your-upstream-domain,看是否返回 A/AAAA 记录
- 再试:nslookup your-upstream-domain 114.114.114.114,排除本地 DNS 服务异常
- 如果是容器或 K8s Pod,进容器执行:cat /etc/resolv.conf,确认 nameserver 是否指向 kube-dns/coredns,search 域是否匹配(例如缺 default.svc.cluster.local 会导致短域名解析失败)
- 若用 Alpine 镜像(musl libc),它默认不支持 EDNS0,某些内网 DNS 会拒绝响应;可临时换 Ubuntu 镜像或加 --dns=8.8.8.8 启动验证
检查 resolver 配置是否真正生效
写了 resolver 不等于就起作用,关键看三点:
- 位置对不对:resolver 必须放在 http{} 块顶层,或至少在 server{} 块内;不能塞进 location、upstream 或 events 块里
- 有没有配合变量用:只有 proxy_pass 写成 http://$backend 这种形式,resolver 才会触发;写死 http://api.example.com 是启动期静态解析,跟 resolver 无关
- 参数是否合理:valid=5s–30s 比较稳妥,太长无法感知 IP 变更,太短加重 DNS 压力;加上 ipv6=off 可避免 IPv6 查询拖慢整体解析
快速验证动态解析是否真在运行时工作
上线前就该做,别等故障发生:
- 修改本地 hosts 或 DNS,让域名返回一个新 IP,观察 error.log 是否出现 resolving 或 could not be resolved 相关记录
- 等 valid 时间过后,用 strace -p $(pgrep nginx) -e trace=connect 抓 worker 进程的 connect 系统调用,看目标 IP 是否切换到了新地址
- 临时把域名指向一个不可达地址,应看到超时日志,证明解析逻辑确实在请求时触发,而不是启动时卡死


















