深入解析Python多服務器監控告警系統:從原理到生產部署
整體架構圖
核心設計思想
- 無代理監控:通過SSH直接獲取數據,無需在目標服務器安裝代理
- 故障隔離:單臺服務器故障不影響整體監控
- 多級檢測:網絡層→資源層→服務層層層遞進
- 冪等設計:支持定時重復執行,避免狀態累積
代碼深度解析
1. 配置模塊 - 靈活的參數管理
# 服務器配置列表
SERVERS = [{"host": "192.168.0.224", "ssh_port": 22, "ssh_user": "root", "ssh_key": "/root/.ssh/server_monitor_key"},# 更多服務器...
]# 監控閾值設置
MEMORY_THRESHOLD = 90 # 內存閾值%
CPU_THRESHOLD = 85 # CPU閾值%
DISK_THRESHOLD = 95 # 磁盤閾值%# 檢測參數
DINGTALK_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token="
PING_TIMEOUT = 3 # 網絡檢測超時(秒)
CHECK_INTERVAL = 600 # 檢查間隔(秒)
- 支持多服務器配置,可擴展性強
- 關鍵參數集中管理,便于維護
- 支持不同服務器使用不同認證方式
2. 網絡檢測模塊 - 基于TCP的連通性檢查
def check_network(host):try:socket.setdefaulttimeout(PING_TIMEOUT)s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((host, 22)) # 檢測SSH端口s.close()return Trueexcept Exception:return False
- 使用TCP連接檢測替代ICMP ping,更貼近實際服務可用性
- 檢測SSH服務端口(22),確保監控功能可用
- 設置超時時間防止阻塞
3. 指標采集模塊 - SSH命令執行與解析
def get_server_metrics(server):# 創建SSH客戶端ssh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())try:# 多密鑰類型支持try:private_key = paramiko.RSAKey.from_private_key_file(server["ssh_key"])except:try:private_key = paramiko.Ed25519Key.from_private_key_file(server["ssh_key"])except:private_key = paramiko.ECDSAKey.from_private_key_file(server["ssh_key"])# 建立SSH連接ssh.connect(hostname=server["host"],port=server["ssh_port"],username=server["ssh_user"],pkey=private_key,timeout=15,look_for_keys=False,allow_agent=False)# 獲取主機名stdin, stdout, stderr = ssh.exec_command("hostname")hostname = stdout.read().decode().strip() or server["host"]# CPU監控命令stdin, stdout, stderr = ssh.exec_command("top -bn1 | grep 'Cpu(s)' | awk -F'[ ,]+' '{print $8}' | tr -d '%' | awk '{print 100 - $1}'")cpu_usage = float(stdout.read().decode().strip())# 更多指標采集...finally:ssh.close()return hostname, alerts
- 多密鑰算法支持:自動嘗試RSA/Ed25519/ECDSA等算法
- 安全連接設置:禁用SSH agent和密鑰搜索
- 主機名獲取:優先使用服務器真實主機名
- 資源釋放:finally塊確保SSH連接關閉
4. 告警模塊 - 釘釘機器人集成
def send_dingtalk_message(message):"""發送Markdown格式消息到釘釘機器人"""headers = {"Content-Type": "application/json"}# 創建Markdown格式消息markdown_content = "### 🚨 服務器監控告警\n" + message.replace("\n", "\n\n")data = {"msgtype": "markdown","markdown": {"title": "服務器監控告警","text": markdown_content}}try:response = requests.post(DINGTALK_WEBHOOK,data=json.dumps(data),headers=headers,timeout=10)if response.status_code == 200:print("釘釘消息發送成功")else:print(f"釘釘消息發送失敗: {response.text}")except Exception as e:print(f"發送釘釘消息時出錯: {str(e)}")
- 添加時間戳便于問題追蹤
- 包含直接訪問監控面板的鏈接
- 使用emoji增強可讀性
- 支持Markdown格式(加粗、換行等)
監控指標采集技術詳解
1. CPU使用率采集
top -bn1 | grep 'Cpu(s)' | awk -F'[ ,]+' '{print $8}' | tr -d '%' | awk '{print 100 - $1}'
命令解析:
top -bn1
:非交互模式運行top命令grep 'Cpu(s)'
:過濾CPU行awk
處理:提取空閑CPU百分比100 - 空閑值
:計算實際使用率
2. 內存使用率采集
free | awk 'NR==2{printf "%.2f", $3*100/$2 }'
計算原理:
總內存 = $2
已用內存 = $3
使用率 = (已用內存 / 總內存) * 100
3. 磁盤使用率采集
df -h | awk '$NF=="/"{printf "%d", $5}'
關鍵參數:
$NF=="/"
:只監控根分區$5
:使用率列(已去除%符號)- 可根據不同服務器掛載的分區自行調整
4. 進程監控
processes = ["kubelet", "dockerd", "kube-proxy"]
for process in processes:stdin, stdout, stderr = ssh.exec_command(f"pgrep -x {process}")if not stdout.read().decode().strip():missing_processes.append(process)
進程檢測邏輯:
- 使用
pgrep -x
精確匹配進程名 - 檢查返回結果是否為空
- 支持擴展添加關鍵進程
生產環境部署指南
系統架構建議
部署步驟
-
環境準備
# 創建專用用戶 sudo useradd -m -s /bin/bash monitor sudo passwd monitor# 安裝依賴 sudo apt-get update sudo apt-get install python3-pip sudo -u monitor pip install paramiko requests
-
SSH密鑰配置
# 生成監控專用密鑰 sudo -u monitor ssh-keygen -t ed25519 -f /home/monitor/.ssh/server_monitor_key# 分發公鑰到目標服務器 for server in ${SERVERS[@]}; dosudo -u monitor ssh-copy-id -i /home/monitor/.ssh/server_monitor_key.pub ${server} done
-
配置文件調整
# 修改服務器配置 SERVERS = [{"host": "10.0.1.101", "ssh_port": 22, "ssh_user": "monitor", # 使用專用賬戶"ssh_key": "/home/monitor/.ssh/server_monitor_key" # 正確路徑},# 更多服務器... ]
-
系統服務化
bash
# 創建systemd服務文件 sudo tee /etc/systemd/system/server-monitor.service <<EOF [Unit] Description=Server Monitoring Service After=network.target[Service] User=monitor ExecStart=/usr/bin/python3 /opt/monitor/new_server_monitor.py Restart=always RestartSec=30[Install] WantedBy=multi-user.target EOF# 啟動服務 sudo systemctl daemon-reload sudo systemctl enable server-monitor sudo systemctl start server-monitor
日志管理方案
# 查看實時日志
journalctl -u server-monitor -f# 日志輪轉配置
sudo tee /etc/logrotate.d/server-monitor <<EOF
/var/log/server-monitor.log {dailymissingokrotate 30compressdelaycompressnotifemptycreate 640 monitor admsharedscriptspostrotatesystemctl restart server-monitor > /dev/nullendscript
}
EOF