十堰开发者运维实战:用 Prometheus + Grafana 搭建服务器监控告警(含企业微信通知与三条核心规则)
一、先看两个真实故障:十堰企业的服务器为什么"看起来没事"
2026 年上半年,我们接手十堰两家本地企业的运维交接,翻开服务器历史记录,两个故障非常典型。
案例一:日志把磁盘写满,网站静默失败了 6 个小时
一家位于十堰张湾区的零部件企业官网,早上 8 点业务员发现询盘表单提交不了。登录服务器一看,/dev/vda1 使用率 100%,Nginx 的 access.log 已经涨到 41GB——因为当初部署时没配 logrotate,日志从上线那天起就没切割过。更麻烦的是 PHP-FPM 写不了 session,表单直接返回 500,但首页是纯静态的,照样能打开,所以没人第一时间发现,一直到业务员上班试了一遍才知道。
案例二:SSL 证书过期,微信里打开官网提示"非官方网页"
另一家十堰的旅游服务公司,用的是免费证书,90 天有效期,续期脚本因为 DNS API 的 token 过期而静默失败。证书到期后,微信内置浏览器直接拦截,客户在朋友圈转发的活动页全部打不开,一天的推广预算白烧,而运维是在客户投诉之后才知道的。
这两个故障的共同点:都不是服务器"挂了",而是某个资源悄悄耗尽。这类问题靠人肉巡检发现不了,必须上监控。下面这套方案,是我们目前在十堰多个客户项目上实际在跑的组合,配置可以直接抄。
二、选型:为什么中小团队适合 Prometheus + Grafana + Alertmanager
常见三类方案的实际对比:
- 云厂商自带监控:开箱即用,但只覆盖 IaaS 层指标,看不到"网站 5xx 比例""证书剩余天数""某个接口从 200ms 变成 2s"这类业务指标,告警通常只能推到短信和邮件。
- Zabbix:功能全、老牌稳定,但 Agent 较重、模板配置繁琐,改一条告警规则要在 Web 界面里拼表达式,很难进 Git 做版本管理。
- Prometheus 全家桶:指标模型简单(时间序列 + label),配置文件全是 YAML,可以进 Git 审核;Grafana 负责出图;Alertmanager 负责分组、抑制、静默。整套跑在一台 2 核 4G 的机器上,内存占用约 300–500MB。
对十堰本地的中小项目来说,这套组合最大的价值是可复制:同一份 docker-compose 和规则文件,换个 targets 列表就能复用到下一个客户,团队不用重新学一套界面。
三、15 分钟搭起来:docker-compose 一把梭
前提:服务器已装 Docker 与 Compose 插件,开放 9090(Prometheus)、3000(Grafana)、9093(Alertmanager)三个端口——务必只对办公网 IP 放行,不要直接暴露到公网,这三个面板本身没有强认证。
3.1 目录结构
monitor/
├── docker-compose.yml
├── prometheus.yml
├── blackbox.yml
├── alertmanager.yml
└── rules/
└── basic.yml
3.2 docker-compose.yml
services:
prometheus:
image: prom/prometheus:v2.53.0
restart: always
ports: ["127.0.0.1:9090:9090"]
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./rules:/etc/prometheus/rules:ro
- prom_data:/prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.retention.time=15d
node-exporter:
image: prom/node-exporter:v1.8.1
restart: always
pid: host
volumes: ["/:/host:ro,rslave"]
command: ["--path.rootfs=/host"]
blackbox:
image: prom/blackbox-exporter:v0.25.0
restart: always
volumes: ["./blackbox.yml:/etc/blackbox_exporter/config.yml:ro"]
alertmanager:
image: prom/alertmanager:v0.27.0
restart: always
ports: ["127.0.0.1:9093:9093"]
volumes: ["./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro"]
grafana:
image: grafana/grafana:11.1.0
restart: always
ports: ["127.0.0.1:3000:3000"]
volumes: ["grafana_data:/var/lib/grafana"]
environment:
GF_SECURITY_ADMIN_PASSWORD: "换成你自己的强密码"
volumes:
prom_data:
grafana_data:
两个细节值得注意:retention.time=15d 表示只保留 15 天数据,单机大约占用 2–4GB 磁盘,够做故障回溯;所有端口都绑在 127.0.0.1,对外访问走 Nginx 反向代理加 Basic Auth,这是我们给十堰客户交付时的标准做法。
3.3 prometheus.yml:采集主机指标 + 探测网站可用性
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- /etc/prometheus/rules/*.yml
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
scrape_configs:
- job_name: node
static_configs:
- targets: ["node-exporter:9100"]
- job_name: blackbox-http
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://www.ydunet.com
- https://www.ydunet.com/news
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox:9115
node-exporter 负责采集 CPU、内存、磁盘、网卡;blackbox 从外部视角访问网站,能拿到状态码、响应耗时和证书到期时间——案例二那种事故就是靠它兜住的。如果被监控站点在内网,把 targets 改成内网地址即可,探测点跟着部署在对应网段。
四、三条必须配的告警规则
规则不在多,而在每条都能对应一个真实会发生的故障。以下三条是我们给十堰企业客户默认配置的最小集合:
groups:
- name: ydunet-basic
rules:
- alert: DiskUsageHigh
expr: |
(1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|squashfs"}
/ node_filesystem_size_bytes{fstype!~"tmpfs|overlay|squashfs"}) * 100 > 85
for: 10m
labels:
severity: warning
annotations:
summary: "磁盘使用率超过 85%({{ $labels.instance }} {{ $labels.mountpoint }})"
- alert: WebsiteDown
expr: probe_success == 0
for: 2m
labels:
severity: critical
annotations:
summary: "网站不可访问:{{ $labels.instance }}"
- alert: SSLCertExpiringSoon
expr: (probe_ssl_earliest_cert_expiry - time()) / 86400 < 14
for: 1h
labels:
severity: warning
annotations:
summary: "SSL 证书 {{ $value | printf \"%.0f\" }} 天后到期:{{ $labels.instance }}"
三个参数值得说明:磁盘阈值定 85% 而不是 95%,因为 ext4 在剩余空间低于 5% 时写入会明显变慢,留 15% 缓冲意味着日志暴涨时还有 1–2 小时响应时间;for: 10m 用来避开备份脚本造成的瞬时峰值;证书提前 14 天告警,是给续期失败留出第二次机会。
五、告警怎么送到人手上:Alertmanager 推企业微信
规则触发后如果只发邮件,十堰不少客户根本没人看。实际交付时我们统一推到企业微信群,alertmanager.yml 核心配置如下:
route:
receiver: wecom
group_by: [alertname, instance]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: wecom
webhook_configs:
- url: "http://127.0.0.1:8060/webhook/wecom"
send_resolved: true
企业微信群机器人只认它自己的 JSON 格式,中间需要一个转换层。两种做法:一是用开源的 prometheus-webhook-wechat 类适配器做协议转换;二是自己写三十行 Flask,把 Alertmanager 的 payload 拼成 markdown 消息 POST 给群机器人 webhook。我们倾向后者——依赖少,出问题好排查。send_resolved: true 很关键,故障恢复时群里会补一条"已恢复",否则运维永远不知道警报是什么时候结束的。
六、Grafana 上先看这三张图
面板不用一次做几十个,先把三块看板做出来,就能覆盖 80% 的日常判断:
- 主机总览:CPU、内存、磁盘、网卡流量四条曲线,用
node_load1配合核数判断负载是否过载。 - 网站探测:
probe_duration_seconds的 P95 曲线加上probe_success状态带。响应时间从 200ms 涨到 2s,往往比直接宕机更值得警惕。 - 证书倒计时:
(probe_ssl_earliest_cert_expiry - time()) / 86400做成单值面板,一眼看到还剩多少天。
Grafana 里直接导入 Node Exporter Full(ID 1860)也能用,但模板指标太多,客户看不懂。我们给十堰企业交付的版本通常裁到 6 个面板以内,并在图旁边写一句"这条线超过多少就该给我们打电话"。
七、上线检查清单
- 监控服务与被监控业务隔离:Prometheus 不要和网站跑在同一台机器上,至少换一台低配云主机。
- 三个 Web 面板只监听 127.0.0.1,通过 Nginx 反代 + Basic Auth 或 IP 白名单对外。
- 做一次演练:手动写入一个大文件把磁盘顶到 90%,确认 10 分钟内企业微信群里收到告警。
- 补齐日志切割:
/etc/logrotate.d/nginx里配daily、rotate 14、compress,postrotate中执行kill -USR1 $(cat /run/nginx.pid),别等磁盘满了才想起这件事。 - 告警接收人写两个,避免单点;每月抽查一次告警是否真的送达。
在十堰做企业网站和软件交付,客户往往没有专职运维,故障的第一发现人经常是客户自己。把这套监控搭起来,本质上是把"等客户打电话"变成"我们先知道"。上面这份配置从零到跑通大约一小时,之后每个新项目只需要改 targets 列表——这是我们判断性价比最高的一项基础设施投入,也是十堰开发者接私活、做外包时最能拉开交付质量差距的一环。
