前言
最近做项目,有业务出现偶发的部署导致响应很慢的情况,据了解,业务使用域名访问,相同的nginx代理,唯一的区别就是K8S重新部署了。那么问题大概率出现在容器平台,毕竟业务是重启几次正常,偶尔一次很慢,又并不是不能返回。这里就很奇特,现象是少部分节点和请求超时,并不是失败。
排查过程
出现问题,根据端到端的全链路原则
应用检查
第一时间排查了应用本身,应用是Java写的,所以通过jstack -l pid

这里出现IPV6了,实际上基本使用都是IPV4,当然IPV6也在普及,毕竟IP数量大。
发现应用大面积的出现类似dns解析的线程栈,那么可以断定问题出在域名解析环节。
抓包
而此时 通过抓包,发现pod在做域名解析时,调用node节点的localdns出现clash状态
笔者本地抓包:wireshark:sudo chown 用户名:admin /dev/bpf*(伯克利包过滤器)
如果是服务器,则执行tcpdump:tcpdump -i any -s0 port 53 -w app.cap
tcpdump命令:
-s number 表示需要截取报文字节数(tcpdump默认只会截取前96个字节),如果是0的话,表示截取报文全部内容
-i 指定网卡,any表示所有
port 指定端口
host 指定ip
-w app.cap 写入xxx文件
当然也可以指定协议,不指定默认所有协议
域名一般是80端口,所以这里写的80,笔者本地dockerdesktop默认没有localdns的,且coredns正常。

以访问qq网站为例,这里就localdns正常,如果异常,那么抓包就会发现
cluster.local的解析报错情况。此时重启nodelocaldns即可正常。
nodelocaldns
NodeLocal DNSCache
是一套 DNS 本地缓存解决方案。NodeLocal DNSCache 通过在集群节点上运行一个 DaemonSet 来提高集群 DNS 性能和可靠性。

根据官方文档:在 Kubernetes 集群中使用 NodeLocal DNSCache | Kubernetes
通过日志查询使用iptables还是ipvs
kubectl logs -n kube-system $(kubectl get pods -n kube-system | grep kube-proxy | awk '{print $1}')
日志
bash
huahua@huahuadeMacBook-Pro kube % kubectl logs -n kube-system $(kubectl get pods -n kube-system | grep kube-proxy | awk '{print $1}')
I0315 09:17:47.935227 1 server_others.go:72] "Using iptables proxy"
I0315 09:17:48.037793 1 server.go:1050] "Successfully retrieved node IP(s)" IPs=["192.168.65.3"]
I0315 09:17:48.037978 1 conntrack.go:118] "Set sysctl" entry="net/netfilter/nf_conntrack_tcp_timeout_established" value=86400
I0315 09:17:48.038086 1 conntrack.go:118] "Set sysctl" entry="net/netfilter/nf_conntrack_tcp_timeout_close_wait" value=3600
I0315 09:17:48.197513 1 server.go:652] "kube-proxy running in dual-stack mode" primary ipFamily="IPv4"
I0315 09:17:48.197663 1 server_others.go:168] "Using iptables Proxier"
I0315 09:17:48.203123 1 server_others.go:503] "Detect-local-mode set to ClusterCIDR, but no cluster CIDR defined"
I0315 09:17:48.203166 1 server_others.go:529] "Defaulting to no-op detect-local"
I0315 09:17:48.203182 1 server_others.go:503] "Detect-local-mode set to ClusterCIDR, but no cluster CIDR defined"
I0315 09:17:48.203198 1 server_others.go:529] "Defaulting to no-op detect-local"
I0315 09:17:48.203847 1 proxier.go:246] "Setting route_localnet=1 to allow node-ports on localhost; to change this either disable iptables.localhostNodePorts (--iptables-localhost-nodeports) or set nodePortAddresses (--nodeport-addresses) to filter loopback addresses"
I0315 09:17:48.207807 1 server.go:865] "Version info" version="v1.29.1"
I0315 09:17:48.207983 1 server.go:867] "Golang settings" GOGC="" GOMAXPROCS="" GOTRACEBACK=""
I0315 09:17:48.215566 1 config.go:188] "Starting service config controller"
I0315 09:17:48.215736 1 shared_informer.go:311] Waiting for caches to sync for service config
I0315 09:17:48.215774 1 config.go:97] "Starting endpoint slice config controller"
I0315 09:17:48.215795 1 config.go:315] "Starting node config controller"
I0315 09:17:48.215803 1 shared_informer.go:311] Waiting for caches to sync for node config
I0315 09:17:48.215827 1 shared_informer.go:311] Waiting for caches to sync for endpoint slice config
I0315 09:17:48.316912 1 shared_informer.go:318] Caches are synced for node config
I0315 09:17:48.316968 1 shared_informer.go:318] Caches are synced for service config
I0315 09:17:48.317142 1 shared_informer.go:318] Caches are synced for endpoint slice config
可以看到笔者本地使用的iptables,当然ipvs性能更强,实际生产应该使用ipvs
Using iptables proxy
根据官方文档,笔者使用iptables安装的node-local-dns

笔者试着干掉localdns,但是因为是deamonset,干掉又自动重建了pod,复现也很简单,把配置写错运行nodelocaldns,比如网上出现的循环解析dns的IP,pod就会处于CrashLoopBackOff状态,重建不成功,发现问题后,修改相应配置即可解决。
总结
实际上这个问题并不是应用的问题,是平台搭建的时候就有问题,但是仅仅是nodelocaldns并不影响最终的结果,毕竟coredns还是正常的,所以仅仅是超时,对于业务研发人员,K8S里面的逻辑是不可见的,所以问题很难解决,最终需要应用分析,抓包和基础设施层共同配合才能解决问题。