首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >运维没用?老杨聊聊一套监控系统到底能为公司省多少钱(p8s为例)

运维没用?老杨聊聊一套监控系统到底能为公司省多少钱(p8s为例)

作者头像
IT运维技术圈
发布2025-10-09 12:17:16
发布2025-10-09 12:17:16
3290
举报
文章被收录于专栏:IT运维技术圈IT运维技术圈

0. 写在前面:为什么你需要“神器”而非“常用命令

大家好,我是老杨,干货满满的老杨.欢迎来到互联网遥遥领先的博客. 欢迎点击原文链接或直接访问vps.top365app.com,来看老杨的全球vps信息还有各种咱们用得着的信息实时收集分析项目.

帮老杨点赞、转发、在看以及打开小星标哦

攒今世之功德,修来世之福报


有时候我觉得咱们运维人啊,就像家里的原配媳妇。心里装着全家,手里忙着柴米油盐,默默守着日子。可惜呀,大家习惯了你的付出,一旦饭不合口,全家人第一时间怪你,谁还记得你平时的操心呢?

老杨今天就给咱运维人算算账,一个好的运维能给公司做多大贡献,省了多少钱,就拿prometheus为例聊聊.

一套监控的重要性和能给公司Prometheus是Google开源出来的。跟传统的push模式不同,Prometheus采用pull模式,主动去各个节点拉取数据。

这个设计其实挺巧妙的。你想想,如果用push模式,网络抖动一下数据就丢了,而且还要在每个节点上配置监控服务器地址。Prometheus这种pull模式就简单多了,节点只要暴露一个HTTP接口,其他的都由监控服务器处理。

来看看实际部署:

代码语言:javascript
复制
# 下载Prometheus
wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz
tar xzf prometheus-2.45.0.linux-amd64.tar.gz
cd prometheus-2.45.0.linux-amd64

# 创建配置文件
cat > prometheus.yml << EOF
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alert_rules.yml"

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100', '192.168.1.10:9100', '192.168.1.11:9100']
    scrape_interval: 10s
    metrics_path: /metrics

  - job_name: 'blackbox'
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
        - https://www.baidu.com
        - https://your-website.com
        - http://192.168.1.10:8080/health
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: localhost:9115

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - localhost:9093
EOF

# 启动Prometheus
./prometheus --config.file=prometheus.yml --storage.tsdb.path=./data

启动后你会看到这样的输出:

代码语言:javascript
复制
level=info ts=2024-01-15T10:30:00.000Z caller=main.go:366 msg="Starting Prometheus"
level=info ts=2024-01-15T10:30:00.100Z caller=web.go:542 component=web msg="Start listening for connections" address=0.0.0.0:9090
level=info ts=2024-01-15T10:30:00.200Z caller=main.go:782 msg="Server is ready to receive web requests."
...

这里有个小技巧,scrape_interval我一般设置成10-15秒,太频繁了会增加系统负担,太稀疏又可能错过关键时刻的数据波动。

Node Exporter:系统指标的窗口

光有Prometheus还不够,你得有数据源。Node Exporter就是专门收集Linux系统指标的工具,CPU、内存、磁盘、网络,该有的都有。

在每台需要监控的服务器上部署Node Exporter:

代码语言:javascript
复制
# 下载Node Exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.0/node_exporter-1.6.0.linux-amd64.tar.gz
tar xzf node_exporter-1.6.0.linux-amd64.tar.gz
cd node_exporter-1.6.0.linux-amd64

# 启动Node Exporter
nohup ./node_exporter --web.listen-address=":9100" > node_exporter.log 2>&1 &

Node Exporter默认会暴露大量指标,但我们通常只关心核心的几个:

  • node_cpu_seconds_total:CPU使用情况
  • node_memory_MemAvailable_bytes:可用内存
  • node_filesystem_avail_bytes:磁盘剩余空间
  • node_network_receive_bytes_total:网络接收字节数

这些指标的命名看起来有点复杂,但实际用起来还是很直观的。比如计算CPU使用率:

代码语言:javascript
复制
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m])) * 100)

这个查询语句的逻辑是:先用rate函数计算idle模式下的CPU时间变化率,然后用100减去这个值,就得到了CPU使用率。

Blackbox Exporter:服务可用性探测

