问题描述
某个环境,产品在使用过程频繁出现异常,获取日志发现报错提示:unable to create new native thread.
连 Pod 都无法进入。
问题排查
根据经验,先登录机器查看 ulimit,发现只有 1024。于是乎修改 ulimit 大小,再观察。
观察发现仍然在报同样的错误,重启 Pod 也无效。容器内部的 Java 进程使用的是 admin 用户启动,考虑到容器内部的用户 UID 本身是映射到宿主机用户 UID。此前就因为只修改了 root 用户的 ulimit 限制,没有修改宿主机对应用户 UID 的 ulimit 限制,导致类似无法创建线程的问题,切换到宿主机同样 UID 的用户,发现 ulimit 是正确的。
因为 Linux 系统里,PID 的限制对进程和线程本身是一样的。于是,拉起一个空的容器来测试,写一个测试脚本来创建 1024 个进程。
1 | #!/bin/bash |
运行测试脚本,发现确实会报错,提示无法继续创建进程。
怀疑是 K8s 对 Pod 内部的 PID 使用做了什么限制。查看kubelet
进程,未看到有类似 --pod-max-pids
的限制。
后来查看kubelet config
,发现有个SuuportPodPidsLimit
的FeatureGate
。
这个集群使用的 K8s 是OpenShift
,查找 OpenShift 相关的资料(https://skybert.net/linux/openshift-container-running-out-of-pids-all-the-time/)。
发现SupportPodPidsLimit
这个就是用来限制 Pod 内部的 PID 数量。在普通的 K8s 集群里,SupportPodPidsLimit
这个是默认关闭,而在 OpenShift 里,SupportPodPidsLimit
这个参数确实默认开启的。联系这个 Openshift
的集群运维,修改参数关闭 SupportPodPidsLimit
,再次运行测试脚本,发现就可以正常运行了。
最后补充一下,宿主机的 ulimit 设置可以通过以下命令查看:cat /proc/sys/kernel/pid_max
。