背景
最近遇到一个问题,线上老集群下线时,node节点全部下线,只剩下ingress的节点,流量已全部切走,理论上应该没什么请求量,但ingress经常负载飙高导致容器挂掉。
分析过程
出问题的时候,可以看到nginx error.log 里面有很多 connection refused 的请求
2020/05/13 03:39:02 [error] 587#587: *5038285 connect() failed (111: Connection refused) while connecting to upstream, client:192.168.231.2 server: _, request: "POST /RPC2 HTTP/1.1", upstream: "http://127.0.0.1:8181/RPC2", host: "1.1.1.1:80"
统计发现请求均来自192.168.231.2 这个IP,经确认,这个IP是我们安全团队漏洞扫描机器IP,也就是说请求是安全团队漏洞扫描机器发出来的
ingress 终端运行日志里面发现default-http-backend 找不到active endpoints 的日志,如下所示
W0513 07:26:38.211186 7 controller.go:353] service kube-system/default-http-backend does not have any active endpoints
问题复现
正常情况下,如果nginx 后端upstream 不存在时,会立即返回502 并退出
root@web-02:~ # curl http://test.abc.com -x"127.0.0.1:80" -I
HTTP/1.1 502 Bad Gateway
而ingress 中,由于default backend 的存在,如果访问一个不存在server_name,请求就会丢给ingress default-backend 这个handler 处理
root@ubuntu:~ # curl http://testnotfound.abc.com/test.html -x "127.0.0.1:80"
default backend - 404
default backend 不存在的情况下,curl 访问ingress 会不断重试陷入无限循环(直到我们自己执行ctrl+c 终端curl请求才会停止)
ingress error.log 里面可以看到不断有新的请求进来
这也是为什么nginx 单个cpu 被打爆而其他cpu 相对空闲的原因,相当于客户端跟nginx建了个长连接(同一个客户端,源端口不变),不断发起请求
为default backend 容器加上污点容忍,让default backend 容器飘到ingress controller机器,正常调度后机器CPU负载恢复正常
root@ubuntu:~# kubectl -n kube-system edit deployment default-http-backend
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/ingress
operator: Equal
value: "true"
root@ubuntu:/home/wuguihong1# kubectl -n kube-system get pod|grep default
default-http-backend-5b6975cbf8-xthpv 1/1 Running 0 15s
[root@ubuntu:~]$ curl http://10.70.2.190:30000/test
default backend - 404
思考
触发需要2个条件,default backend 实例不存在 + 随机访问一个不存在的server_name (能进入default backend逻辑即可)
如果线上环境上default backend 容器挂掉,会不会同样触发该问题导致ingress机器单CPU 100% 问题?(待验证)