除了系统指标,我们还需要知道服务是否正常。这时候Blackbox Exporter就派上用场了。它可以通过HTTP、HTTPS、DNS、TCP、ICMP等协议探测服务的可用性。

代码语言:javascript
复制
# 下载Blackbox Exporter
wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.24.0/blackbox_exporter-0.24.0.linux-amd64.tar.gz
tar xzf blackbox_exporter-0.24.0.linux-amd64.tar.gz
cd blackbox_exporter-0.24.0.linux-amd64

# 创建配置文件
cat > blackbox.yml << EOF
modules:
  http_2xx:
    prober: http
    timeout: 5s
    http:
      valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
      valid_status_codes: []
      method: GET
      headers:
        Host: vhost.example.com
        Accept-Language: en-US
      no_follow_redirects: false
      fail_if_ssl: false
      fail_if_not_ssl: false
      preferred_ip_protocol: "ip4"

  tcp_connect:
    prober: tcp
    timeout: 5s

  dns:
    prober: dns
    timeout: 5s
    dns:
      query_name: "example.com"
      query_type: "A"
EOF

# 启动Blackbox Exporter
./blackbox_exporter --config.file=blackbox.yml

Blackbox Exporter的妙处在于,它不需要在目标服务器上安装任何东西。从监控服务器发起探测请求,就能知道目标服务的健康状态。

Grafana:让数据会说话

数据收集完了,但是一堆数字谁看得懂?这时候就需要Grafana来做可视化展示。

代码语言:javascript
复制
# 下载Grafana
wget https://dl.grafana.com/enterprise/release/grafana-enterprise-10.0.0.linux-amd64.tar.gz
tar -zxf grafana-enterprise-10.0.0.linux-amd64.tar.gz
cd grafana-10.0.0

# 修改配置
cat > conf/defaults.ini << EOF
[server]
http_port = 3000
domain = localhost

[database]
type = sqlite3
path = grafana.db

[auth.anonymous]
enabled = true
org_role = Viewer
EOF

# 启动Grafana
./bin/grafana-server

Grafana启动后,访问 http://localhost:3000 就能看到登录界面。默认用户名和密码都是admin。

我一般会导入几个经典的Dashboard模板:

  • • Node Exporter Full (ID: 1860):系统监控面板
  • • Blackbox Exporter (ID: 7587):服务可用性面板
  • • Prometheus 2.0 Stats (ID: 3662):Prometheus自身监控

这些模板都是社区贡献的,质量相当不错。当然,你也可以根据自己的需求自定义面板。

比如我经常用到的一个Panel,显示服务器的负载情况:

代码语言:javascript
复制
{
  "targets":[
    {
      "expr":"node_load1",
      "legendFormat":"{{instance}} - 1m load",
      "refId":"A"
    },
    {
      "expr":"node_load5",
      "legendFormat":"{{instance}} - 5m load",
      "refId":"B"
    }
],
"type":"graph"
}

AlertManager:告警的艺术

监控不告警等于白搭。但告警也是门艺术,告警太多了会让人麻痹,告警太少了又可能错过重要问题。

我的经验是,告警规则要分级:

  1. 1. Critical级别:服务完全不可用,需要立即处理
  2. 2. Warning级别:性能异常,需要关注但不紧急
  3. 3. Info级别:一般性信息,可以延后处理

创建告警规则文件:

代码语言:javascript
复制
# alert_rules.yml
groups:
-name:critical-alerts
rules:
-alert:InstanceDown
    expr:up==0
    for:1m
    labels:
      severity:critical
    annotations:
      summary:"实例 {{ $labels.instance }} 已下线"
      description:"{{ $labels.instance }} 已经下线超过1分钟,请立即检查"

-alert:HighCPUUsage
    expr:100-(avgby(instance)(rate(node_cpu_seconds_total{mode="idle"}[2m]))*100)>90
    for:5m
    labels:
      severity:critical
    annotations:
      summary:"{{ $labels.instance }} CPU使用率过高"
      description:"CPU使用率已达到 {{ $value }}%,持续5分钟以上"

-name:warning-alerts
rules:
-alert:HighMemoryUsage
    expr:(1-(node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes))*100>80
    for:10m
    labels:
      severity:warning
    annotations:
      summary:"{{ $labels.instance }} 内存使用率较高"
      description:"内存使用率为 {{ $value }}%,请关注"

