[转发]记一次kubernetes网络调试 -- 从失败中可以也学到很多
来源:互联网 发布:唯弋女装旗舰店淘宝 编辑:程序博客网 时间:2024/05/18 20:09
背景
过了年leetcode的用户量渐渐起来了,1台服务器已经有点吃力,当高峰的时候经常有些请求超时。而且为了防止服务器的单点问题,需要部署多个replica以保证高可用性。之前的架构已经是在kubernetes集群上了,因此扩容相对而言比较容易。整个webserver的架构如下图所示:
- nginx作为反向代理监听互联网的请求
- 对于leetcode.com的访问转发到kubernetes service
- 通过label将service与pod绑定,并在service层作负载均衡
两个pod分布在不同的机器上,其中pod2所在的机器是为了这次的扩容而部署的。关于如何在已有的集群中增加机器,可以参考我这篇文章。当然手动部署可能不是最方便的,如果想要自动部署,可以去看看关于kubeadm的相关资料。
遇到的问题
当一切准备就绪并导流的时候,旧机器的log在不断地输出,说明工作正常,但新机器的日志文件没有滚动,请求一个也没有进来。检查pod的状态,发现它是一切正常的:
1234
[root@kubernetes-slave-2 ~]# kubectl get pod --namespace=nojNAME READY STATUS RESTARTS AGEnoj-rc-i3aca 1/1 Running 0 2hnoj-rc-vgb5e 1/1 Running 0 2h
而且,noj-rc-vgb5e
这个pod也是顺利被分配到slave2并启动的。这说明kubelet
和kube-proxy
的配置没有问题,不然是无法收到master机器的调度请求从而部署pod的。因此首先怀疑两台机器网络状态是否不一致。
在slave2执行systemctl stop firewalld
,请求陆陆续续地进来了。因此应该就是iptables配置的问题,某些规则配置错误,导致网络包被reject了。在debug之前先贴上网络结构图方便之后说明。
调试纠错
step1
由于kubernetes集群的iptables规则较为复杂,执行iptables -L -n
和iptables -L -n -t nat
发现有上百条记录,对于一条条比对的任务就望而却步了,粗略看了一下一模一样,就连行数都是一样的。
1234
[root@kubernetes-slave-2 ~]# iptables -L -n | grep -c ''135[root@kubernetes-slave-2 ~]# iptables -L -n -t nat| grep -c ''174
1234
[root@kubernetes-slave-1]# iptables -L -n | grep -c ''135[root@kubernetes-slave-1]# iptables -L -n -t nat| grep -c ''174
这就让我犯难了:既然两台机器的网络环境都一模一样,为什么请求一台能进去,一台进不去呢?
step2
我们现在知道的症状有限,还有没有别的可供参考呢?找找其它症状吧。
进入slave1的container:
12345678
[root@kubernetes-slave-1]# kubectl exec -it noj-rc-i3aca bash --namespace=nojroot@noj-rc-i3aca:/leetcode/noj# nslookup google.comServer: 10.254.0.10Address: 10.254.0.10#53Non-authoritative answer:Name: google.comAddress: 216.58.194.174
进入slave2的container(其中nslookup的过程花了很久,大约2-3秒):
12345678
[root@kubernetes-slave-2]# kubectl exec -it noj-rc-vgb5e bash --namespace=nojroot@noj-rc-vgb5e:/leetcode/noj# nslookup google.comServer: 8.8.8.8Address: 8.8.8.8#53Non-authoritative answer:Name: google.comAddress: 216.58.194.174
在kubernetes集群中,我部署了dns服务在10.254.0.10
,slave2确实将10.254.0.10
配置为首选dns服务器,但是slave2并没有使用它或者访问不到它。
123456
root@noj-rc-vgb5e:/leetcode/noj# cat /etc/resolv.confsearch noj.svc.cluster.local svc.cluster.local cluster.localnameserver 10.254.0.10nameserver 8.8.8.8nameserver 8.8.4.4options ndots:5
这也就解释了为什么在slave2执行nslookup那么慢的原因:10.254.0.10
失败了,再选择8.8.8.8
。
step3
slave2访问集群内部服务失败,它是不是也无法跨机器ping通docker呢。
在slave1上ping master
1234
[root@kubernetes-slave-1]# ping 172.16.92.1PING 172.16.92.1 (172.16.92.1) 56(84) bytes of data.64 bytes from 172.16.92.1: icmp_seq=1 ttl=64 time=2.71 ms64 bytes from 172.16.92.1: icmp_seq=2 ttl=64 time=2.18 ms
1234
[root@kubernetes-slave-2 ~]# ping 172.16.92.1PING 172.16.92.1 (172.16.92.1) 56(84) bytes of data.--- 172.16.92.1 ping statistics ---5 packets transmitted, 0 received, 100% packet loss, time 3999ms
step4
既然关闭防火墙是可以服务的,那我们一步步在防火墙中添加ACCEPT记录,看看究竟是哪条记录导致网络包被REJECT了。
1
[root@kubernetes-slave-2 ~]# iptables -I INPUT 1 -j ACCEPT
非常幸运,在INPUT链添加ACCEPT规则后,一切请求马上都正常了,包括step3中的ping也可以正常服务了。
删掉刚才添加的ACCEPT规则,并在iptables中打日志,看看ping 172.168.92.1
的时候会有那些日志进来:
1
[root@kubernetes-slave-2 ~]# iptables -I INPUT 1 -j LOG
tail -f /var/log/messages
,我发现有以下的包在slave1是可以顺利通过防火墙的,但在slave2被拒绝了:
123
Feb 11 08:18:03 kubernetes-slave-2 kernel: IN=eth0 OUT= MAC=5a:e9:b7:d6:88:8d:30:7c:5e:91:9c:30:08:00 SRC=<ip of master> DST=<ip of slave2> LEN=134 TOS=0x00 PREC=0x00 TTL=60 ID=16426 PROTO=UDP SPT=56731 DPT=8472 LEN=114Feb 11 08:18:04 kubernetes-slave-2 kernel: IN=eth0 OUT= MAC=5a:e9:b7:d6:88:8d:30:7c:5e:91:9c:30:08:00 SRC=<ip of master> DST=<ip of slave2> LEN=134 TOS=0x00 PREC=0x00 TTL=60 ID=16426 PROTO=UDP SPT=56731 DPT=8472 LEN=114Feb 11 08:18:05 kubernetes-slave-2 kernel: IN=eth0 OUT= MAC=5a:e9:b7:d6:88:8d:30:7c:5e:91:9c:30:08:00 SRC=<ip of master> DST=<ip of slave2> LEN=134 TOS=0x00 PREC=0x00 TTL=60 ID=16426 PROTO=UDP SPT=56731 DPT=8472 LEN=114
注意到8472端口,这个端口是vxlan用于广播数据报文用的端口,vxlan是flannel底层用于跨机器通信用的。我明明记得配置kubernetes机器的时候对这个端口开了白名单呀:
12345
[root@kubernetes-slave-1 ~]# iptables -L -n | grep 8472ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:8472 ctstate NEW[root@kubernetes-slave-2 ~]# iptables -L -n | grep 8472ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8472 ctstate NEW
这个时候我终于发现问题了,当时给8472开的白名单误写成了tcp,然而vxlan使用的是udp!!!
最后,两条命令解决问题,终于一切都正常了!
12
firewall-cmd --zone=public --add-port=8472/udp --permanentsystemctl restart firewalld
总结
一个非常小的错误,导致这一通排查花了我一整天的时间,还是应该多仔细啊。在排查的过程中,其实我也走了一些弯路,刚开始我就确定是网络配置的问题,step2和step3其实都是没有必要的。如果刚开始就直接在iptables中打日志,就可以更快的发现这个问题。因为事后证明新发现的症状对于最后的debug并没有太大的帮助。
来源:http://xidui.github.io/2017/02/09/%E8%AE%B0%E4%B8%80%E6%AC%A1kubernetes%E7%BD%91%E7%BB%9C%E8%B0%83%E8%AF%95/
- [转发]记一次kubernetes网络调试 -- 从失败中可以也学到很多
- 这里不错,可以学到很多东西
- 动手真的可以学到很多
- 从查找一次内存泄漏学到的...
- 有用的oracle的SQL语句,可以学到很多东西
- 从 Kubernetes 谈容器网络
- 从 Kubernetes 谈容器网络
- 从乐高上我们可以学到什么?
- 进阶:从 EventBus 我们可以学到什么
- 我们也可以从这样的案件中,学会正视
- 从输入流中获取数据并以字节数组返回,这种输入流可以来自Android本地也可以来自网络
- apche server 中配置别名【也可以设定网络路径】
- BP神经网络也可以有很多层隐层啊,为什么说BP网络是浅层,而所谓DNN是深层?
- 没有源代码也可以调试
- 我在一次网络布线中碰到的问题,也许很多人都知道的。
- 从Google身上可以学到的14个东西
- 从Google身上可以学到的14个东西
- 从Google身上可以学到的14个东西
- SSH项目实战---图书销售及后台管理系统
- 我们为什么要配置环境变量
- android开发中的各种实用网站
- maven的生命周期
- 梯度下降算法比较
- [转发]记一次kubernetes网络调试 -- 从失败中可以也学到很多
- ckeditor中 config.js等通过ckeditor.js引入文件手动修改方法
- 从0开始学习 GitHub 系列之「01.初识 GitHub」----转载自stormzhang 原创文章
- 2017数据分析与R语言制图专题研讨班震撼来袭 课程大公开!
- 算法核心思想总结及模板(不定期更新)
- caffe 入门学习 2
- 持久化存储——Redis简介
- 队列的总结
- tensorflow pip 安装