目的: 轻量级, 传统的 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'

最终脚本:
监听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 ,
浙公网安备 33010602011771号