-alert:DiskSpaceLow
    expr:(node_filesystem_avail_bytes/node_filesystem_size_bytes)*100<20
    for:30m
    labels:
      severity:warning
    annotations:
      summary:"{{ $labels.instance }} 磁盘空间不足"
      description: "{{ $labels.mountpoint }} 剩余空间仅 {{ $value }}%"

这里我特别想说说告警的时间设置。CPU使用率过高我设置了5分钟的持续时间,因为短暂的CPU峰值是正常的,但持续高负载就需要关注了。而磁盘空间告警我设置了30分钟,因为磁盘空间变化相对缓慢。

钉钉告警:接地气的通知方式

邮件告警太慢,短信告警要钱,钉钉机器人既免费又实时,是我最推荐的告警方式。

配置AlertManager连接钉钉:

代码语言:javascript
复制
# alertmanager.yml
global:
resolve_timeout:5m

route:
group_by: ['alertname', 'severity']
group_wait:10s
group_interval:10s
repeat_interval:1h
receiver:'dingtalk-webhook'
routes:
-match:
      severity:critical
    receiver:'dingtalk-critical'
    repeat_interval:30m

receivers:
-name:'dingtalk-webhook'
webhook_configs:
-url:'http://localhost:8080/webhook/dingtalk/general'
    send_resolved:true

-name:'dingtalk-critical'
webhook_configs:
-url:'http://localhost:8080/webhook/dingtalk/critical'
    send_resolved: true

然后需要写个简单的webhook服务来转发消息到钉钉:

代码语言:javascript
复制
#!/usr/bin/env python3
import json
import requests
from flask import Flask, request

app = Flask(__name__)

DINGTALK_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"

@app.route('/webhook/dingtalk/<channel>', methods=['POST'])
defdingtalk_webhook(channel):
    data = request.json
    
    for alert in data.get('alerts', []):
        status = alert['status']
        annotations = alert['annotations']
        labels = alert['labels']
        
        if status == 'firing':
            color = "#FF0000"if labels.get('severity') == 'critical'else"#FFA500"
            message = f"🚨 告警触发\n**{annotations['summary']}**\n{annotations['description']}"
        else:
            color = "#00FF00"
            message = f"✅ 告警恢复\n**{annotations['summary']}**"
        
        payload = {
            "msgtype": "markdown",
            "markdown": {
                "title": "监控告警",
                "text": message
            }
        }
        
        requests.post(DINGTALK_WEBHOOK, json=payload)
    
    return"OK"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

这样配置后,一旦触发告警,钉钉群里就会收到消息。我们团队用了两年多,效果很好。

实战经验:电商网站的监控部署

之前我帮一个朋友做电商网站的监控,3台服务器,日访问量大概10万+。这个案例比较典型,我来详细说说。

架构是这样的:

  • • 1台监控服务器(4核8G):跑Prometheus、Grafana、AlertManager
  • • 2台Web服务器(8核16G):跑Nginx + PHP-FPM
  • • 1台数据库服务器(16核32G):跑MySQL主从

部署过程中遇到了几个问题,也积累了一些经验。

问题1:Prometheus数据量太大

电商网站的指标数据量确实不小。一开始我按照默认配置,保留15天的数据,结果发现磁盘空间不够用。后来优化了存储策略:

代码语言:javascript
复制
./prometheus \
  --config.file=prometheus.yml \
  --storage.tsdb.path=./data \
  --storage.tsdb.retention.time=7d \
  --storage.tsdb.retention.size=50GB \
  --storage.tsdb.wal-compression

通过压缩WAL日志和限制存储大小,磁盘使用量控制在了合理范围内。

问题2:MySQL监控配置

数据库监控比较特殊,需要专门的Exporter。我用的是mysqld_exporter:

代码语言:javascript
复制
# 创建监控用户
mysql> CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'StrongPassword123!';
mysql> GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'exporter'@'localhost';
mysql> GRANT SELECT ON performance_schema.* TO 'exporter'@'localhost';
mysql> FLUSH PRIVILEGES;

# 启动mysqld_exporter
export DATA_SOURCE_NAME='exporter:StrongPassword123!@(localhost:3306)/'
./mysqld_exporter --web.listen-address=":9104"

这样就能收集到数据库的连接数、查询QPS、慢查询数量等关键指标。

问题3:业务指标监控

