尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

自建服务器监控:MySQL+Supervisor+LVM组合拳详解

自建服务器监控:MySQL+Supervisor+LVM组合拳详解 做服务器监控这事我一直觉得不需要一上来就上太重的东西。早年间我试过 Zabbix、Nagios装完那叫一个折腾各种依赖、Web 界面、Agent 部署等配完都快忘了自己想监控什么。后来做业务运维的时间长了慢慢发现一个道理监控系统自己先别成为负担。能在一台 CentOS 7 上用小半天时间搭起来、能解决 80% 日常巡检需求的方案才是最实用的。今天这篇就把我常用的这套 MySQL Supervisor LVM 组合拳完整拆开讲从分区规划到数据库存储再到进程守护一条龙给你捋清楚。1. 这个监控方案的整体思路与组件分工这套东西不是拿三件套拼凑出一个看起来很高端的架构而是它们各自都有不可替代的位置。你要先理解每个组件到底在监控体系里扮演什么角色后面部署才不会沦为“装了个软件”。1.1 为什么自建监控而不是直接用 Zabbix/Prometheus说句实话Zabbix 确实强大Prometheus 更是当前云原生监控的主流。但问题在于很多场景下你只需要监控三五台机器甚至就是一台重要的数据库服务器。为这种规模引入一套完整的监控平台光是维护成本就够喝一壶的。Zabbix 依赖 LAMP 环境Prometheus 虽然轻一些但生态组件多Grafana 面板要调好看也得花时间。自建方案的核心逻辑是“小而美”监控数据的采集用 shell 脚本存储用 MySQL进程守护交给 Supervisor磁盘弹性交给 LVM。全部是我们日常运维中已经很熟悉的技术栈出了问题好排查逻辑透明不依赖厂商。对中小团队、个人站长、以及刚接手服务器运维的新手来说这套方案能让你真正理解监控数据的流转过程而不是在黑盒里操作。1.2 三个核心组件在监控体系中的定位先说 LVM它解决的是存储层的弹性和可靠性问题。监控系统跑久了最尴尬的事就是磁盘满了导致监控数据写不进去——监控系统自己不监控自己。LVM 的逻辑卷可以在线扩容还能做快照备份这两点对长时间运行的监控数据库来说太重要了。MySQL 在这里承担的角色是监控数据的存储端。你可能觉得用文件存监控数据不就行了问题是当你有多个采样指标、要按时间维度做趋势分析的时候文件方案根本没法查。MySQL 用一张表把所有采样数据存下来一条 SQL 就能查出某个时间段 CPU 的趋势还能配合定时任务做数据清理这种灵活度不是文件能比拟的。Supervisor 的职责是守护采集脚本的持久运行。监控脚本跑在前台会随着终端关闭而退出用 crontab 虽然可以每分钟执行一次但脚本执行时间重叠的问题很麻烦而且没有进程状态可视化管理。Supervisor 用 Python 写的运行稳定配置简单能把脚本的启动、停止、重启、日志输出全部管起来。谁挂了立刻拉起还会发通知。1.3 一条完整的监控数据流转链路把三个组件串起来看整个流程就很清晰了Supervisor 守护的采集脚本每隔固定时间收集一次系统状态数据CPU、内存、磁盘、MySQL 运行状态然后通过 SQL 语句写入 MySQL 数据库LVM 在底层支撑 MySQL 数据目录的动态扩容保证存储空间不会成为瓶颈当你需要查看历史趋势或排查问题时登录 MySQL 直接查询监控数据表即可。这就像是一条流水线采集端脚本负责感知服务器的“体温”存储端MySQL负责留下“病历”守护端Supervisor确保“医生”时刻坚守岗位底层LVM保证“病历库”永远不会因为空间不足而关门。理解了这个链路后面每一个部署步骤你都会知道自己在干什么。2. 基础准备CentOS 7 系统与网络配置谈监控方案之前得先把场子搭好。CentOS 7 虽然已经进入维护周期的尾声但在现网中存量依然巨大很多生产环境跑的就是 7.9 版本。这里我以最小化安装的 CentOS 7.9 为例把系统层面的准备工作一条条说清楚。2.1 镜像选择与安装阶段的分区规划镜像强烈建议用 CentOS-7-x86_64-Minimal-2009.iso这是 7 系列的最后一个小版本也是我用的最稳的一个。下载时优先选国内镜像站比如清华 TUNA 或者阿里云速度比官网快很多。如果你的机器配置不高安装时直接把“软件开发工具”和“兼容性库”两个组包勾上别的都不用选最小化安装就够。安装阶段最重要的其实是分区。很多运维朋友装完系统之后才想起来磁盘不够用结果只能重新搞。用 LVM 方案就不要选择自动分区要手动划分配置。我的建议是/boot 分区给 1GBswap 按内存的 1 到 2 倍给剩下的全部划给 / 根分区并把根分区直接建立在 LVM 逻辑卷上。这样后续不管是扩容根目录还是单独切出数据卷都有很大的操作空间。具体操作时在安装界面的“分区方案”里选择“LVM 标准分区”然后创建分区的挂载点选 / 设备类型选“LVM”卷组名称起个容易认的比如 vg_root。你不用在一开始就把所有空间都分配给根目录可以预留一部分空间不分配等系统装完再通过后面的步骤动态创建数据卷给 MySQL 用。这个习惯真的建议养成磁盘规划一定要留一手。2.2 网络配置与防火墙放行CentOS 7 最小化安装后默认网卡是 DHCP生产环境建议固定 IP。修改 /etc/sysconfig/network-scripts/ifcfg-ens192网卡名用 ip addr 查看把 BOOTPROTOdhcp 改成 static然后追加 IPADDR、NETMASK、GATEWAY、DNS1、DNS2。改完记得 systemctl restart network 重启网络不生效就检查是不是 NetworkManager 管理着网卡。防火墙这一块很多教程一上来就让你 systemctl stop firewalld这在生产环境是大忌。正确做法是按需放行端口监控方案涉及的 MySQL 端口 3306、Supervisor Web 管理端口 9001以及 SSH 的 22 端口。一条命令搞定firewall-cmd --permanent --add-port3306/tcp firewall-cmd --permanent --add-port9001/tcp firewall-cmd --reload还有 SELinux如果 MySQL 绑定非默认端口或者用非标准目录存放数据就得要调整 SELinux 策略。新手建议先把 SELinux 设成 permissive 模式练手用 setenforce 0 临时生效改 /etc/selinux/config 里的 SELINUXpermissive 持久生效。等运维水平上来了再折腾 enforcing 的定制策略。2.3 时间同步与基础依赖组件监控数据的准确性完全依赖系统时间的准确性这一步忽略的人最多。没有时间同步你的采样时间戳全乱套趋势分析直接废掉。CentOS 7 自带 chronyd启动它并设为开机自启systemctl enable chronyd --now chronyc sources -v看到带 * 号的时间源就说明同步成功了。如果你的环境不能访问外部时间源至少要保证同一局域网内各机器时间一致可以搭建内部 NTP 服务器。基础依赖组件方面MySQL 官方仓库和 Supervisor 安装过程需要下面这些工具提前装上省得半路报错yum install -y wget vim net-tools unzip epel-release yum update -y其中 epel-release 是必装的Supervisor 在 EPEL 源里有现成的包不需要用 pip 从源码装那么麻烦。3. LVM 分区规划设计从 PV、VG 到 LVLVM 这套机制简单理解就是传统分区的“升级版”。传统分区把一个硬盘切成几块切完之后想要调整大小几乎不可能LVM 则把物理分区PV先聚合成一个资源池VG再从这个池子里按需划出“虚拟分区”LV给系统用。用了 LVM磁盘就像变成了乐高积木想加一块就拼一块想分一块就切一块。3.1 安装时如何规划好 LVM 卷组结合监控场景我建议安装系统时做如下 LVM 布局。把 /、/home、swap 全部放进一个名为 vg_root 的卷组其中 / 分配 80% 左右的容量/home 分配 10%swap 按实际内存来。如果你需要单独存放 MySQL 数据可以预留一部分空间不分配之后直接从 vg_root 里 lvcreate 卷组切割出来挂载到 /data 或者直接用 MySQL 默认的 /var/lib/mysql。有个非常实用的习惯给 LV 命名的时候按用途来。比如 lv_root、lv_home、lv_mysql、lv_backup。这样你在执行 lvdisplay 或者 lvs 命令时一眼就能知道每个逻辑卷是干什么的。当年我接手一台服务器发现逻辑卷名叫 lvol0、lvol1根本对应不上服务排查问题都得先做一轮“考古”。3.2 给 MySQL 数据盘扩容的完整操作流程服务器跑监控一段时间之后MySQL 数据文件增长导致磁盘空间告急这是最常见的事件。LVM 扩容的流程在掌握了核心概念之后其实非常简单。核心就是几个命令pvcreate 把新磁盘变成 PVvgextend 把 PV 加入 VGlvextend 把空间分配给 LVxfs_growfs或者 resize2fs让文件系统真正“吃下”新增空间。假设你现在 vg_root 卷组空间不足了新加了一块 100GB 的磁盘 /dev/sdb操作如下# 创建 PV pvcreate /dev/sdb # 扩展 VG vgextend vg_root /dev/sdb # 扩展 LV给 MySQL 数据卷增加 50GB lvextend -L 50G /dev/vg_root/lv_mysql # 如果文件系统是 XFS xfs_growfs /data/mysql # 如果文件系统是 EXT4 resize2fs /dev/vg_root/lv_mysql注意的一点是xfs_growfs 后面跟的是挂载点而 resize2fs 后面跟的是设备路径这个区别踩坑的人太多了。lvextend 加 -r 参数可以让文件系统自动扩展但我个人习惯手动分步操作每一步验证通过再走下一步因为直接 -r 的话如果文件系统类型异常日志很不好排查。扩展完 vgdisplay 和 df -h 一对比物理空间增大了挂载点可用空间也增大了整个过程完全在线完成服务零中断。这就是 LVM 相比传统分区最让人放心的地方。3.3 缩容操作的正确姿势与风险提示比扩容更棘手的是缩容。缩容操作建议只在测试环境或者停机维护窗口内做而且顺序特别讲究先缩小文件系统再缩小逻辑卷顺序绝不能反。操作不当直接损坏数据这和你用分区工具改分区表失败的结果是一样的。# 1. 卸载需要缩容的文件系统必须停掉相关服务 umount /data/mysql # 2. 检查文件系统 e2fsck -f /dev/vg_root/lv_mysql # 3. 缩容文件系统EXT4 示例缩到 50G resize2fs /dev/vg_root/lv_mysql 50G # 4. 缩容逻辑卷 lvreduce -L 50G /dev/vg_root/lv_mysql # 5. 重新挂载 mount -a这里要特别强调XFS 文件系统不支持在线缩容缩容操作只适用于 ext 系列而且缩容后你的逻辑卷大小一定不能小于文件系统内已有数据量否则文件系统损坏哭都来不及。生产环境我基本上只做扩容不做缩容宁可让空间“浪费”着也不要冒险动有业务的卷。3.4 LVM 快照在监控方案中的应用除了扩容LVM 还有一个杀手级功能——快照。快照可以在秒级生成一个逻辑卷在某时间点的“照片”在这个时间点之后对该卷的修改不会影响快照里的数据。这对监控方案有什么用试想一个场景MySQL 数据目录在 /var/lib/mysql你打算对监控数据库做一次数据导出备份但直接备份正在写数据的库会导致数据不一致。利用 LVM 快照先对 lv_mysql 做快照然后挂载快照卷进行备份期间 MySQL 可以继续运行备份出来的数据是一致且完整的。lvcreate -L 10G -s -n snapshot_mysql /dev/vg_root/lv_mysql mkdir -p /mnt/snapshot mount /dev/vg_root/snapshot_mysql /mnt/snapshot # 备份 /mnt/snapshot 下数据 umount /mnt/snapshot lvremove /dev/vg_root/snapshot_mysql快照空间的大小需要预估一下快照只记录差异数据写操作多的话快照空间会消耗很快满了快照就失效了。4. MySQL 安装配置存储监控数据的基础设施存储监控数据用 MySQL听起来有点“大炮打蚊子”但你要是真想自己控制监控体系MySQL 的灵活性和查询能力是文件方案没法比的。而且用 MySQL 还有一个好处你平时维护数据库的经验都能复用比如备份、恢复、权限管理用的都是你熟悉的那一套。4.1 官方仓库安装 MySQL 8.0 的完整步骤CentOS 7 默认源里带的 MySQL 版本太老我建议直接用 MySQL 官方 YUM 仓库安装 8.0 版本。这一步要注意官方仓库在安装前还需要源里的 gpg key 校验网络环境不好的机器很容易卡在这里。# 下载官方仓库 wget https://dev.mysql.com/get/mysql80-community-release-el7-5.noarch.rpm # 安装仓库信息 rpm -ivh mysql80-community-release-el7-5.noarch.rpm # 安装 MySQL 服务器 yum install -y mysql-community-server # 启动并设置开机自启 systemctl enable mysqld --now安装完成后 MySQL 会生成一个临时密码在 /var/log/mysqld.log 里用 grep temporary password 找到它。然后登录数据库马上修改密码。MySQL 8.0 默认装了密码校验插件 validate_password要求密码包含大小写字母、数字和特殊字符长度至少 8 位。如果嫌麻烦可以在 /etc/my.cnf 里加一行禁用[mysqld] validate_password.policyLOW validate_password.length6不过监控库的数据价值高我还是建议保留强密码策略配置好权限只允许本机和监控应用访问也省得以后被安全扫描扫出来单。4.2 监控场景下的数据库调优参数监控场景的数据库特点是写入频繁、查询集中、单表数据量大。针对这几个特点MySQL 参数要稍微调整一下。打开 /etc/my.cnf重点关注以下几个参数[mysqld] # 日志大小决定事务性能的上限 innodb_log_file_size 256M # InnoDB 缓冲池核心内存参数 innodb_buffer_pool_size 1G # 允许的最大连接数 max_connections 200 # 日志缓冲区 innodb_log_buffer_size 16M # 数据写入磁盘的策略 innodb_flush_log_at_trx_commit 2 # binlog 保留天数 expire_logs_days 7innodb_buffer_pool_size 是 MySQL 内存占用的大头建议设置为物理内存的 50% 到 70%但要注意别和机器上别的服务抢内存如果你是 2G 内存的小机器就给 512M 就足够了。innodb_flush_log_at_trx_commit 的默认值是 1每次事务提交都要刷盘安全但慢监控数据的容忍度可以放宽设置成 2 或者 0 能显著提升写入速度代价是极端宕机时可能丢最近一秒的数据对监控场景来说完全能接受。同时要开启性能相关状态开关方便监控脚本采集UPDATE performance_schema.setup_consumers SET ENABLEDYES WHERE NAME LIKE events_statements%;4.3 建库建表与监控用户创建存储监控数据我习惯建独立的库名 monitor表结构尽量简洁高效。核心表就三张系统指标表、MySQL 状态表、通知记录表。系统指标表记录 CPU、内存、磁盘等基础状态MySQL 状态表记录连接数、慢查询数、主从状态等数据库自身指标通知记录表记录告警发送的时间和内容方便事后复盘。-- 创建监控库 CREATE DATABASE IF NOT EXISTS monitor DEFAULT CHARSET utf8mb4; USE monitor; -- 系统基础指标表 CREATE TABLE system_metrics ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, hostname VARCHAR(64) NOT NULL COMMENT 主机名, cpu_usage DECIMAL(5,2) NOT NULL COMMENT CPU 使用率, mem_usage DECIMAL(5,2) NOT NULL COMMENT 内存使用率, disk_usage DECIMAL(5,2) NOT NULL COMMENT 根分区使用率, load_avg VARCHAR(32) NOT NULL COMMENT 负载均值, collect_time DATETIME NOT NULL COMMENT 采集时间, PRIMARY KEY (id), KEY idx_collect_time (collect_time) ) ENGINEInnoDB COMMENT系统基础指标表; -- MySQL 性能指标表 CREATE TABLE mysql_metrics ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, threads_connected INT NOT NULL COMMENT 当前连接数, slow_queries INT NOT NULL COMMENT 慢查询数, qps INT NOT NULL COMMENT 每秒查询数, buffer_pool_hit_rate DECIMAL(5,2) NOT NULL COMMENT 缓冲池命中率, collect_time DATETIME NOT NULL COMMENT 采集时间, PRIMARY KEY (id), KEY idx_collect_time (collect_time) ) ENGINEInnoDB COMMENTMySQL 性能指标表; -- 告警通知记录表 CREATE TABLE alert_log ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, alert_type VARCHAR(32) NOT NULL COMMENT 告警类型, alert_content VARCHAR(255) NOT NULL COMMENT 告警内容, status TINYINT NOT NULL DEFAULT 0 COMMENT 通知状态, create_time DATETIME NOT NULL COMMENT 触发时间, PRIMARY KEY (id) ) ENGINEInnoDB COMMENT告警通知记录表;这张表的设计有几个实用之处DECIMAL(5,2) 存储百分比数值既精确又不占空间collect_time 建索引历史趋势查询秒回utf8mb4 字符集应对各种告警内容不报错。索引的建立要克制索引能加速查询但也拖慢写入监控表以写入为主、查询集中在时间范围所以只给时间字段建索引就够了。权限方面创建独立的监控账号权限最小化。账号只授予 monitor 库的 SELECT、INSERT、UPDATE、DELETE 权限绝不给 GRANT 和跨库权限CREATE USER monitorlocalhost IDENTIFIED BY YourStrongPassword!; GRANT SELECT, INSERT, UPDATE, DELETE ON monitor.* TO monitorlocalhost; FLUSH PRIVILEGES;这里的 host 一定要按实际来写如果你的监控脚本和 MySQL 在同一台机器上用 localhost 就行如果要走网络采集再按需改成具体 IP 或网段。4.4 数据保留策略与定时清理监控数据随时间无限增长必须设计清理策略。我的方案是按月保留每月月初清理三个月前的数据。不用 DELETE 一条条删效率太低直接按时间范围批量删除DELETE FROM system_metrics WHERE collect_time DATE_SUB(NOW(), INTERVAL 90 DAY);这条语句理论上可行但当数据量达到百万级时直接 DELETE 会拖垮系统。更好的方式是利用分区表按月分区或者直接开个定时任务定期用 DROP TABLE 换表的方式做轮转。对大多数中小配置的服务器90 天数据清一次就够配合定时任务每月执行即可。清理任务推荐放进 MySQL 自身的事件调度器SET GLOBAL event_scheduler ON; CREATE EVENT IF NOT EXISTS clean_monitor_data ON SCHEDULE EVERY 1 DAY DO BEGIN DELETE FROM system_metrics WHERE collect_time DATE_SUB(NOW(), INTERVAL 90 DAY); DELETE FROM mysql_metrics WHERE collect_time DATE_SUB(NOW(), INTERVAL 90 DAY); END;需要注意DELETE 操作也会产生 binlog主从环境下会产生大量日志建议在离线时段比如凌晨 4 点执行。另外监控数据的价值随时间递减保留 90 天对日常排查完全够用。5. Supervisor 部署与监控脚本编写Supervisor 是整个体系里负责“保障运行”的组件。脚本写好了但谁来确保它一直跑着Supervisor 的意义在于它把你的采集脚本变成“系统服务”——可以自动启动、崩溃重启、日志持久化、状态可通过命令查看。这跟直接 crontab 丢进去是两个时代的东西。5.1 Supervisor 的安装与核心配置在 CentOS 7 上装 Supervisor 最简单的方式是直接用 EPEL 源yum install -y supervisor systemctl enable supervisord --nowEPEL 里的 Supervisor 版本是 3.x对于常规进程守护完全够用。配置文件在 /etc/supervisord.conf实际使用中我习惯把每个进程的配置单独放一个文件放在 /etc/supervisord.d/ 目录下主配置文件末尾用 include 引入[include] files /etc/supervisord.d/*.ini这样每新增一个守护任务只需在 /etc/supervisord.d/ 下新建一个 .ini 文件再执行 supervisorctl update 即可不用频繁改主配置文件。这个习惯在你管理的监控脚本和后台任务多起来之后价值立竿见影。5.2 服务器监控采集脚本的编写要点真正的监控实战核心其实是采集脚本本身。我写脚本的原则是不引入额外的 agent 依赖纯 shell 加上系统自带命令就能采集到关键指标。CPU 使用率可以用 mpstat 或 vmstat内存、磁盘、负载则用 free、df、uptime 等命令解析。下面是我常用的采集脚本思路核心是三个函数采集系统指标、采集 MySQL 指标、写入数据库。#!/bin/bash # /usr/local/bin/collect_metrics.sh MYSQL_CMDmysql -umonitor -pYourStrongPassword! -h127.0.0.1 -N -e HOSTNAME$(hostname) TIME$(date %Y-%m-%d %H:%M:%S) # 1. 采集系统指标 # CPU使用 vmstat 获取空闲率100 减掉即使用率 CPU_IDLE$(vmstat 1 2 | tail -1 | awk {print $15}) CPU_USAGE$(echo 100 - $CPU_IDLE | bc) # 内存free 返回数值输出已用内存总计占比 MEM_TOTAL$(free -m | awk /^Mem:/{print $2}) MEM_USED$(free -m | awk /^Mem:/{print $3}) MEM_USAGE$(echo scale2; $MEM_USED * 100 / $MEM_TOTAL | bc) # 磁盘根分区使用率 DISK_USAGE$(df -h / | awk NR2{print $5} | sed s/%//) # 负载均值 LOAD_AVG$(uptime | awk -Fload average: {print $2}) # 2. 写入系统指标表 $MYSQL_CMD INSERT INTO monitor.system_metrics (hostname, cpu_usage, mem_usage, disk_usage, load_avg, collect_time) VALUES ($HOSTNAME, $CPU_USAGE, $MEM_USAGE, $DISK_USAGE, $LOAD_AVG, $TIME);这里有些细节必须注意vmstat 的参数写法因为要取采样后的数据所以后面加了“1 2”取第二行的值mysql 命令用 -N 参数跳过表头省去文本解析的头疼事所有指标做变量引用时都加了单引号防止特殊字符破坏 SQL 语句。MySQL 状态指标采集原理类似从 SHOW GLOBAL STATUS 和 SHOW GLOBAL VARIABLES 中取关键值# 连接数 THREADS_CONNECTED$(mysql -umonitor -pYourStrongPassword! -h127.0.0.1 -N -e SHOW GLOBAL STATUS LIKE Threads_connected; | awk {print $2}) # 慢查询数 SLOW_QUERIES$(mysql -umonitor -pYourStrongPassword! -h127.0.0.1 -N -e SHOW GLOBAL STATUS LIKE Slow_queries; | awk {print $2}) # QPS 两次采样差值的平均值 QPS$(mysqladmin -umonitor -pYourStrongPassword! status | awk {print $6}) # 缓冲池命中率 HIT_RATE$(mysql -umonitor -pYourStrongPassword! -N -e SHOW GLOBAL STATUS LIKE Innodb_buffer_pool_read_requests; | awk {print $2})读到这里你应该明白了这个自建监控没有你不知道的黑科技全是你在 MySQL 日常运维中肯定会用到的命令行工具。把状态值按时写入数据表后后面的一切分析都有了可靠的数据基础。5.3 用 Supervisor 进程守护实现脚本自动拉起采集脚本写完还不算完关键是如何让它每 30 秒执行一次并保证崩了能自动恢复。Supervisor 的配置里不支持小于 1 秒的 sleep 循环控制但我们可以让脚本自身循环执行Supervisor 只负责守护脚本进程。把采集逻辑包在一个无限循环里每次执行完采集后用 sleep 控制采样间隔#!/bin/bash # /usr/local/bin/collect_metrics_daemon.sh while true; do /usr/local/bin/collect_metrics.sh sleep 30 done然后创建 Supervisor 配置[program:collect_metrics] directory/usr/local/bin command/bin/bash /usr/local/bin/collect_metrics_daemon.sh autorestarttrue startsecs5 startretries10 redirect_stderrtrue stdout_logfile/var/log/monitor/collect_metrics.log stdout_logfile_maxbytes100MB stdout_logfile_backups5这里 set autorestarttrue 的作用是无论任何原因导致脚本挂了Supervisor 都会自动拉起。startsecs5 表示进程持续运行 5 秒以上才认为是启动成功防止“反复重启死循环”。日志配置可以防止日志无限膨胀这个在长期运行中特别重要。配置完成后supervisorctl reread supervisorctl update supervisorctl status看到 collect_metrics 的状态是 RUNNING就说明守护成功。你可以试一下 kill 进程观察 supervisorctl status 里进程会自动重启这就是 Supervisor 守护职责的实战验证。5.4 告警阈值与通知机制监控的目的是在出问题时尽早发现所以要给脚本加入阈值判断和通知逻辑。最简单的通知方式是结合 SMTP 发邮件或者调用企业微信机器人、钉钉机器人的 Webhook 接口。以钉钉机器人为例先在钉钉群里添加一个自定义机器人拿到 Webhook 地址然后在脚本里封装一个 webhook 通知函数DING_MSG() { local content$1 curl -s -H Content-Type: application/json -X POST $DING_WEBHOOK_URL \ -d {\msgtype\: \text\, \text\: {\content\: \[服务器监控] $content\}} /dev/null }在采集脚本里加上阈值判断比如 CPU 超过 85%、磁盘超过 90%、MySQL Threads_connected 超过上限都触发告警if [ $(echo $CPU_USAGE 85 | bc) -eq 1 ]; then DING_MSG CPU 使用率过高: ${CPU_USAGE}% fi if [ $(echo $DISK_USAGE 90 | bc) -eq 1 ]; then DING_MSG 根分区使用率过高: ${DISK_USAGE}% fi这里如果用简单的大小比较会踩坑因为 awk 计算出的 CPU_USAGE 是浮点数shell 的 -ge 命令不支持浮点运算所以用了场景中很常见的 bc 命令做浮点比较。注意告警通知要加入去重逻辑同一个问题在持续时间内不要重复轰炸。可以在通知表里记录最近一次的通知时间如果当前时间和上次通知时间相差不足 10 分钟就跳过这一步能有效防止告警风暴。5.5 数据可视化最简单的方式存了监控数据总得让它产生价值。全功能可视化可以以后接 Grafana但在一开始用命令行也可以满足查看趋势的需求。比如查询最近一小时 CPU 使用率SELECT collect_time, cpu_usage FROM monitor.system_metrics WHERE collect_time DATE_SUB(NOW(), INTERVAL 1 HOUR) ORDER BY collect_time;如果你连 Grafana 都懒得装也可以用 MySQL 自带的方式把数据导出成 CSV丢进 Excel 画图效果完全够日常巡检用SELECT collect_time, cpu_usage, mem_usage, disk_usage FROM monitor.system_metrics WHERE collect_time DATE_SUB(NOW(), INTERVAL 24 HOUR) INTO OUTFILE /tmp/metrics_24h.csv FIELDS TERMINATED BY ,;要说最实用的场景其实是故障复盘。服务器出问题后你第一时间去查监控库里对应时间点的数据CPU、负载、慢查询数全部呈现比什么排查工具都直接。6. 常见问题与排查技巧实录跑了这套体系两年多我把真正踩过的高频问题整理成一份速查表希望能帮你少走几周弯路。6.1 高频问题排查对照表症状可能原因排查思路Supervisor 启动时报错 /var/run/supervisord.sock 不存在supervisor 服务未启动systemctl status supervisord先启动服务采集脚本手动执行正常但 Supervisor 启动后无数据脚本路径或环境变量问题在配置里指定绝对路径 interpretermysql 命令连接报 Access denied密码策略太强或权限不对检查用户 host 匹配、密码复杂度用 mysql -u -p 手动验证lvextend 后磁盘容量没变化文件系统未扩展xfs 用 xfs_growfs / 挂载点ext4 用 resize2fs 设备路径LVM 快照挂载后数据不一致快照前 MySQL 有未刷盘的缓冲数据最好通过 mysqldump 或 xtrabackup 做一致性备份监控数据表越来越大查询变慢缺少时间索引或数据未清理补建 collect_time 索引开启自动清理事件服务器重启后 Supervisor 没有拉起脚本Supervisor 开机自启没设systemctl enable supervisord检查配置文件无语法错误curl 发 Webhook 通知超时外网网络不稳定或 Webhook 地址不通手动 curl 测试加超时参数 --connect-timeout 56.2 我踩过的两个印象深刻的坑第一个坑是刚部署 Supervisor 时脚本起不来日志里报权限错误。排查了半天发现是脚本目录 /usr/local/bin 下没有给执行权限。Supervisor 的 command 指定 /bin/bash 调用脚本其实不受执行权限影响但我犯的错是在 command 里直接写了脚本路径且没加 bash 前缀导致文件没有 x 权限时直接被拒绝。现在我的配置一律写成 /bin/bash /path/to/script.sh顽固依赖彻底规避。第二个坑是 MySQL 扩容。有一次监控库的机器磁盘告警我满怀信心地 lvextend -L 20G执行完 xfs_growfs 后 df -h 一查容量一点没变。查了半天才发现那块数据卷是 ext4 文件系统xfs_growfs 根本不支持手动确认文件系统类型后改用 resize2fs 才成功。这个低级失误提醒我操作前必须用 blkid 或者 lsblk -f 确认文件系统类型。6.3 安全加固建议和备份策略监控系统虽然不直接承载业务但它记录的是你所有服务器的健康档案安全等级不能太低。MySQL 侧要定期修改密码Supervisor 的 Web 管理端口默认 9001除非在受控内网否则建议关闭外网访问或者用 SSH 隧道来访问。防火墙规则要收紧3306 和 9001 不做静态放行用 SSH 隧道转发端口来连最稳。数据库备份方面监控数据虽然可以丢一部分但运维复盘时需要历史数据建议每天对 monitor 库做一次 mysqldump 备份保留 14 天mysqldump -umonitor -pYourStrongPassword! monitor /data/backup/monitor_$(date %F).sql find /data/backup -name monitor_*.sql -mtime 14 -delete你可以把这条命令也写进 Supervisor 配置里做成一个定时执行的备份程序比 crontab 看得更清楚。6.4 扩展思路从 shell 到更现代的监控视野这套自建监控方案跑通之后你已经拥有了监控系统的骨架存储层、采集层、守护层、提醒层。在这个骨架上做扩展非常容易。比如把采集数据输出为 Prometheus 格式对接一个轻量级的 Prometheus 服务端和 Grafana就能获得专业级的可视化面板也可以把采集目标从一台机器扩展到多台机器MySQL 库表里加一个 hostname 字段就能区分所有来源。我个人实际运营下来的感想是不再需要看到任何面板都觉得是黑科技了。因为监控的本质无非是定时取数、按规则判异、通知有人的过程。自己搭过一遍反而对那些重型监控系统有了平常心知道它们在解决什么问题也知道哪些问题是自己的规模根本遇不到的。这套组合的另一个好处是后续迁移成本低。MySQL、Supervisor、LVM 都是跨平台的成熟技术你换到 Ubuntu、换到 Debian核心逻辑完全复用只是包管理器的命令不同而已。最后再分享一个小技巧玩 LVM 的时候执行完任何变更操作之后养成 lvs、vgs、pvs 三个命令轮番看一眼的习惯你就能时刻掌握存储的完整状态。这套监控方案我跑了两三年期间扛过 CPU 打满、磁盘写满、进程假死等各种故障该报警的时候从没哑火过值得你试试。
返回列表