一、背景
阿里云k8s容器,在发布java应用程序的时候,客户端访问出现500错误。
后端服务是健康且可用的,网关层大量500错误请求,slb没有流入和流出流量。
经过回滚,仍未能解决错误。可谓是一次血的教训,特此记录下来,如果你也使用的是阿里云slb来实现k8s的service,值得一看,希望对你有所帮助。
在讲述这个事故前,我们还是照旧把系统架构交待清楚。
补充说明
指标的区别:一个k8s节点允许注册到slb的数量限制 与 一个slb允许注册的端口数量限制
前者在本文也未能找到查看之处,还望知晓的同学指点一二。示意图见下:
后者在文末的总结有说明,为了和前者进行对比,也画出其示意图:
这两个指标的理解对本文发生的事故非常重要。
二、系统架构
1、kong upsteam
配置的是slb的内网IP+端口号
2、k8s的服务service
3、slb监听虚拟服务器
下面是重点需要关注的,,虚拟服务器组下的四个服务器,对应的就是4个pod的ip地址。
本文所述的发布事故,就是这里的服务器没有及时更新导致。
4、pod的ip地址
绿色的“Running”,表示Pod节点运行健康。
我这里使用了服务注册中心consul,从consul也能佐证java服务是健康无疑。
当然我还进一步验证,直接访问pod的接口,比如/info和/health接口,返回的版本号和健康状态也都是正常。
三、问题排查
1、kong网关报错
23937#0: *2832787172 connect() failed (111: Connection refused) while connecting to upstream
request: request: "PUT /api/v3/pub/user/extend HTTP/1.1"
2、slb监控
可以看到,出现故障之后,连接数和流量将至零。也就是说,http请求没有能够进入后端pod节点。
3、k8s容器的服务service
Error syncing load balancer [lb-bpxxxxxxxxxx6ndspgh]: Message: There is backend server has reached to the quota limit number of load balancers that it could be related to.
根据错误信息,查找阿里云的帮助文档,https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-errorcodes
见下:
由此可见,是配额限制了。
继续查找文档,
https://help.aliyun.com/zh/slb/classic-load-balancer/product-overview/limits-1
可以看到,这里是默认50,所以我们到slb的配额设置查看,并申请调整至80。
申请调额:
四、踩过的坑
比较明确的一点是,问题出在slb。所以我们的思路,先是换一个,不行之后,又新建一个全新的slb。其实,问题在于我们忽视了k8s对很多指标的配额阈值。
1、slb的每个实例可以保有的监听数量超过了限制
所以尝试把k8s的服务service修改到另外一个slb,结果还是一样报错。
2、新建一个slb,跟上面的报错一样。
service状态一直是创建中
3、配额限制
我们缺少监控和报警,导致我们的思路,一直不能理解发布为啥会突然出错。
五、总结
1、Kong upstream配置pod IP
在没有解决问题前,只能在Kong的upstream配置pod IP,而非slb ip。虽然能解决,但是不够动态,显然是临时解决方案。
因为我们没有去做动态注册kong upstream。
2、阿里云的限额配置不直观
说同一台服务器可以重复添加为slb后端服务器的次数使用了53,可是到底是哪些,并不知晓。。为啥不弄个明细给用户可以查看。
3、每个实例可以保有的监听数量
这里已使用的数量达到85个。
像我购买了多个slb,好一通寻找。这里给你一个方向:
核实的方法是TCP关键词,统计其数量是否等于85.
可以看到,这个slb注册的tcp端口数更好是85,也是最多端口的slb。
4、架构的优化
- 去slb的依赖
- kong部署到k8s
- 引入ingress网关
- 使用k8s内部的发现机制