除了系统指标,业务指标也很重要。比如订单量、支付成功率、用户注册数等。我在应用代码里埋了一些自定义指标:

代码语言:javascript
复制
<?php
// 订单创建指标
$registry = new \Prometheus\CollectorRegistry(new \Prometheus\Storage\Redis());
$counter = $registry->getOrRegisterCounter('app', 'orders_total', 'Total orders', ['status']);
$counter->inc(['created']);

// 支付成功率指标
$gauge = $registry->getOrRegisterGauge('app', 'payment_success_rate', 'Payment success rate');
$gauge->set($success_rate);
?>

然后在Nginx配置里暴露metrics接口:

代码语言:javascript
复制
location /metrics {
    allow 192.168.1.0/24;
    deny all;
    fastcgi_pass unix:/var/run/php-fpm.sock;
    fastcgi_param SCRIPT_FILENAME /var/www/metrics.php;
    include fastcgi_params;
}

好的监控能省多少钱?这个帐咱们该怎么算?

1. 资源节省角度
  • 思路:通过监控发现哪些机器、容器、服务过度分配资源,从而做降配或合并。
  • 计算公式: (优化前资源费用−优化后资源费用)×12(月)(优化前资源费用 - 优化后资源费用) \times 12(月)
2. 开源替代角度
  • 思路:对比商业监控产品和开源监控方案的订阅/授权费用差异。
  • 计算公式: 商业授权费用−(开源部署硬件成本+人力运维成本)商业授权费用 - (开源部署硬件成本 + 人力运维成本)
3. 及时恢复角度(减少宕机时间损失)
  • 思路:监控提前预警 + 故障快速定位,能大幅降低 MTTR(平均修复时间)。
  • 计算公式: (无监控时平均宕机时长−有监控时宕机时长)×每小时业务损失金额×年均故障次数(无监控时平均宕机时长 - 有监控时宕机时长) \times 每小时业务损失金额 \times 年均故障次数
4. 预防故障角度
  • 思路:监控提前发现风险(磁盘爆满、CPU 飙升、证书过期等),避免重大事故。
  • 计算公式: (可能造成的业务损失金额)×发生概率×预防率(可能造成的业务损失金额) \times 发生概率 \times 预防率
5. 人力效率角度
  • 思路:减少人工巡检、加班、多人参与排查的成本。
  • 计算公式: (减少的人力小时数)×(人力成本/小时)(减少的人力小时数) \times (人力成本/小时)

样例:

  • • Zabbix企业版:大概5万/年
  • • 阿里云监控:按量付费,中等规模网站大概2万/年
  • • 专业运维人员:至少10万/年

开源方案的成本:

  • • 监控服务器:2000元(一次性投入)
  • • 域名和SSL证书:300元/年
  • • 学习和部署时间:1-2周

高可用设计:不能让监控成为单点

监控系统本身也要考虑高可用。我的做法是:

1. Prometheus集群部署

两台Prometheus服务器,采用相同配置,数据存储到共享存储:

代码语言:javascript
复制
# prometheus-1.yml
global:
  external_labels:
    replica: prometheus-1

# prometheus-2.yml  
global:
  external_labels:
    replica: prometheus-2

2. Grafana高可用

Grafana可以配置外部数据库,这样多个实例就能共享配置:

代码语言:javascript
复制
[database]
type = mysql
host = 192.168.1.100:3306
name = grafana
user = grafana
password = password

3. AlertManager集群

AlertManager支持集群模式,多个实例之间会自动同步告警状态:

代码语言:javascript
复制
# alertmanager.yml
global:
  smtp_smarthost: 'localhost:587'

cluster:
  listen-address: "0.0.0.0:9094"
  peers:
    - 192.168.1.10:9094
    - 192.168.1.11:9094

这样配置后,任何一台服务器挂掉,监控系统都能正常工作。

一些踩坑经验

搞了这么多年监控,也踩过不少坑。分享几个比较典型的:

坑1:指标命名不规范

自定义指标的命名很重要,要遵循Prometheus的命名规范:

  • • 用下划线分隔单词,不要用驼峰
  • • 单位要明确,比如 _seconds_bytes_total
  • • 不要在指标名里包含label信息

坑2:label滥用

label虽然灵活,但不能滥用。每增加一个label,都会成倍增加时间序列数量。我见过有人把用户ID作为label,结果Prometheus直接被撑爆了。

