首页 > 应用开发 > Go语言 > 我为什么劝你别用Kubernetes做车联网网关
上个月,一个做车联网的兄弟找我,说他们网关上了K8s,结果终端批量掉线。
我问他:你网关怎么部署的?
他说:Deployment,三个副本,Service做负载均衡。
我说:TCP长连接,你用什么负载均衡?
他说:K8s Service啊。
我沉默了。
K8s Service做TCP长连接负载均衡的致命问题
K8s Service默认是iptables模式。iptables做四层负载均衡,是基于连接跟踪的。什么意思?一个TCP连接建立时,iptables随机选一个Pod,之后所有数据包都走这个Pod。
听起来没问题?问题大了。
Pod重启、滚动更新、扩缩容,连接跟踪表会失效。已经建立的TCP连接,因为后端Pod变了,直接断。
你的终端在高速上跑着,突然网关断连,终端开始重连。几万台终端同时重连,你的网关直接被打挂。
这不是K8s的错,是你的错。K8s Service本来就不是给长连接设计的。
我们踩过的坑
2021年,我们网关上了K8s。三个副本,滚动更新。
第一次滚动更新,10%的终端掉线,重连后恢复。我们没在意,觉得重连是正常的。
第二次滚动更新,30%的终端掉线。部分终端重连失败,因为网关负载太高。
第三次滚动更新,50%的终端掉线。客户投诉电话打爆了。
我们排查了一周,发现两个问题:
第一,滚动更新时,旧Pod被杀死,上面的TCP连接直接断。终端要重新注册、鉴权、同步参数。几万台终端同时做这些操作,网关扛不住。
第二,K8s Service的会话保持有问题。终端重连后,可能被分配到另一个Pod,之前的会话状态丢了。如果会话状态存在内存里,新Pod没有这个终端的上下文。
车联网网关为什么不适合K8s
我总结了几个原因:
第一,长连接和K8s的设计理念冲突。
K8s假设你的服务是无状态的,可以随时创建、销毁、迁移。但TCP长连接是有状态的。一个终端连到一个Pod,这个Pod就承载了这个终端的会话。Pod死了,会话就断了。
第二,终端不会优雅重连。
Web服务的客户端是浏览器,断线重连用户无感。车联网的终端是车载设备,重连逻辑千奇百怪。有的终端重连间隔1秒,有的重连10次失败就进入休眠。几万台终端同时重连,就是DDoS。
第三,网络抖动影响大。
K8s的网络模型,Pod之间通过Overlay网络通信。Overlay网络比宿主机网络多一层封装,延迟更高。车联网对延迟敏感,位置上报延迟超过5秒,客户就会投诉。
那车联网网关怎么部署?
我们后来的方案:
不用K8s,直接用物理机或虚拟机
网关用主备模式,主节点承载全部连接,备节点热备
主备切换用Keepalived + VIP,终端无感
单机100万连接,够用了
如果非要容器化,用Docker,但不要用K8s编排。用systemd管理容器,或者用Nomad这种更轻量的编排工具。
什么人适合用K8s做网关?
如果你的终端是短连接,每次请求都新建连接,那K8s没问题。
如果你的终端数量少,几千台,掉线重连影响不大,那K8s也可以。
但如果你的终端是长连接,数量几万甚至几十万,K8s Service做负载均衡就是灾难。
总结
K8s是好东西,但不是银弹。车联网网关的部署方式,要根据连接模型来选。长连接场景,简单的主备 + VIP,比K8s靠谱得多。
JTE的部署方案里,网关层默认推荐主备模式,而不是K8s。这不是保守,是被坑过。
项目仓库:
Gitee:suoten/jt-engine GitHub:suoten/JTEngine
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70050062/viewspace-3184170/ ,如需转载,请注明出处,否则将追究法律责任。