docker热重启,临时解决docker内存泄漏问题
#!/bin/bash
#####################################自定义变量区
#内存阈值
host_mem_limit=60 #主机内存占用阈值,单位%(百分比)
max_mem_gb=5 ##dockerd内存占用阈值,单位GB
###########################业务方法区####################################
hotRestartDockerd(){
echo "hotRestartDockerd"
DOCKERD_CONF='/etc/docker/daemon.json'
[ ! -f "$DOCKERD_CONF" ] && echo "error, failed to find $DOCKERD_CONF " && exit 1
[ ! -s "$DOCKERD_CONF" ] && echo "error, $DOCKERD_CONF is empty" && exit 2
DOCKERD_PID=$(systemctl status docker | grep "Main PID" | awk '{print $3}')
[ -z "$DOCKERD_PID" ] && echo "error, dockerd is not running" && exit 3
# enable Live Restore
CHANGED=""
if !( docker info | grep -i "Live Restore Enabled" | grep -i "true" > /dev/null ) ; then
echo "enable Live Restore "
cp -f $DOCKERD_CONF $DOCKERD_CONF-backup
sed -i '/live-restore/ d' $DOCKERD_CONF
sed -i -E 's/^\{$/\{\n "live-restore": true , /' $DOCKERD_CONF
CHANGED="1"
kill -SIGHUP $DOCKERD_PID
sleep 5
if !( docker info | grep -i "Live Restore Enabled" | grep -i "true" > /dev/null ) ; then
echo "error, failed to enable Live Restore "
exit 4
fi
fi
systemctl restart docker
echo "restarting docker "
OK=""
for((i=0;i<10;i++)) ; do
sleep 4
( systemctl status docker | grep "Active: active (running)" &> /dev/null ) \
&& OK="1" && break
done
[ -z "$OK" ] && echo "error, failed to restart docker" && exit 5
if [ -n "$CHANGED" ] ; then
sed -i '/live-restore/ d' $DOCKERD_CONF
sed -i -E 's/^\{$/\{\n "live-restore": false , /' $DOCKERD_CONF
kill -SIGHUP $(systemctl status docker | grep "Main PID" | awk '{print $3}')
rm -f $DOCKERD_CONF
mv $DOCKERD_CONF-backup $DOCKERD_CONF
sleep 5
fi
echo "finished restarting dockerd"
}
restartSpecialCon(){
echo "restart related contariners which wants to communicate with "
LIST=` docker inspect $(docker ps -q)|grep 'Source.*docker.sock\|Name": "/'|grep sock -B1|grep Name | awk -F'"' '{print $4}' | sed 's/^\///' `
[ -z "$LIST" ] && echo "no container needed to restart , finish" && return 0
for NAME in $LIST ; do
docker restart $NAME
done
}
#判断docker的文件系统是否为xfs,非xfs如果daemon.json设置了overlay2.size会导致docker重启异常
checkFileSystem(){
local daemonPath="/etc/docker/daemon.json"
backing_fs=$(docker info | grep "Backing Filesystem" | awk '{print $3}')
if [ "${backing_fs}" = "extfs" ]; then
# 检查/etc/docker/daemon.json文件中是否配置了overlay2.size
if grep -q "overlay2.size" ${daemonPath}; then
sed -i '/"storage-opts": \[/,/]/d' ${daemonPath}
fi
fi
# 检查倒数第二行是否以逗号结尾
second_last_line=$(tail -n 2 "${daemonPath}" | head -n 1)
if [[ ${second_last_line} =~ ,$ ]]; then
# 删除倒数第二行的逗号
sed -i '$!N;$s/,\n/\n/;P;D' "${daemonPath}"
echo "已删除倒数第二行的逗号"
else
echo "倒数第二行不以逗号结尾,无需删除"
fi
}
##############################执行逻辑区#########################
mem_used=$(free | awk '/^Mem/ {print $3/$2 * 100.0}')
mem_used=${mem_used%.*}
if [ ${mem_used} -gt ${host_mem_limit} ]; then
# 获取进程内存占用值(单位为 GB)
dockerd_mem_gb=$(ps -p $(systemctl status docker | grep "Main PID" | awk '{print $3}') -o rss= | awk '{ printf "%.2f", $1/1024/1024 }')
echo -e "${dockerd_mem_gb%.*} ${max_mem_gb}"
if [ ${dockerd_mem_gb%.*} -ge ${max_mem_gb} ]; then
echo -e "$(date +"%Y-%m-%d %H:%M:%S") $(hostname) 主机内存占用率超过:${limit}% dockerd 进程内存占用超过 ${max_mem_gb} GB,执行热重启"
#执行热重启前先校验docker文件系统,若非xfs需要修改daemon.json文件避免热重启失败
checkFileSystem
# 执行dockerd热重启
hotRestartDockerd
restartSpecialCon
echo -e "$(date +"%Y-%m-%d %H:%M:%S") $(hostname) finished"
else
echo -e "$(date +"%Y-%m-%d %H:%M:%S") $(hostname) 主机内存使用量超出${host_mem_limit}%的限制范围,dockerd服务内存占用在${max_mem_gb} GB范围内,当前占用为${dockerd_mem_gb} GB."
fi
else
echo -e "$(date +"%Y-%m-%d %H:%M:%S") $(hostname) 内存使用量在${host_mem_limit}%的限制范围内."
fi
本文系作者 @Mr.Lee 原创发布在 维简网。未经许可,禁止转载。