目的: 轻量级, 传统的  cAdvisor +  Prometheus + Grafana  + ELK  过于重,能否简易通知, 不关注细节,达到提示作用

系统:  ubuntu20.04

场景   轻量监控docker  容器 ---> eg : per  5min 执行一次,内存利用率大于95% ,发出提示

 

1. 简易通知服务:(notifyApp.py)

import asyncio
import uvicorn
from fastapi import FastAPI
from starlette.requests import Request
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI(title="Sea test API")
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.post("/sendNotify")
async def send_notify( request: Request):
    request_body = await request.body()
    try:
        request_body_str = request_body.decode('utf-8')
        print("sendNotify " + request_body_str)
        msg = eq_wechat_notify.send_group_chat_msg(group_id=WX_GROUP_ID, message=request_body_str) # 企业微信 or 钉钉
        print("sendNotify result " + str(msg))
        return {"code":200,"message": "ok"}
    except Exception as e:
        print("send_notify error : " + str(e))
        return {"code":250,"message": str(e)}


if __name__ == '__main__':
    async def run_both_services():
        # 同时运行 Kafka 消费者和 FastAPI
        await asyncio.gather(
            asyncio.to_thread(start),  # 将同步函数转换为异步执行 (kafka 其它异常通知)
            asyncio.to_thread(lambda: uvicorn.run(app, host="0.0.0.0", port=5000))
        )
    asyncio.run(run_both_services())

 

使用:

正确的 curl POST 请求格式:
1. 发送原始字符串 "hello":
bash
curl -X POST http://localhost:5000/sendNotify -d "hello" -H "Content-Type: text/plain"
2. 发送 JSON 数据:
bash
curl -X POST http://localhost:5000/sendNotify \
  -H "Content-Type: application/json" \
  -d '{"message": "hello"}'
3. 发送表单数据:
bash
curl -X POST http://localhost:5000/sendNotify \
  -d "message=hello"

 

 

 

 

 

 

脚本1:筛选内存使用率大于80%的容器 

简洁版本: 

sudo docker stats --no-stream --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}\t{{.MemUsage}}" | awk 'NR==1 || $4+0 > 80'

image

 

 

最终脚本: 

   监听server  memory  dick and docker container  的使用状况

#!/bin/bash

# default 配置参数
DOCKER_CONTAINER_MEMORY_THRESHOLD=95           # docker容器内存阈值百分比 95% 提醒
LOCAL_FREE_MEMORY_THRESHOLD=300  # 本地 server 内存阈值(低于) 300MB  提醒
LOCAL_DISK_USED_THRESHOLD=93   # 90% 本地 server 磁盘使用阈值(高于) 95% 提醒
NOTIFY_URL="http://192.168.186.154:5000/sendNotify"



# 获取服务器信息
get_server_info() {
    server_ip=$(hostname -I | awk '{print $1}')
    echo "IP地址: $server_ip"
}


# 发送通知 eg: send_notification "内存使用率过高"
send_notification() {
   local message="$1"
    # 发送请求
    curl -X POST "$NOTIFY_URL" \
         -d "$message" \
         -H "Content-Type: text/plain" \
         --max-time 5  # 5秒超时
}


# 获取Docker容器信息内存使用率  筛选内存使用率大于80%的容器
get_docker_container_info() {
    # 获取Docker容器信息内存使用率  筛选内存使用率大于80%的容器  不打印表头
    # sudo docker stats --no-stream --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}\t{{.MemUsage}}" | awk '$4+0 > 80'
    # 判断 是否可以获取Docker容器信息
    if ! command -v docker &> /dev/null; then
        echo "Docker未安装"
        return 1
    fi
    # 获取Docker容器信息内存使用率  筛选内存使用率大于80%的容器  不打印表头
    docker_info=$( docker stats --no-stream --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}\t{{.MemUsage}}" |  awk -v threshold="$DOCKER_CONTAINER_MEMORY_THRESHOLD" '$4+0 > threshold')
    # 判断是否获取到数据
    if [ -z "$docker_info" ]; then
        echo "未获取到Docker容器内存使用率大于90%的容器信息"
        return 1
    fi

    # 获取Docker容器信息内存使用率  筛选内存使用率大于80%的容器  打印表头
    # sudo docker stats --no-stream --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}\t{{.MemUsage}}" | awk 'NR==1 || $4+0 > 80' # DOCKER_MEMORY_THRESHOLD
    docker_info=$( docker stats --no-stream --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemPerc}}\t{{.MemUsage}}" | awk -v threshold="$DOCKER_CONTAINER_MEMORY_THRESHOLD" 'NR==1 || $4+0 >threshold')
    # 判断是否获取到数据
    if [ -z "$docker_info" ]; then
        echo "未获取到Docker容器内存使用率大于90%的容器信息"
        return 1
    fi
    # 发送通知
    echo "Docker容器内存使用率大于90%的容器信息: $docker_info"
    send_notification "警告! server_ip ${server_ip}: 请关注以下Docker容器内存使用率大于\n ${DOCKER_CONTAINER_MEMORY_THRESHOLD}%的容器信息: \n  $docker_info"
}





