Linux服务器节点性能问题排查和优化思路
- [1. atop安装](#1. atop安装)
- [2. 整体思路](#2. 整体思路)
-
- [2.1 如果现场存在/能复现](#2.1 如果现场存在/能复现)
- [2.2 如果现场不能复现:](#2.2 如果现场不能复现:)
- [3. 高负载问题排查与应对](#3. 高负载问题排查与应对)
-
- [3.1. hung task 问题](#3.1. hung task 问题)
- [3.2. 底层硬盘/文件系统无法写入](#3.2. 底层硬盘/文件系统无法写入)
- [3.3. IO性能不足导致的运行缓慢](#3.3. IO性能不足导致的运行缓慢)
- [3.4. CPU 性能不足导致的运行缓慢(由程序引起)](#3.4. CPU 性能不足导致的运行缓慢(由程序引起))
- [3.5. CPU性能不足导致的运行缓慢(由 steal 高引起)](#3.5. CPU性能不足导致的运行缓慢(由 steal 高引起))
- [3.6. CPU性能不足导致的运行缓慢(由软中断 si 引起)](#3.6. CPU性能不足导致的运行缓慢(由软中断 si 引起))
- [3.7.容器 LIMIT 设置不当导致运行缓慢/负载高](#3.7.容器 LIMIT 设置不当导致运行缓慢/负载高)
- [3.8. 内存不足导致 cache 频繁刷盘](#3.8. 内存不足导致 cache 频繁刷盘)
- [4. 程序相关性能问题](#4. 程序相关性能问题)
-
- [4.1. CPU相关](#4.1. CPU相关)
- [4.2. 磁盘相关](#4.2. 磁盘相关)
-
- [4.2.1. 磁盘用满](#4.2.1. 磁盘用满)
- [4.2.2. 磁盘IO性能不足导致程序故障](#4.2.2. 磁盘IO性能不足导致程序故障)
- [4.2.3. IO 被突发写入干扰导致不稳定](#4.2.3. IO 被突发写入干扰导致不稳定)
- [4.2.4. 底层IO速度不稳定](#4.2.4. 底层IO速度不稳定)
- [4.2.5. 底层IO速度不稳定且监控正常](#4.2.5. 底层IO速度不稳定且监控正常)
- 4.3.内存相关
-
- [4.3.1. available 内存不足导致程序无法正常启动/使用](#4.3.1. available 内存不足导致程序无法正常启动/使用)
- [4.3.2. pod的limit 不足/泄漏导致某个容器 OOM](#4.3.2. pod的limit 不足/泄漏导致某个容器 OOM)
- [4.3.3. 内存不足/泄漏导致整机 OOM](#4.3.3. 内存不足/泄漏导致整机 OOM)
- [4.3.4. 内存物理故障导致程序异常](#4.3.4. 内存物理故障导致程序异常)
- [5. 节点进程性能分析](#5. 节点进程性能分析)
-
- [5.1. R/D进程查看](#5.1. R/D进程查看)
- [5.2. 进程CPU/IO/内存用量分析](#5.2. 进程CPU/IO/内存用量分析)
- [5.3. 短进程分析](#5.3. 短进程分析)
-
- [5.3.1. 使用 atop 初步分析](#5.3.1. 使用 atop 初步分析)
- [5.3.2. 使用 bcc 拉取短进程清单](#5.3.2. 使用 bcc 拉取短进程清单)
- [5.4. 进程 IO 分析](#5.4. 进程 IO 分析)
-
- [5.4.1. 使用 atop 分析](#5.4.1. 使用 atop 分析)
- [5.5. 内存泄漏分析](#5.5. 内存泄漏分析)
-
- [5.5.1.使用 atop 分析](#5.5.1.使用 atop 分析)
本文档分为三个部分研究和解决节点性能问题:
- 高负载问题的排查与应对:主要解决的问题是,已经知道了节点存在高负载的问题,要怎么办?
- 程序相关的节点性能问题:主要讨论的问题是:如果已经知道了是某个程序存在性能问题,但是不知道和节点有没有关系?这里我们会介一些节点问题相关的应用性能问题的排查方法和解决思路。本文档并不会涉及到和业务相关的内容,业务自身的问题可以通过应用的可观测进行排查(如 golang pprof、监控、日志等),互为补充。
- 节点进程洞察:主要讨论的问题是:如果我们已经确定了节点存在某些方面的问题,但是还不知道是哪个进程导致的?
1. atop安装
本教程以 atop 为主要工具,目标是给大家一些排查的思路。如果 atop 无法使用也可以使用 top 和 iostat 代替。
如下3种方法均可以安装
- 编译安装
bash
wget https://www.atoptool.nl/download/atop-2.7.1.tar.gz && tar zxvf atop-2.7.1.tar.gz && cd atop-2.7.1
make && make install
- yum安装
bash
yum install atop -y
2. 整体思路
2.1 如果现场存在/能复现
- 先看负载高不高,高说明程序运行不顺畅,可以按照文档下面的高负载排查思路排查
- 负载不高的话,主要考虑是程序自身的问题,优先从程序侧排查
- 容器的进程是否还在,如果不在则考虑幽灵容器的问题
- 排除磁盘满了,然后再看磁盘是否繁忙,一直繁忙的话说明磁盘性能不足,可能会影响写入程序的性能
- 再看内存的 available 量,判断 available 是否足够
- 网络问题通常比较明显:丢包/无回包/无法连接
2.2 如果现场不能复现:
- 如果已经预装了 atop,可以查看 atop 的历史,同样是首先观察负载的情况
- 如果云哨采集到了数据,可以在 grafana 上面查看
3. 高负载问题排查与应对
linux 计算 load的方法可以参考文档 一文说清linux system load
从上述load的计算原理可以看出,导致load 飙高的原因,负载和 R 与 D 的线程数有直接关系
- R 多说明程序处理不过来
- D 多说明 IO 处理不过来或者 IO 链路上有故障/卡点
- 僵尸进程则需要分析相关僵尸产生的原因和修复
以下几种情况都会导致节点的负载高
- 系统内核的问题
- hung task 问题
- CPU 不足问题
- 程序太多/程序用的 CPU 太多
- steal 高
- 软中断高
- sys 高
- IO 的问题
- 磁盘 IO 性能不足
- 磁盘 IO 卡住
- 内存的问题
- 内存不足
- 容器 Cgroup 的问题
- 容器的 CPU Limit 设置过小
我们主要通过以下一些观测手段来确定是哪种问题
- 观察 CPU 的一些指标,包括 CPU Idle,sys, si, st (这些可以直接通过 top 或者 atop 看到)
- 观察磁盘的 IO 指标,IO 读写速度和 IO 使用率、D 进程数量 (IO指标可以通过 atop 或者 iostat 看到,D进程数量可以参考第三章的"R/D 进程查看")
- 观察内存的 available,VGROW,PAG 指标(可以通过 free 和 atop 查看)
- 查看 dmesg -T 和 /var/log/message 的日志,查看系统有没有报一些错误日志
表 | 链 |
---|---|
filter | INPUT、FORWARD、OUTPUT |
nat | PREROUTING(DNAT)、OUTPUT、POSTROUTING(SNAT) |
mangle | PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING |
raw | PREROUTING、OUTPUT |
3.1. hung task 问题
-
现象:CPU 正常,io busy 正常,D 进程多,iowait 较高
-
分析:查看 dmesg -T 发现有无 hung_task_timeout 的日志,如果有说明是内核发生了死锁
-
解决办法:
可以先执行以下命令导出 vmcore 并重启机器
bash
echo 1 > /proc/sys/kernel/hung_task_panic
重启后可以通过配置内核参数自动检测并且重启,参数为
bash
kernel.hung_task_panic = 1kernel.hung_task_timeout_secs = 1200
3.2. 底层硬盘/文件系统无法写入
-
现象:CPU 正常,io busy 正常,D 进程多,iowait 正常
-
分析:atop 使用输入 Q 和 D,可以查找 D 进程,需要再按 a 查看所有的不活跃的 D 进程。我们发现基本都没有写入速度,说明是底层磁盘或者文件系统出现了故障。
-
解决方法:可以通过 dmesg -T 看看有没有 NFS 的提示,如果没有挂载 NFS,一般是 IaaS 盘掉速导致的,要在 Iaas 侧处理
3.3. IO性能不足导致的运行缓慢
-
现象:CPU 正常,io busy 高,D 进程多,iowait 高
-
分析方法 1:atop 使用输入 Q 和 D,可以查找 D 进程,需要再按 a 查看所有的不活跃的 D 进程。我们发现 D 多且都有比较大的写入速度,说明是写入的程序很多,磁盘性能不足导致的
-
解决方法:检查写入的程序是否符合预期,或者提高 IaaS 的磁盘性能
-
分析方法 2:如果是物理机,也有可能是磁盘出现坏道,可以通过 dmesg -T 检查 Buffer I/O Error 信息
-
解决方法:更换磁盘
3.4. CPU 性能不足导致的运行缓慢(由程序引起)
现象:CPU 高(>=70%),IO 正常,D 进程少,steal(st) 低,irq(si) 低, sys 低
- 这个时候会有几种可能性
- 有几个特别高的,说明是可能是程序自己有异常
- 可能没有特别高的,则说明加起来不低,CPU 性能不足(比如,TCE 存在很多短进程,会占用很多基本的 CPU 资源),ps:CPU 有超线程/线程切换等原因,idle 可能会在还有挺多(如 30% 的时候),负载就不太好了,这也属于 CPU 性能不足
- 解决方法:
- 有某几个 CPU 特别高,看看是否是程序异常,如果不是异常,则看看能否横向扩展(即多搞几个副本)或者迁移
- 减少机器上的进程数量或单个进程用的 CPU(属于长期优化)
3.5. CPU性能不足导致的运行缓慢(由 steal 高引起)
- 现象:CPU 高(>=70%),IO 正常,D 进程少,steal 高
- 分析:使用 atop 可以看 steal 值
使用 top 可以查看 st 值,steal 是虚拟化程序(如 KVM,VMWARE)告诉虚拟机的 CPU 被挪用的一个接口,虚拟机侧无法解决,只能通过调整母机的超卖比例
- 解决方法:联系 IaaS 降低 steal
3.6. CPU性能不足导致的运行缓慢(由软中断 si 引起)
-
现象:CPU 高(>=70%),IO 正常,D 进程少,si 高,网络可能会有丢包
-
分析:使用 top 查看 cpu 的 si 比较高
使用 atop 可以查看到 irq 值,如果只显示了总的,可以输入 l 999 一直回车,即可显示所有 CPU 的,可能会有多个 CPU 的 si 非常高
-
解决方法:
- 需查看 iptables-save | wc -l 规则数,正常环境不会超过15000 条,需要网络侧继续分析
- 有可能是硬件故障,可以看 /var/log/messages
3.7.容器 LIMIT 设置不当导致运行缓慢/负载高
- 现象:CPU 正常,io busy 正常,D 进程正常,程序运行缓慢
- 分析:这个可通过 atop 分析发现,在 atop 的默认面板中,我们可以看到某些进程的 RDELAY 非常高,这些是需要注意的
我们使用一个 stress-ng 的富容器来模拟了这个情况,我们可以通过查看 RDELAY 时间超过 1s 的大概率是被 cgroup throttle 了,如果线程多或者进程多,则会直接推高负载,而背后的原因主要是容器 CPU LIMIT 设置不当
- 解决方法:把容器放开到合适的 limit
3.8. 内存不足导致 cache 频繁刷盘
-
现象:CPU 正常,io busy 较高,D 进程正常,sys 高,内存较低
-
分析:有可能有 PAG 数据显示,表示 cache 在刷盘
-
解决方法:
- 一种情况是老的环境 vm.min_free_kbytes 设置的太大了,导致虽然有 free 内存但是也一直在回收 cache,导致节点卡死,这里我们目前可以调整为 262144:vim /etc/sysctl.d/99-tcs.conf 然后通过 sysctl -p 99-tcs.conf 生效
- 一种情况是程序导致的,这种情我们一方面可以查看一下内存有没有泄露(下面章节),如果是程序本身规模变大的话,就只能考虑机器升配。
4. 程序相关性能问题
4.1. CPU相关
CPU 问题一般都会导致节点高负载,思路和问题可以参考上一章,我们可以重点关注容器的 limit 设置和节点 CPU 的剩余情况
4.2. 磁盘相关
4.2.1. 磁盘用满
- 现象:程序无法正常写入,节点被迁移或被禁止调度
- 分析:使用 df -h 查看磁盘是否超过 90%
- 解决方法:清理磁盘
4.2.2. 磁盘IO性能不足导致程序故障
- 现象:磁盘繁忙程度高,写入主要由单个程序引起
- 分析:使用 atop 查看,VDB 磁盘繁忙程度高,且写入速度达到了 IaaS 宣称的值
输入 d 转到 IO 面板,可以看到写入高的进程:
这里可以看到是压测的进程,实际环境有可能是 etcd 进程,且无其他进程,如果长时间保持这种繁忙的状态,说明磁盘 IO 不能适应程序的要求
- 解决方法:
- 判断程序的 IO 写入是否正常
- 升级磁盘配置
4.2.3. IO 被突发写入干扰导致不稳定
- 现象:曾经有一段时间 IO 写入变慢,可能导致了切主之类的问题,后续又恢复正常,看监控发现异常时间段有尖峰
- 分析:初步分析的话,我们可以先看监控磁盘的 iowait 和 iops 等数据看看有无凸起,可以通过监控数据,可以看到这些数据
- 解决方法:找到尖峰的程序,和他做好隔离或者限制
4.2.4. 底层IO速度不稳定
-
现象:看监控,过去有一个时间段,突然有一段时间写入速度下降或者变慢
-
分析:一般都是底层 IO 速度不稳定导致的
-
解决方法:联系 IaaS 同学协助定位
4.2.5. 底层IO速度不稳定且监控正常
- 现象:曾经有一段时间 IO 写入变慢,可能导致了切主之类的问题,后续又恢复正常,看监控发现异常时间段磁盘 IO 无异常
- 分析:这种非常细小的抖动,节点监控中可能看不到,一方面我们要从业务层监控观察到这种性能不稳定的现象,然后再反过来排查节点的性能问题,如果节点监控中表现不明显,这个时候可以考虑看看 IaaS 侧的监控有无异常
- 解决方法:联系 IaaS 同学协助定位
4.3.内存相关
4.3.1. available 内存不足导致程序无法正常启动/使用
- 现象:
- available 内存较小,有的程序无法启动或者无法正常运行'
- atop 中一直显示 PAG 信息,说明系统正在不断的回收内存,也可以判断系统的内存处于不足的状态
-
分析:程序的内存可能会有一个大的申请量,available 如果较小(如 5G),即使大于程序预期的内存申请量,也要留意有无可能是内存不足的问题
-
解决方法:转移需要大内存的程序,如果无法转移则需要扩大节点内存
-
原理:
available 计算的是 cached 和 slab 里面可以回收的内存 + free 内存计算得来的,当程序申请的内存超过 free 内存的时候,linux 就会从 cache 和 slab 回收内存。但是这里可能会发生一些问题,就是有些程序会有持续的读写或者某些原因,cache 回收之后又会马上用上。或者是 available 的计算也会出现不准确的情况。这就导致 available 可能仍然足够,但是程序也无法申请到足够多内存。比如,某个环境 etcd 内存占用较大需要 5G 内存,但是此时 available 仍有 6G,也出现了无法启动的情况。
4.3.2. pod的limit 不足/泄漏导致某个容器 OOM
- 现象:整机内存 available 比较充足,dmesg 中有看到某个容器发生了 OOM,或者在 pod 的状态里面看到 OOM
- 分析:limit 不足,如果程序申请超过了这个值,则会 OOM,这有可能是正常的因为业务侧压力增大,也有可能是不正常的内存泄漏
- 解决方法:
- 短期优化:调大 limit,检查有无内存泄漏
- 长期优化:告知程序容器的 limit 限制,让内部尽快的回收内存
4.3.3. 内存不足/泄漏导致整机 OOM
- 现象:整机的内存严重不足,linux 会对内存最大的程序优先进行 OOM Kill 操作
- 分析:dmesg 中会显示日志
- 解决方法:
- 分析有无程序发生了内存泄漏,如果是容器的话,可以从监控中看到容器的内存指标一直向上走的状态,如果是宿主机进程的话可以使用 atop 分析(详见下方的『内存泄漏分析』)
- 也有可能是因为程序负载过大导致的,可以优化程序或者转移程序,或者做机器升配
4.3.4. 内存物理故障导致程序异常
-
现象:dmesg 或者在 messages 中显示内存校验不过等信息
-
分析:内存物理故障一例,可以看 /var/log/messages 日志
-
解决办法:联系 Iaas 侧修复
5. 节点进程性能分析
我们已经确定了节点存在某些方面的问题,并且通过 atop 工具无法观测到是哪个进程导致的,这里介绍一些工具和方法
5.1. R/D进程查看
使用 atop,首先需要按 Q ,然后按 R 或 D 筛选 R/D 进程,我们主要关心 D 进程的数量
5.2. 进程CPU/IO/内存用量分析
使用 atop ,输入 i 60,把 atop 的分析时间调整为 60s,然后等待 60s 页面刷新后,按 z 暂停住页面,可以看到各个程序的各种资源用量
我们可以主要观察几个指标,CPU,MEM,RGROW,RDDSK,WDDSK,RELAY,我们可以通过按 m 来切换到内存面板,按 g 回复到默认面板
如果是多进程的程序(如 nginx),我们也可以在 atop 中按 p 按照进程名聚合,或者按 j 安装容器名聚合,这样可以更直观的看到哪些程序
linux 计算 load的方法可以参考文档 https://zhuanlan.zhihu.com/p/445753426
从上述load的计算原理可以看出,导致load 飙高的原因,说简单也简单,无非就是runnable 或者 uninterruptible(僵尸或者D进程) 的task 增多了
5.3. 短进程分析
5.3.1. 使用 atop 初步分析
我们也可以用 atop 来分析短进程的情况,短进程是 TCE 的一个特色,因为健康检查的脚本非常多
我们在 atop 中输入 i 60,然后等待 60s 的时间,抓取所有出现的进程,然后按 z 暂停住页面,即可看到右上角显示的,这段时间退出的 7039 个进程
5.3.2. 使用 bcc 拉取短进程清单
使用 bcc 的 execsnoop 工具,可以拉取所有新建出来的进程,然后我们聚合一下就可以得到短进程的清单
- 镜像组件的健康检查,bash 的健康检查会连带拉起 runc 和 containd 多个进程,bash 内部也会拉起 netstat, grep, curl, wc, ps, mysql mysqladmin 等多个进程,每秒会产生大约100+个进程2. ruler-daemon 每秒产生10+个iptables进程3. npd 每秒产生 10+ 个进程
5.4. 进程 IO 分析
我们可以先看监控看到磁盘的 IO 有一些毛刺,然后我们就可以使用 atop 或者 sysak 找到是哪个容器或者进程
5.4.1. 使用 atop 分析
可以参考配置 atop 采集周期为 1s 每次,然后放到环境中采集一段时间,得到采集数据后,再回看监控中出现毛刺的时间,来回看 atop 的数据,这里主要看两点
- 磁盘的 busy 程度,只有磁盘非常 busy 才比较可能对其他程序有影响
- 分析此时 IO 中的进程即可
这里我们就可以分析是 fio 导致磁盘写满,影响了其他的程序
5.5. 内存泄漏分析
基本思路我们还是先看容器的监控,来看看进程有没有内存的直线上升的情况,如果不是容器的话我们可以通过 atop 来分析内存的增量
5.5.1.使用 atop 分析
atop 提供了 RGROW 内存增量的监控项,因此我们可以直接分析内存的增量情况,我们也可以通过中配置 atop 采集历史的数据,来判断程序是否存在内存泄露
通过多次采集时间的对比,我们就可以发现内存泄漏,下图是一个比较明显的内存泄漏的模拟