问题现象
有应用A和应用B,应用A通过 svc-1 把请求转发给应用B,整体请求链路:
应用A pods -> svc-1 -> 应用B pods
整体接口请求量QPS 2W+,A和B在同一个VPC内的同一个K8S集群,POD数约为 1:10;
应用B因为意外全量POD重启后,应用A转发svc-1提示报错 "No route to host"
原因定位
k8s svc 原理是通过linux的连接跟踪 & ipvs/iptables对请求进行转发,在线上高并发请求下,产生了大量的短连接,这些短连接会记录到本地的连接跟踪表中,并产生大量 time-wait的连接;
应用B重启期间,ipvs 将老的pod IP权重置为0,而这些time-wait的连接在ipvs中会被统计为InActConn,因此这些老的pod IP 在这些time-wait连接没释放,不会释放;
而在五元组(tuple)信息:源端口 + 源IP + 目的端口 + 目的IP + 协议 都 不变的情况下,ipvs 不会对新连接进行重新负载,而是复用之前的负载结果,将新连接转发到原来的pod IP上;
应用B重启后,由于应用A之前记录在本地连接跟踪表的记录还存在,导致A还是把请求转发给了应用B那些老的pod IP,而原来的pod早已销毁,所以报错"No route to host"。
解决手段
临时止血处理
重启应用A,从而销毁应用A本地连接跟踪表
后续优化手段(TODO)
总结感悟
生产环境高并发带来的挑战除了性能问题外就是排查各种令人头大的“幺蛾子”问题,线上五花八门复杂的情况 + 大流量高并发让原本低概率事件变成100%会发生,这些“幺蛾子”排查难度大、成本高、耗时耗力,定位此次事故原因多亏了公司的运维大佬!我作为业务层应用开发对这些偏底层的网络问题“力不从心”,这也是后续自己要强化的点。
参考资料
Kubernetes 疑难杂症排查分享: 诡异的 No route to host
Service IP not available (no route to host) after pod has been restarted on another node. #24092