# 获取本地磁盘的使用率 如果大于90%,则发送通知
get_local_disk_usage() {
    # 获取表头
    header=$(df -h | head -1)

    # 查找磁盘容量大于100G且使用率超过阈值的分区
    result=$(df -h | awk -v threshold="$LOCAL_DISK_USED_THRESHOLD" '
        NR==1 {next}  # 跳过表头
        $2 ~ /[0-9\.]+G$/ && $2+0 > 100 {
            usage = substr($5, 1, length($5)-1)+0
            if (usage > threshold) {
                print $0
                found = 1
            }
        }
        END {
            if (!found) print "no"
        }
    ')

    if [ "$result" != "no" ] && [ -n "$result" ]; then
        echo "磁盘使用率过高"
        echo "$header"
        echo "$result"
        # 发送通知
        send_notification "警告! server_ip ${server_ip}:磁盘使用率过高! 磁盘使用情况: $header $result"
    else
        echo "磁盘使用率正常"
    fi
}






get_local_memory_free(){
  # 获取物理机内存信息
  total=$(free -m | awk 'NR==2{print $2}')
  used=$(free -m | awk 'NR==2{print $3}')
  free=$(free -m | awk 'NR==2{print $4}')
  available=$(free -m | awk 'NR==2{print $7}')
  buffer_cache=$(free -m | awk 'NR==2{print $6}')
  echo "=== 内存使用情况 ==="
  echo "总内存: ${total}MB"
  echo "已使用: ${used}MB"
  echo "空闲内存: ${free}MB"
  echo "可用内存: ${available}MB"
  echo "缓冲/缓存: ${buffer_cache}MB"

  if [ $free -lt $LOCAL_FREE_MEMORY_THRESHOLD ]; then
      echo ""
      echo "❌ 警报:可用内存低于阈值!"
      echo "可用内存: ${free}MB < 阈值: ${LOCAL_FREE_MEMORY_THRESHOLD}MB"
      # 显示占用内存最多的进程
      echo ""
      echo "占用内存最多的5个进程:"
      ps aux --sort=-%mem | head -6
      # 发送系统通知(需要安装libnotify)
      send_notification "警告! server_ip ${server_ip}: 总内存 ${total}MB 可用内存 ${available}MB free ${free}MB 可用内存低于阈值 ${LOCAL_FREE_MEMORY_THRESHOLD}MB!  buffer_cache ${buffer_cache}MB"
  fi
}



# 主函数
main() {
    echo "开始检查..."
   echo "获取服务器信息..."
   get_server_info
   echo "获取Docker容器信息..."
   get_docker_container_info
   echo "获取本地磁盘使用情况..."
   get_local_disk_usage
   echo "获取本地内存使用情况..."
   get_local_memory_free
   echo "检查完成!"
}

# 执行主函数  用户可以传 4个参数 分别是 DOCKER_CONTAINER_MEMORY_THRESHOLD LOCAL_FREE_MEMORY_THRESHOLD LOCAL_DISK_USED_THRESHOLD NOTIFY_URL
# 参数0 1 2 3 如果用户不传参数 则使用默认参数,否则使用用户传的参数
echo " 用户可以传 4个参数 分别是 DOCKER_CONTAINER_MEMORY_THRESHOLD(95) LOCAL_FREE_MEMORY_THRESHOLD(300) LOCAL_DISK_USED_THRESHOLD(93) NOTIFY_URL(http://192.168.186.154:5000/sendNotify)"
echo " eg: check_server_and_docker_memory.sh 95 300 93  http://192.168.186.154:5000/sendNotify    其中  url 为post method  Content-Type=text/plain"
if [ $# -eq 4 ]; then
  DOCKER_CONTAINER_MEMORY_THRESHOLD=${1}
  echo "DOCKER_CONTAINER_MEMORY_THRESHOLD: $DOCKER_CONTAINER_MEMORY_THRESHOLD"
  LOCAL_FREE_MEMORY_THRESHOLD=${2}
  echo "LOCAL_FREE_MEMORY_THRESHOLD: $LOCAL_FREE_MEMORY_THRESHOLD"
  LOCAL_DISK_USED_THRESHOLD=${3}
  echo "LOCAL_DISK_USED_THRESHOLD: $LOCAL_DISK_USED_THRESHOLD"
  NOTIFY_URL=${4}
  echo "NOTIFY_URL: $NOTIFY_URL"
fi


main


######## 定时任务:  部署 crontab  ######
# crontab -e
# # 每5分钟同步一次
# */5 * * * * /opt/check_server_and_docker_memory.sh 95 300 93 http://192.168.186.154:7980/sendNotify
# */5 * * * * /opt/check_server_and_docker_memory.sh 95 300 93 http://10.180.3.148:7980/sendNotify
#保存了crontab之后,我们还需要重启cron来应用这个计划任务。使用以下命令:
#sudo service cron restart
#crontab -l   命令列出它的全部信息

 

 

 

 

 

详细的整个server , 

 

 

 

 

 

 

 

 

 

posted on 2025-12-31 12:30  lshan  阅读(25)  评论(0)    收藏  举报