📊 OOM Killer 深度监控:进程、cgroup 和 namespace 配置 🔍查看 OOM Killer 详细信息 1.查看 OOM 杀死的历史记录 # 查看内核环形缓冲区中的 OOM 详细日志 sudo dmesg -T| grep -A30 -B5 "Out of memory" # 使用专门的 OOM 日志分析工具 sudo journalctl -k --grep= "oom\|out.of.memory" --since= "24 hours ago" # 查看被杀死进程的详细信息 sudo grep -i"killed process" /var/log/messages| tail -20# 更详细的 OOM 信息(包含内存统计) sudo journalctl -k| grep -i"oom_kill_process" -A10 2.查看当前内存压力状态 # 查看内存压力状态 cat /proc/pressure/memory# 监控内存压力变化 watch -n1 'cat /proc/pressure/memory' # 查看每个 NUMA 节点的内存统计 cat /proc/zoneinfo| grep -A5 "Node" # 查看页面分配失败统计(OOM 前兆) cat /proc/vmstat| grep -E"allocstall|pgalloc_dma" 📁进程级别的 OOM 配置查看 1.查看单个进程的 OOM 配置 # 查看指定进程的所有 OOM 相关文件 ls -la /proc/< PID> /oom_*# 查看 OOM 分数(越高越容易被杀) cat /proc/< PID> /oom_score# 查看 OOM 调整值(范围:-1000 到 +1000) cat /proc/< PID> /oom_score_adj# 查看进程的内存使用情况 cat /proc/< PID> /status| grep -A10 -E"Vm" # 查看进程的内存映射 cat /proc/< PID> /maps2.批量查看所有进程的 OOM 分数 # 查看所有进程的 OOM 分数和内存使用 for pid in $( ps -eo pid| grep -v PID) ; do if [ -f /proc/$pid /oom_score] ; then oom_score = $( cat /proc/$pid/oom_score2 > /dev/null) oom_adj = $( cat /proc/$pid/oom_score_adj2 > /dev/null) cmd = $( ps -p $pid -ocomm = 2 > /dev/null) echo "PID:$pid , CMD:$cmd , OOM Score:$oom_score , OOM Adj:$oom_adj " fi done | sort -k6 -rn| head -20# 更简洁的版本 ps -eo pid,comm,%mem --sort= -%mem| head -10| while read pid cmd mem; do [ -f /proc/$pid /oom_score] && \ echo "PID:$pid , CMD:$cmd , MEM:$mem %, OOM:$( cat /proc/$pid/oom_score) " done 🏗️Cgroup 相关的 OOM 配置 1.Cgroup v1(CentOS 7 默认) # 查看 cgroup 内存配置 ls -la /sys/fs/cgroup/memory/# 查看系统所有 memory cgroup find /sys/fs/cgroup/memory -name"memory.*" -type f| head -20# 查看特定 cgroup 的内存限制 cat /sys/fs/cgroup/memory/memory.limit_in_bytescat /sys/fs/cgroup/memory/memory.usage_in_bytes# 查看 cgroup 的 OOM 控制 cat /sys/fs/cgroup/memory/memory.oom_control# oom_kill_disable 0 = 允许 OOM Killer,1 = 禁用 # under_oom 0 = 没有 OOM,1 = 处于 OOM 状态 # 查看 cgroup 的内存统计 cat /sys/fs/cgroup/memory/memory.stat# 查看哪个 cgroup 发生了 OOM sudo dmesg | grep -i"oom_kill" | grep -o"cgroup.*" 2.Cgroup v2(如果启用) # 查看 cgroup v2 挂载点 mount | grep cgroup2# 查看 cgroup v2 内存配置 ls -la /sys/fs/cgroup/# 查看当前进程所在的 cgroup cat /proc/self/cgroup# 查看 cgroup 的内存限制和当前使用 cat /sys/fs/cgroup/memory.maxcat /sys/fs/cgroup/memory.current# 查看内存压力 cat /sys/fs/cgroup/memory.pressure3.Docker 容器的 OOM 配置 # 查看 Docker 容器的内存限制 docker inspect< container_id> | grep -i memory# 查看容器的 cgroup 路径 docker inspect< container_id> | grep Cgroup# 查看容器的 OOM 事件 docker events --filter'event=oom' --since'24h' # 查看容器内进程的 OOM 状态 docker stats --no-stream# 进入容器的 cgroup 查看详细配置 CONTAINER_ID = < your_container_id> CGROUP_PATH = $( docker inspect $CONTAINER_ID| grep Cgroup| cut -d'"' -f4) ls -la /sys/fs/cgroup/memory/docker/$CGROUP_PATH /🌐Namespace 相关的内存隔离 1.查看进程的 Namespace 信息 # 查看进程的 namespace ID ls -la /proc/< PID> /ns/# 查看进程所在的各个 namespace readlink /proc/< PID> /ns/mnt readlink /proc/< PID> /ns/pid readlink /proc/< PID> /ns/net readlink /proc/< PID> /ns/ipc readlink /proc/< PID> /ns/uts readlink /proc/< PID> /ns/user# 查看进程的 Mount namespace 中的内存文件系统 findmnt -N< PID> 2.查看 Namespace 中的内存配置 # 查看特定 namespace 中的内存信息 nsenter -t< PID> -mfree -h# 进入容器的 namespace 查看内存 nsenter -t< PID> -m -pcat /proc/meminfo# 查看不同 namespace 中的内存压力 nsenter -t< PID> -mcat /proc/pressure/memory🔧高级诊断工具 1.使用 systemd-cgtop 监控 cgroup # 按内存使用排序查看 cgroup systemd-cgtop --order= memory# 实时监控 cgroup 内存变化 watch -n1 systemd-cgtop --order= memory2.使用 cgroup-tools # 安装 cgroup 工具 yuminstall libcgroup libcgroup-tools# 查看所有 cgroup 子系统 lssubsys -am# 查看特定进程的 cgroup cat /proc/< PID> /cgroup# 查看 cgroup 配置 cgget -r memory< cgroup_path> 3.自定义 OOM 监控脚本 #!/bin/bash # oom-monitor.sh # 监控 OOM 事件 echo "=== OOM Killer 监控 ===" echo "1. 查看最近 OOM 事件:" journalctl -k --since= "1 hour ago" | grep -i"oom\|killed" | tail -5echo -e"\n 2. 内存使用前10的进程:" ps -eo pid,ppid,cmd,%mem,%cpu --sort= -%mem| head -11echo -e"\n 3. Cgroup 内存使用:" for cg in $( find /sys/fs/cgroup/memory -name"memory.usage_in_bytes" ) ; do usage = $( cat $cg) limit_file = $( echo $cg| sed 's/usage_in_bytes/limit_in_bytes/' ) if [ -f$limit_file ] ; then limit = $( cat $limit_file) if [ $limit -ne9223372036854775807 ] ; then usage_mb = $(( usage/ 1024 / 1024 )) limit_mb = $(( limit/ 1024 / 1024 )) echo "Cgroup:$( dirname $cg) , Usage:${usage_mb} MB, Limit:${limit_mb} MB" fi fi done | head -10echo -e"\n 4. 内存压力状态:" cat /proc/pressure/memory📊实战:分析 OOM 事件 1.完整 OOM 事件分析流程 # 步骤1: 查找最近的 OOM 事件 OOM_LOG = $( sudo journalctl -k| grep -B5 -A15"Out of memory" | tail -30) echo "$OOM_LOG " # 步骤2: 提取被杀死的进程信息 KILLED_PID = $( echo "$OOM_LOG " | grep "Killed process" | grep -o"pid [0-9]*" | awk '{print $2}' ) if [ ! -z"$KILLED_PID " ] ; then # 步骤3: 查看进程的 cgroup echo "进程$KILLED_PID 的 cgroup:" cat /proc/$KILLED_PID /cgroup# 步骤4: 查看进程的内存使用历史 if [ -d /proc/$KILLED_PID ] ; then echo "进程内存状态:" cat /proc/$KILLED_PID /status| grep -E"Vm|Rss" fi # 步骤5: 查看进程的 OOM 配置 echo "OOM 配置:" cat /proc/$KILLED_PID /oom_scorecat /proc/$KILLED_PID /oom_score_adjfi 2.Cgroup OOM 分析 #!/bin/bash # analyze-cgroup-oom.sh # 查找发生过 OOM 的 cgroup echo "查找发生过 OOM 的 cgroup:" find /sys/fs/cgroup/memory -name"memory.oom_control" | while read file ; do under_oom = $( grep "under_oom" $file| awk '{print $2}' ) if [ "$under_oom " == "1" ] ; then cgroup = $( dirname $file) echo "Cgroup$cgroup 处于 OOM 状态" echo " 内存使用:$( cat $cgroup/memory.usage_in_bytes) bytes" echo " 内存限制:$( cat $cgroup/memory.limit_in_bytes) bytes" fi done ⚙️配置建议和优化 1.保护重要进程 # 为重要进程设置 OOM 保护 echo "-1000" > /proc/< PID> /oom_score_adj# 对于 systemd 服务 [ Service] OOMScoreAdjust = -1000MemoryHigh = 90 %MemoryMax = 95 %2.Cgroup 内存限制最佳实践 # 为不同服务设置合理的 cgroup 限制 # /etc/systemd/system/myapp.service.d/memory.conf [ Service] MemoryLimit = 2GMemorySwapMax = 1G3.监控和报警配置 # 在 /etc/crontab 中添加定期检查 */5 * * * * root /usr/local/bin/check-oom-risk.sh# 使用 Prometheus node_exporter 监控 # 监控指标: node_memory_OOM_kill, node_memory_pressure