问题1: k8s环境下,服务使用node:xxx-alpine镜像,服务间访问报错: getaddrinfo EAI_AGAIN
问题2: 非alpine镜像, 使用clusterip访问频繁出现超时问题: connect ECONNRESET
,read ECONNRESET
还有服务本身axios报的timeout
问题3: 非alpine镜像, 使用dns访问报错: getaddrinfo ENOTFOUND
问题4: coreDns报错出现error: [ERROR] plugin/errors: 2 . NS: read udp 10.42.2.5:38764->183.60.82.98:53: i/o timeout
[DONE]记录问题解决过程
问题1问题排查/解决过程
- 现象1: 问题发生在流量高峰阶段
- 现象2: 压测tps,200线程仅30多每秒, 吞吐量极差
- 现象3: 是偶尔性的, 200线程50次仅发现十几条这样的报错日志
原因描述(备注: 该原因分析, 仅针对node:alpine镜像在对dns解析报错eai_again的问题, 在后文我发现换了debian也有同样的错误, 所以这个问题也不排除是coreDns出了问题)
参考链接: https://github.com/nodejs/docker-node/issues/1030#issuecomment-956122581
我们所有的程序相互都是以http协议进行接口交互, 而k8s提供的service为每一组pod提供了dns
当A调用B时,
调用方式即如下: http://B.default.svc.cluster.local:<port>
当A尝试与B.default.svc.cluster.local
建立 HTTP 连接的时候
必须查找 IP,因此 lib/dns.js(Node 的一部分)包装了 Node 的引擎函数
然后通过调用 getaddrinfo() 进行实际查找
后者取决于动态链接的 libc(alpine使用的并不是像其他系统一样的传统的libc)
还有一个问题:Alpine 的 musl libc 不完全支持 DNS 解析的所有功能,例如当使用多个 DNS 服务器或搜索命令时
参考链接
中提到两种可能的解决方案:
**A)**不要使用不完全支持 libc 功能(例如 Alpine)的最小基础镜像,而是切换到 Debian、Ubuntu、Ubi 等“slim”变体。
**B)**在构建 Node.js 引擎二进制文件时,将 libc 的 getaddrinfo() 静态链接到二进制文件中。这不会使用动态链接的 musl libc 代码。
问题2、3、4问题排查/解决过程
首先确认pod的dnsPolicy,为ClusterFirst(默认)
查看系统日志, 有error提示, 但是通过该 issue来看, 似乎问题不在这里
1 | Aug 15 21:51:12 k3s-prod-master3 k3s: W0815 21:51:12.632215 2021 watcher.go:220] watch chan error: etcdserver: mvcc: required revision has been compacted |
- 查看coredns的日志,通过日志,又去检查了
10.42.2.5
所在节点,服务器带宽较低
1 | # kubectl logs coredns-7448499f4d-pswcf -n kube-system |
随即手动进入容器curl集群内部接口 - 正常;curl集群外部第三方服务接口 - 响应较慢
查看coreDns的监控, 是否超标
我们现在coreDns的资源即副本数如下, 猜测是由于CoreDNS副本数不足、业务请求量高等情况导致的CoreDNS负载高, 才发生的报错(但Prometheus查并没啥异样...高峰期0.38左右的cpu和20多m内存, 并没到限制值)
1 | spec: |

- dnsutils-pod.yaml
1 | apiVersion: v1 |
- kubectl exec -i -t dnsutils -- nslookup dns
1 | # 使用dig命令, status为NOERROR, 循环看了1000次 |
补充1
- 暂时是将所有的dns地址换成了service的cluster ip了, 并且发现吞吐量是使用dns时候的5倍之多, 感觉就是dns解析这里出了问题
补充2
在将内存最小最大都调至210,再进行压测还是会有
getaddrinfo enotfount
这种问题,且内存占用资源还不到限制额度的7分之一,而且使用clusterIp访问方式压测第2番之后,发现流量过大会有如下问题服务间接性timeout:
connect ECONNRESET
,read ECONNRESET
还有服务本身axios报的timeout以下问题是因为重启了coreDns导致,忽略发现了coreDns的error日志bash1
2
3
4
5
6.:53(53即dns端口)
[INFO] plugin/reload: Running configuration MD5 = 442b35f70385f5c97f2491a0ce8a27f6
CoreDNS-1.8.3
linux/amd64, go1.16, 4293992
[ERROR] plugin/errors: 2 4227623083530362207.3296446569099129492. HINFO: read udp 10.42.2.219:48721->xxx:53: i/o timeout
[ERROR] plugin/errors: 2 4227623083530362207.3296446569099129492. HINFO: read udp 10.42.2.219:58867->xxx:53: i/o timeout
补充3
- 按照官方的建议将版本升至1.24.3,并加egrees-selector-mode: flase参数, 再次进行压测, 还是会有超时问题, 所以想着是不是节点之间的网络有问题
这里将所有的agent节点pod迁移到master, 并停止调度, 再次进行压测
1 | # 配置不可调度 |
- 使用clusterip的方式压测, timeout问题消失, 大胆断定之前服务间接性timeout问题是因为node节点和master节点之间connect存在互通问题(目前是node和master之间使用nginx进行负载, 而nginx所在服务器资源占用比较严重)
- 使用dns的方式进行压测, 服务出现间接性的
getaddrinfo ENOTFOUND
错误
补充4(第三个问题)
- 第三个问题:
如果使用dns访问, 服务将偶现getaddrinfo enotfound
肯定还是dns解析问题, 然后顺着https://stackoverflow.com/questions/70913822/kubernetes-k3s-pod-gets-enotfound-after-5-20-hours-of-airing-time
去了解下nodelocalcache, 安装, 并进行压测, 此问题消失
关于NodeLocalCache, 站内查看NodeLocalCache
篇
补充5(第四个问题)
可以使用log插件将请求详情记录下日志,来分析异常的原因; 但需要注意的是开启log插件调试可能会消耗10%左右的cpu资源, 建议调试完之后关闭

1 | # 通过修改kubernetes的configmap中的coredns配置来开启日志功能,无需重启coredns |
问题1:通过错误日志error: [ERROR] plugin/errors: 2 . NS: read udp 10.42.2.5:38764->183.60.82.98:53: i/o timeout
,随即去检查10.42.2.5
所在节点,发现出网带宽较低,ssh进入当前节点,进行curl外部第三方服务接口时发现响应也较慢
问题2(属于资源浪费,不能算问题):发现些外部域名末尾加了本不该加的svc.cluster.local, 如下
1 | [INFO] 10.42.3.0:41390 - 37462 "AAAA IN cmq-gz.public.tencenttdmq.com.cluster.local. tcp 61 false 65535" NXDOMAIN qr,aa,rd 154 0.000066155s "0" |
原因是因为DNS的无意义请求
(其实这个本质上不是问题, 但是产生了资源的浪费)
具体原因和解决方案见本站关于Dns解析的一些认识
参考:
- https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/
- https://www.suse.com/support/kb/doc/?id=000020174
使用镜像(1.22.8): https://hub.docker.com/r/dyrnq/k8s-dns-node-cache/tags