文章目录
- 前言
-
- shell-基于k8s/docker管理容器、监控模型训练所消耗的最大CPU与最大内存脚本
-
- [1. 基于docker管理容器、监控模型训练所消耗的最大CPU与最大内存](#1. 基于docker管理容器、监控模型训练所消耗的最大CPU与最大内存)
-
- [1.1. 使用](#1.1. 使用)
- [1.2. 源码](#1.2. 源码)
- [2. 基于k8s管理容器、监控模型训练所消耗的最大CPU与最大内存](#2. 基于k8s管理容器、监控模型训练所消耗的最大CPU与最大内存)
前言
如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!
shell-基于k8s/docker管理容器、监控模型训练所消耗的最大CPU与最大内存脚本
对于k8s管理容器来说,它与Docker管理容器对于 资源隔离机制 与 宿主机内核共享机制是不同的。
1. 基于docker管理容器、监控模型训练所消耗的最大CPU与最大内存
对于docker 容器启动时的状况 如果没有设置内存限制(如 --memory 或 --cpus),那么容器中的 free、top、htop、cat /proc/meminfo 等命令看到的,其实是宿主机的整体资源,而不是容器自己的资源。
设置限制内存的docker启动示例:
bash
docker run -d --name jupyter \
--memory=4g \
--cpus=2 \
-p 8888:8888 jupyter/base-notebook
1.1. 使用
启动:
bash
./tool.sh start 1
然后查看进程启动是否成功:
ps -ef | grep tool

脚本:tool.sh
start:第一个参数,代表启动;
1:第二个参数,代表每1秒查询一次;
执行ps -ef | grep tool后可以看到出现两个进程,21732为守护进程,作用是管理启动、停止、守护工作进程、当工作进程宕机时主动拉取。
执行./tool.sh start 1后可以看到,生成两个文件,一个是tool.pid文件,存储的是父进程的pid,一个是resource_monitor.log 文件,存储的是我们监听后持久到本地的指标。
效果:

可以看到运行期间最高占用与最高内存使用是变化的。
停止:
bash
./tool.sh stop

1.2. 源码
代码逻辑:
第一步停止守护进程;
第二步停止工作进程;
第三步备份指标历史记录;
第四步删除tool.pid存储守护进程id文件;
脚本源码:
bash
#! /bin/sh
cd `dirname $0` || exit 1
readonly FILE_NAME='tool'
BIN_ROOT=`pwd`
index=${2}
help(){
echo "${0} <start|stop>"
exit 1
}
run(){
interval=$1
while true; do
cd $BIN_ROOT
nohup sh tool_moudel.sh resource_monitor.log $interval </dev/null >/dev/null 2>&1
sleep 60
done
}
start(){
if [ $# -eq 1 ]; then
run ${1} &
echo $! > $FILE_NAME'.pid'
else
echo '缺失参数'
fi
}
stop(){
pid_file=${FILE_NAME}'.pid'
if [ -f "$pid_file" ]; then
pid=$(cat $pid_file)
rm $pid_file
echo "kill -9 $pid"
kill -9 $pid
echo "守护进程已停止"
else
echo "无法找到守护进程的PID文件"
fi
child_pid=$(ps -ef | grep "sh tool_moudel.sh" | grep -v grep | awk '{print $2}')
echo "子进程id:$child_pid"
if [ -z "$child_pid" ]; then
echo "子进程已停止"
exit 1
fi
echo "kill -9 $child_pid"
kill -9 $child_pid
if [ -f "resource_monitor.log" ]; then
mv resource_monitor.log "resource_monitor.log.$(date +%Y%m%d%H%M%S)"
echo "日志已备份"
fi
sleep 5
child_pid=$(ps -ef | grep "sh tool_moudel.sh" | grep -v grep | awk '{print $2}')
if [ -z "$child_pid" ]; then
echo "子进程已停止"
fi
}
case "${1}" in
start)
start ${2}
;;
stop)
stop
;;
*)
help
;;
esac
exit 1
tool_moudel.sh:
bash
#!/bin/sh
cd "$(dirname "$0")" || exit 1
BIN_ROOT=$(pwd)
check() {
if [ $# -lt 2 ]; then
echo "Usage: $0 <file_name> <interval>"
exit 1
fi
}
readonly FILE=$BIN_ROOT"/"$1
readonly interval=$2
init() {
# 获取 CPU 总核数(逻辑核)
CPU_TOTAL=$(nproc)
# 当前 CPU 使用核数(user + system 时间百分比换算)
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk -v total="$CPU_TOTAL" '{print ($2 + $4) * total / 100}')
# 当前内存使用量(MB)
MEM_USED=$(free -m | awk '/Mem/ {print $3}')
# 当前总内存(MB)
MEM_TOTAL=$(free -m | awk '/Mem/ {print $2}')
# 如果文件不存在,初始化文件
if [ ! -f "$FILE" ]; then
echo "运行期间最高占用${CPU_USAGE}核,最高内存使用${MEM_USED}MB,当前容器:${CPU_TOTAL}核,容器运行总内存:${MEM_TOTAL}MB" > "$FILE"
return
fi
# 从文件中读取上次记录的最大 CPU 和内存
LAST_LINE=$(cat "$FILE")
LAST_CPU_USED=$(echo "$LAST_LINE" | grep -oP '最高占用\K[0-9.]+')
LAST_MEM_USED=$(echo "$LAST_LINE" | grep -oP '最高内存使用\K[0-9.]+')
# 比较并取最大值
MAX_CPU_USED=$(echo "$CPU_USAGE $LAST_CPU_USED" | awk '{if($1>$2) print $1; else print $2}')
MAX_MEM_USED=$(echo "$MEM_USED $LAST_MEM_USED" | awk '{if($1>$2) print $1; else print $2}')
# 覆盖写入最新最大值
echo "运行期间最高占用${MAX_CPU_USED}核,最高内存使用${MAX_MEM_USED}MB,当前容器:${CPU_TOTAL}核,容器运行总内存:${MEM_TOTAL}MB" > "$FILE"
}
run() {
while true; do
cd "$BIN_ROOT"
init
sleep "$interval"
done
}
check "$@"
run
2. 基于k8s管理容器、监控模型训练所消耗的最大CPU与最大内存
说明:k8s的基于yaml做容器资源限制的,这时候,使用top、free之类的命令查询的是宿主机的资源,而不是容器内部本身的资源,因此对于查询最大CPU和最大内存的逻辑需要调整,其余地方保持一致即可。
示例:
bash
#!/bin/sh
cd "$(dirname "$0")" || exit 1
BIN_ROOT=$(pwd)
check() {
if [ $# -lt 2 ]; then
echo "Usage: $0 <file_name> <interval>"
exit 1
fi
}
readonly FILE=$BIN_ROOT"/"$1
readonly interval=$2
init() {
# 获取 CPU 总核数(逻辑核)
CPU_QUOTA=$(cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us)
CPU_PERIOD=$(cat /sys/fs/cgroup/cpu/cpu.cfs_period_us)
CPU_TOTAL=$(awk "BEGIN {print $CPU_QUOTA / $CPU_PERIOD}")
# 当前 CPU 使用核数
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print ($2+$4)/100 * '"$CPU_TOTAL"'}')
# 当前内存使用量(MB)
MEM_USED=$(($(cat /sys/fs/cgroup/memory/memory.usage_in_bytes)/1024/1024))
# 当前总内存(MB)
MEM_TOTAL=$(($(cat /sys/fs/cgroup/memory/memory.limit_in_bytes) / 1024 / 1024))
# 如果文件不存在,初始化文件
if [ ! -f "$FILE" ]; then
echo "运行期间最高占用${CPU_USAGE}核,最高内存使用${MEM_USED}MB,当前容器:${CPU_TOTAL}核,容器运行总内存:${MEM_TOTAL}MB" > "$FILE"
return
fi
# 从文件中读取上次记录的最大 CPU 和内存
LAST_LINE=$(cat "$FILE")
LAST_CPU_USED=$(echo "$LAST_LINE" | grep -oP '最高占用\K[0-9.]+')
LAST_MEM_USED=$(echo "$LAST_LINE" | grep -oP '最高内存使用\K[0-9.]+')
# 比较并取最大值
MAX_CPU_USED=$(echo "$CPU_USAGE $LAST_CPU_USED" | awk '{if($1>$2) print $1; else print $2}')
MAX_MEM_USED=$(echo "$MEM_USED $LAST_MEM_USED" | awk '{if($1>$2) print $1; else print $2}')
# 覆盖写入最新最大值
echo "运行期间最高占用${MAX_CPU_USED}核,最高内存使用${MAX_MEM_USED}MB,当前容器:${CPU_TOTAL}核,容器运行总内存${MEM_TOTAL}MB" > "$FILE"
}
run() {
while true; do
cd "$BIN_ROOT"
init
sleep "$interval"
done
}
check "$@"
run
启动脚本无需变化。