0. 写在前面:为什么你需要“神器”而非“常用命令
大家好,我是老杨,干货满满的老杨.欢迎来到互联网遥遥领先的博客. 欢迎点击原文链接或直接访问vps.top365app.com,来看老杨的全球vps信息还有各种咱们用得着的信息实时收集分析项目.
帮老杨点赞、转发、在看以及打开小星标哦
攒今世之功德,修来世之福报
这个设计其实挺巧妙的。你想想,如果用push模式,网络抖动一下数据就丢了,而且还要在每个节点上配置监控服务器地址。Prometheus这种pull模式就简单多了,节点只要暴露一个HTTP接口,其他的都由监控服务器处理。
来看看实际部署:
# 下载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启动后你会看到这样的输出:
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秒,太频繁了会增加系统负担,太稀疏又可能错过关键时刻的数据波动。
光有Prometheus还不够,你得有数据源。Node Exporter就是专门收集Linux系统指标的工具,CPU、内存、磁盘、网络,该有的都有。
在每台需要监控的服务器上部署Node Exporter:
# 下载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使用率:
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[2m])) * 100)这个查询语句的逻辑是:先用rate函数计算idle模式下的CPU时间变化率,然后用100减去这个值,就得到了CPU使用率。
除了系统指标,我们还需要知道服务是否正常。这时候Blackbox Exporter就派上用场了。它可以通过HTTP、HTTPS、DNS、TCP、ICMP等协议探测服务的可用性。
# 下载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.ymlBlackbox Exporter的妙处在于,它不需要在目标服务器上安装任何东西。从监控服务器发起探测请求,就能知道目标服务的健康状态。
数据收集完了,但是一堆数字谁看得懂?这时候就需要Grafana来做可视化展示。
# 下载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-serverGrafana启动后,访问 http://localhost:3000 就能看到登录界面。默认用户名和密码都是admin。
我一般会导入几个经典的Dashboard模板:
这些模板都是社区贡献的,质量相当不错。当然,你也可以根据自己的需求自定义面板。
比如我经常用到的一个Panel,显示服务器的负载情况:
{
"targets":[
{
"expr":"node_load1",
"legendFormat":"{{instance}} - 1m load",
"refId":"A"
},
{
"expr":"node_load5",
"legendFormat":"{{instance}} - 5m load",
"refId":"B"
}
],
"type":"graph"
}监控不告警等于白搭。但告警也是门艺术,告警太多了会让人麻痹,告警太少了又可能错过重要问题。
我的经验是,告警规则要分级:
创建告警规则文件:
# 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连接钉钉:
# 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服务来转发消息到钉钉:
#!/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:Prometheus数据量太大
电商网站的指标数据量确实不小。一开始我按照默认配置,保留15天的数据,结果发现磁盘空间不够用。后来优化了存储策略:
./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:
# 创建监控用户
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:业务指标监控
除了系统指标,业务指标也很重要。比如订单量、支付成功率、用户注册数等。我在应用代码里埋了一些自定义指标:
<?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接口:
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. Prometheus集群部署
两台Prometheus服务器,采用相同配置,数据存储到共享存储:
# prometheus-1.yml
global:
external_labels:
replica: prometheus-1
# prometheus-2.yml
global:
external_labels:
replica: prometheus-22. Grafana高可用
Grafana可以配置外部数据库,这样多个实例就能共享配置:
[database]
type = mysql
host = 192.168.1.100:3306
name = grafana
user = grafana
password = password3. AlertManager集群
AlertManager支持集群模式,多个实例之间会自动同步告警状态:
# 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坑2:label滥用
label虽然灵活,但不能滥用。每增加一个label,都会成倍增加时间序列数量。我见过有人把用户ID作为label,结果Prometheus直接被撑爆了。
坑3:告警风暴
告警规则设置不当,容易产生告警风暴。比如一台服务器宕机,可能会触发十几个相关告警。我的做法是设置告警依赖关系:
- 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做服务发现:
scrape_configs:
- job_name: 'consul-services'
consul_sd_configs:
- server: 'localhost:8500'
relabel_configs:
- source_labels: [__meta_consul_service]
target_label: job智能告警
基于历史数据训练模型,设置动态阈值,减少误报:
predict_linear(cpu_usage[1h], 3600) > 90分布式追踪
集成Jaeger或者Zipkin,追踪请求在微服务间的调用链路:
# prometheus.yml
scrape_configs:
- job_name: 'jaeger'
static_configs:
- targets: ['jaeger:14269']说了这么多,其实核心思想就一个:用合适的工具解决实际问题。监控系统不在于多么复杂,关键是要能及时发现问题、快速定位原因。
开源监控栈虽然需要一定的学习成本,但一旦掌握了,就是一个非常强大的工具集。而且随着云原生技术的发展,这套技术栈的应用场景会越来越广。
最后说一句,监控系统搭完只是开始。真正的价值在于持续优化告警规则、完善监控指标、积累故障处理经验。这是个长期的过程,但也是运维工程师成长的必经之路。
这里老杨先声明一下,日常生活中大家都叫老杨波哥,跟辈分没关系,主要是岁数大了.就一个代称而已. 老杨的00后小同事老杨喊都是带哥的.张哥,李哥的. 但是这个称呼呀,在线下参加一些活动时.金主爸爸也这么叫就显的不太合适. 比如上次某集团策划总监,公司开大会来一句:“今个咱高兴!有请IT运维技术圈的波哥讲两句“ 这个氛围配这个称呼在互联网这行来讲就有点对不齐! 每次遇到这个情况老杨就想这么接话: “遇到各位是缘分,承蒙厚爱,啥也别说了,都在酒里了.老杨干了,你们随意!” 所以以后咱们改叫老杨,即市井又低调.还挺亲切,老杨觉得挺好.
运维X档案系列文章:
企业级 Kubernetes 集群安全加固全攻略( 附带一键检查脚本)
看完别走.修行在于点赞、转发、在看.攒今世之功德,修来世之福报
点击阅读原文或打开地址实时收集分析全球vps的项目 vps.top365app.com
老杨AI的号: 98dev