踩了K8s Pod内部PID限制的一个坑

问题描述

某个环境,产品在使用过程频繁出现异常,获取日志发现报错提示: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
2
3
4
5
6
7
8
9
#!/bin/bash

for i in {1..1024}
do
echo "Process: ${i}"
( sleep 600 & )
done

wait

运行测试脚本,发现确实会报错,提示无法继续创建进程。

怀疑是 K8s 对 Pod 内部的 PID 使用做了什么限制。查看kubelet进程,未看到有类似 --pod-max-pids的限制。

后来查看kubelet config,发现有个SuuportPodPidsLimitFeatureGate

这个集群使用的 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

感谢您请我喝咖啡~O(∩_∩)O,如果要联系请直接发我邮箱chenx1242@163.com,我会回复你的
-------------本文结束感谢您的阅读-------------