现象
在K8S中部署MySQL进行测试,发现连接数上不去,卡在1000内。查看MySQL日志,报错信息为
Can't create thread to handle new connection(errno= 11)
排查过程
根据报错信息可以初步判断是pod的线程数被限制了,按照这个信息,进入pod里面查看ulimit信息,发现相关配置项都设置的比较大,可以排除是ulimit设置错误导致的。
之后根据K8S和线程作为关键字在网上检索,可以发现kubelet中有个配置是控制每个pod的进程数,具体的可以看kubeletConfiguration中的podPidsLimit配置和kubelet的pod-max-pids参数。但是发现环境中的这个值取的是-1,即每个pod的进程数限制等于主机的最大进程数。
考虑到K8S中实际是由CRI去创建容器的,有没有可能是CRI里面限制了pod的进程数量?这里的CRI选的是CRI-O,于是查看对应的配置文件(/etc/crio/crio.conf),发现有个类似podPidsLimit的配置
# Maximum number of processes allowed in a container.
pids_limit = 1024
到这里基本可以确定就是这个配置导致的,之后修改这个配置并再次测试也确认了就是这个配置导致的。之后在Github上也找到了类似的问题。
解决方法
解决的方法有两个:
1. 修改crio配置,重启相关服务
2. 升级crio到v1.24.0以上的版本
总结
如果在K8S中的应用遇到无法创建新线程的错误,都可以按照上述方法,检查和修改kubelet以及CRI的配置来排查。