坑3:告警风暴

告警规则设置不当,容易产生告警风暴。比如一台服务器宕机,可能会触发十几个相关告警。我的做法是设置告警依赖关系:

代码语言:javascript
复制
- alert:ServiceDown
expr:up{job="web"}==0
labels:
    severity:critical

-alert:HighResponseTime
expr:http_request_duration_seconds>5
labels:
    severity:warning
# 只有在服务正常时才告警
condition:up{job="web"}== 1

后续优化方向

基础监控搭好后,还有很多可以优化的地方:

服务发现

手工维护监控目标列表太麻烦,可以集成Consul或者etcd做服务发现:

代码语言:javascript
复制
scrape_configs:
  - job_name: 'consul-services'
    consul_sd_configs:
      - server: 'localhost:8500'
    relabel_configs:
      - source_labels: [__meta_consul_service]
        target_label: job

智能告警

基于历史数据训练模型,设置动态阈值,减少误报:

代码语言:javascript
复制
predict_linear(cpu_usage[1h], 3600) > 90

分布式追踪

集成Jaeger或者Zipkin,追踪请求在微服务间的调用链路:

代码语言:javascript
复制
# prometheus.yml
scrape_configs:
  - job_name: 'jaeger'
    static_configs:
      - targets: ['jaeger:14269']

说了这么多,其实核心思想就一个:用合适的工具解决实际问题。监控系统不在于多么复杂,关键是要能及时发现问题、快速定位原因。

开源监控栈虽然需要一定的学习成本,但一旦掌握了,就是一个非常强大的工具集。而且随着云原生技术的发展,这套技术栈的应用场景会越来越广。

最后说一句,监控系统搭完只是开始。真正的价值在于持续优化告警规则、完善监控指标、积累故障处理经验。这是个长期的过程,但也是运维工程师成长的必经之路。

老杨时间

这里老杨先声明一下,日常生活中大家都叫老杨波哥,跟辈分没关系,主要是岁数大了.就一个代称而已. 老杨的00后小同事老杨喊都是带哥的.张哥,李哥的. 但是这个称呼呀,在线下参加一些活动时.金主爸爸也这么叫就显的不太合适. 比如上次某集团策划总监,公司开大会来一句:“今个咱高兴!有请IT运维技术圈的波哥讲两句“ 这个氛围配这个称呼在互联网这行来讲就有点对不齐! 每次遇到这个情况老杨就想这么接话: “遇到各位是缘分,承蒙厚爱,啥也别说了,都在酒里了.老杨干了,你们随意!” 所以以后咱们改叫老杨,即市井又低调.还挺亲切,老杨觉得挺好.

运维X档案系列文章:

从告警到CTO:一个P0故障的11小时生死时速

企业级 Kubernetes 集群安全加固全攻略( 附带一键检查脚本)

看完别走.修行在于点赞、转发、在看.攒今世之功德,修来世之福报

点击阅读原文或打开地址实时收集分析全球vps的项目 vps.top365app.com

老杨AI的号: 98dev

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT运维技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 有时候我觉得咱们运维人啊,就像家里的原配媳妇。心里装着全家,手里忙着柴米油盐,默默守着日子。可惜呀,大家习惯了你的付出,一旦饭不合口,全家人第一时间怪你,谁还记得你平时的操心呢?
  • 老杨今天就给咱运维人算算账,一个好的运维能给公司做多大贡献,省了多少钱,就拿prometheus为例聊聊.
  • 一套监控的重要性和能给公司Prometheus是Google开源出来的。跟传统的push模式不同,Prometheus采用pull模式,主动去各个节点拉取数据。
  • Node Exporter:系统指标的窗口
  • Blackbox Exporter:服务可用性探测
  • Grafana:让数据会说话
  • AlertManager:告警的艺术
  • 钉钉告警:接地气的通知方式
  • 实战经验:电商网站的监控部署
  • 好的监控能省多少钱?这个帐咱们该怎么算?
    • 1. 资源节省角度
    • 2. 开源替代角度
    • 3. 及时恢复角度(减少宕机时间损失)
    • 4. 预防故障角度
    • 5. 人力效率角度
  • 高可用设计:不能让监控成为单点
  • 一些踩坑经验
  • 后续优化方向
  • 老杨时间
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档