背景

最近遇到一个问题,线上老集群下线时,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请求才会停止)


【踩坑记录】Default backend 不存在导致ingress 机器CPU高载_Linux


ingress error.log 里面可以看到不断有新的请求进来

【踩坑记录】Default backend 不存在导致ingress 机器CPU高载_Linux_02


这也是为什么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


【踩坑记录】Default backend 不存在导致ingress 机器CPU高载_Linux_03


思考

触发需要2个条件,default backend 实例不存在 + 随机访问一个不存在的server_name (能进入default backend逻辑即可)

如果线上环境上default backend 容器挂掉,会不会同样触发该问题导致ingress机器单CPU 100% 问题?(待验证)