目录标题
- @[TOC](目录标题)
- 一、先理解告警在说什么(避免误判)
- 1️⃣ node_exporter 监控的是什么
- 2️⃣ 为什么危险
- 二、第一步:立刻判断「是真快爆了,还是阈值太低」
- 1️⃣ 看系统总 FD 上限
- 2️⃣ 当前已用 FD 数
- 3️⃣ 计算使用率
- 判断标准(经验值)
- 三、第二步:快速定位——是谁在吃 FD(最关键)
- 1️⃣ 找 FD 使用最多的进程(Top 排行)
- 2️⃣ 把 PID 翻译成进程名
- 四、第三步:判断是「正常高并发」还是「FD 泄露」
- 1️⃣ 看 FD 类型分布(非常重要)
- 2️⃣ socket 多 → 看网络连接
- 3️⃣ 文件多 → 看谁没 close
- 五、第四步:常见“真凶”模式(结合你的环境)
- 🚩 模式 1:数据库连接池失控
- 🚩 模式 2:日志 / 文件句柄泄露
- 🚩 模式 3:K8s 组件泄露(较常见)
- 六、第五步:临时止血 vs 根因治理
- 🔧 临时止血(不要当最终方案)
- 1️⃣ 提高系统级上限
- 2️⃣ 提高进程级限制
- 🧠 根因治理(真正该做的)
- 七、你可以直接照这个“最短排查路径”跑
目录标题
- @[TOC](目录标题)
- 一、先理解告警在说什么(避免误判)
- 1️⃣ node_exporter 监控的是什么
- 2️⃣ 为什么危险
- 二、第一步:立刻判断「是真快爆了,还是阈值太低」
- 1️⃣ 看系统总 FD 上限
- 2️⃣ 当前已用 FD 数
- 3️⃣ 计算使用率
- 判断标准(经验值)
- 三、第二步:快速定位——是谁在吃 FD(最关键)
- 1️⃣ 找 FD 使用最多的进程(Top 排行)
- 2️⃣ 把 PID 翻译成进程名
- 四、第三步:判断是「正常高并发」还是「FD 泄露」
- 1️⃣ 看 FD 类型分布(非常重要)
- 2️⃣ socket 多 → 看网络连接
- 3️⃣ 文件多 → 看谁没 close
- 五、第四步:常见“真凶”模式(结合你的环境)
- 🚩 模式 1:数据库连接池失控
- 🚩 模式 2:日志 / 文件句柄泄露
- 🚩 模式 3:K8s 组件泄露(较常见)
- 六、第五步:临时止血 vs 根因治理
- 🔧 临时止血(不要当最终方案)
- 1️⃣ 提高系统级上限
- 2️⃣ 提高进程级限制
- 🧠 根因治理(真正该做的)
- 七、你可以直接照这个“最短排查路径”跑
一、先理解告警在说什么(避免误判)
1️⃣ node_exporter 监控的是什么
通常告警来自:
node_filefd_allocated node_filefd_maximum或
node_filefd_allocated / node_filefd_maximum1657,320表示的是:
👉当前内核已分配的 file descriptor 总数
不是单进程,而是整台主机。
2️⃣ 为什么危险
当 FD 接近上限时,会出现:
accept()失败open()返回EMFILE / ENFILE新 TCP 连接失败
kubelet / containerd / DB 进程异常
表象可能是:
- 服务超时
- 连接数异常
- “偶发性”不可恢复故障
👉这是系统级“硬资源耗尽”,比 CPU 高更危险
二、第一步:立刻判断「是真快爆了,还是阈值太低」
1️⃣ 看系统总 FD 上限
cat/proc/sys/fs/file-max例如:
10485762️⃣ 当前已用 FD 数
cat/proc/sys/fs/file-nr输出示例:
667520 0 1048576解释:
已分配FD 未使用(废弃) 最大值👉核心看第一个数字
3️⃣ 计算使用率
awk'{printf "%.2f%%\n",$1/$3*100}'/proc/sys/fs/file-nr判断标准(经验值)
| 使用率 | 结论 |
|---|---|
| <50% | 安全 |
| 50–70% | 关注 |
| 70–85% | 高风险 |
| >85% | 随时炸 |
三、第二步:快速定位——是谁在吃 FD(最关键)
1️⃣ 找 FD 使用最多的进程(Top 排行)
forpidin/proc/[0-9]*;doecho"$(ls-1 $pid/fd2>/dev/null|wc-l)$(basename$pid)"done|sort-nr|head-20输出示例:
124532 32456 98321 1789 ...2️⃣ 把 PID 翻译成进程名
ps-fp32456或:
cat/proc/32456/comm🚨如果前 1–2 个进程占了 70%+ FD,99% 是泄露或配置不合理
四、第三步:判断是「正常高并发」还是「FD 泄露」
1️⃣ 看 FD 类型分布(非常重要)
ls-l /proc/<PID>/fd|awk'{print$NF}'|sed's/.*://'|sort|uniq-c重点关注:
| 类型 | 含义 |
|---|---|
socket | 网络连接 |
anon_inode | eventfd / epoll |
| 普通文件 | 文件未关闭 |
pipe | 管道泄露 |
2️⃣ socket 多 → 看网络连接
ss -anp|grep<PID>|wc-l进一步:
ss -s关注:
- ESTAB 数量
- TIME_WAIT 是否异常
- CLOSE_WAIT(最危险,典型 FD 泄露)
3️⃣ 文件多 → 看谁没 close
lsof-p<PID>|head是否看到:
- 相同路径被打开成千上万次
- 已删除文件
(deleted)仍被占用
五、第四步:常见“真凶”模式(结合你的环境)
结合你之前的背景(K8s / DB / 存储)👇
🚩 模式 1:数据库连接池失控
特征:
- socket FD 爆炸
- CLOSE_WAIT 多
- 进程:
postgres / oracle / oceanbase / app
原因:
- 应用未关闭连接
- 连接池 max 不设
- 异常路径没 close
🚩 模式 2:日志 / 文件句柄泄露
特征:
- 普通文件 FD 激增
- 大量
(deleted)文件
原因:
- 日志轮转不 reload
- 应用反复 open 不 close
🚩 模式 3:K8s 组件泄露(较常见)
进程:
- kubelet
- containerd
- dockerd(老集群)
特征:
- anon_inode / epoll 多
- socket 多
- 节点越跑越高,重启即恢复
六、第五步:临时止血 vs 根因治理
🔧 临时止血(不要当最终方案)
1️⃣ 提高系统级上限
sysctl -w fs.file-max=2097152持久化:
echo"fs.file-max=2097152">>/etc/sysctl.conf sysctl -p2️⃣ 提高进程级限制
ulimit-nsystemd 服务:
[Service] LimitNOFILE=1048576🧠 根因治理(真正该做的)
找到FD Top 进程
明确是:
- 连接池参数问题
- 异常路径未 close
- 内核 / runtime bug
用:
strace -p <pid> -e trace=open,close- 或应用级 metrics
七、你可以直接照这个“最短排查路径”跑
cat/proc/sys/fs/file-maxcat/proc/sys/fs/file-nrforpidin/proc/[0-9]*;doecho"$(ls-1 $pid/fd2>/dev/null|wc-l)$(basename$pid)"done|sort-nr|headps-fp<TOP_PID>ls-l /proc/<TOP_PID>/fd|headss -anp|grep<TOP_PID>|wc-l如果你愿意,下一步我可以直接帮你做:
- ✅结合 node_exporter 指标,设计一套 FD 泄露预警模型
- ✅把这次排查整理成一份《文件句柄耗尽故障排查 SOP》
- ✅你把 Top 进程 + FD 类型贴出来,我直接帮你判断是不是泄露