服务监控与告警
0 简介
服务监控与告警保证对服务的实时或准实时监控
监控系统整体架构
Supervisor是一套通用的进程管理工具,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。这里用来管理监控所需要的几大组件,保证监控系统持续良好运行。Prometheus是开源监控报警系统, 其基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。Alertmanager是一个独立的告警模块,接收Prometheus等客户端发来的警报,之后通过分组、删除重复等处理,并将它们通过路由发送给正确的接收器;告警方式可以按照不同的规则发送给不同的模块负责人。node_exporter用来监控服务器CPU、内存、磁盘、I/O等信息。
构建一整套监控系统需要做以下事情:
- 安装supervisor 管理接下来的监控系统;
- 安装prometheus
- 安装node exporter
- 安装altermanager
- 安装grafana
- 新建企业微信机器人
- 搭建bridge服务
- 配置supervisor
- 配置prometheus
- 配置altermanager
- 配置grafana
- 在服务端编写监控服务
- 在prometheus中配置监控规则
- 在grafana中新建监控项目(与告警项)
- 解析告警信息
- 其他事项...
1 Supervisor
1.1 安装supervisor
pip3 install supervisor
supervisor安装后会生成三个执行程序:supervisord
, supervisorctl
及echo_supervisord_conf
:
supervisord
用于管理supervisor 本身服务supervisorctl
用于管理我们需要委托给supervisor管理的服务echo_supervisord_conf
用于生成supervisor
的配置文件
1.2 初始化supervisor
mkdir /etc/supervisord.d
echo_supervisord_conf > /etc/supervisord.conf
1.3 启动supervisor
启动:supervisord -c /etc/supervisord.conf
关闭:supervisorctl shutdown
常用命令:
supervisorctl stop program_name # 停止某一个进程,program_name 为 [program:x] 里的 x
supervisorctl start program_name # 启动某个进程
supervisorctl restart program_name # 重启某个进程
supervisorctl stop groupworker: # 结束所有属于名为 groupworker 这个分组的进程 (start,restart 同理)
supervisorctl stop groupworker:name1 # 结束 groupworker:name1 这个进程 (start,restart 同理)
supervisorctl stop all # 停止全部进程,注:start、restartUnlinking stale socket /tmp/supervisor.sock、stop 都不会载入最新的配置文件
supervisorctl reload # 载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程
supervisorctl update # 根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启
1.4配置supervisord.conf
#修改[include]
files=/etc/supervisord.d/*.ini
# 这句目的是让supervisor识别并管理(如启动、停止等)委托的服务
然后重启supervisor: supervisorctl reload
.
1.5可能的问题
supervisor使用有时候会报如下错误:
unix:///tmp/supervisor.sock no such file
原因是supervisor默认配置会把socket文件和pid守护进程生成在/tmp/目录下,/tmp/目录是缓存目录,Linux会根据不同情况自动删除其下面的文件。
原因找到了,就好办了,将supervisor配置文件里的相应地方改掉就好了。
vi /etc/supervisord.conf
修改:
[unix_http_server]
;file=/tmp/supervisor.sock ; (the path to the socket file)
file=/var/run/supervisor.sock ; 修改为 /var/run 目录,避免被系统删除
[supervisord]
;logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile=/var/log/supervisor/supervisord.log ; 修改为 /var/log 目录,避免被系统删除
pidfile=/var/run/supervisord.pid ; 修改为 /var/run 目录,避免被系统删除
...
[supervisorctl]
; 必须和'unix_http_server'里面的设定匹配
;serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
serverurl=unix:///var/run/supervisor.sock ; 修改为 /var/run 目录,避免被系统删除
supervisorctl update
2 node_exporter
2.1安装node_exporter
node_exporter
监控服务器的运行状态(如cpu、内存、硬盘等),
# 进入目标目录如:/app
wget https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-amd64.tar.gz
tar xvf node_exporter-0.18.1.linux-amd64.tar.gz
# 重命名目录
mv node_exporter-0.18.1.linux-amd64 node_exporter-0.18.1
然后在/etc/supervisord.d
目录下生成node_exporter.ini
.
然后添加如下内容:
[program:node_exporter]
directory=/app/node_exporter-0.18.1
command=/app/node_exporter-0.18.1/node_exporter
autostart=true
autorestart=true
startsecs=1
startretries=3
user=root
redirect_stderr=true
stdout_logfile=/tmp/node_exporter.log
启动组件:
备注:需要更新下:supervisorctl update, 然后node会自动启动
supervisorctl start node_exporte
3. prometheus
3.1 安装prometheus
cd /app
wget https://github.com/prometheus/prometheus/releases/download/v2.20.1/prometheus-2.20.1.linux-amd64.tar.gz
tar xvfz prometheus-*.tar.gz
mv prometheus-2.20.1.linux-amd64 prometheus-2.20.1
同样地,在/etc/supervisord.d
中创建prometheus.ini
,并在其中加入:
[program:prometheus]
directory=/data/app/prometheus-2.20.1
command=/app/prometheus-2.20.1/prometheus --config.file /app/prometheus-2.20.1/prometheus.yml --storage.tsdb.path=/app/prometheus-2.20.1/data
autostart=true
autorestart=true
startsecs=1
startretries=3
user=root
redirect_stderr=true
stdout_logfile=/tmp/prometheus.log
然后配置prometheus的配置文件:
cd /data/prometheus-2.20.1
vim prometheus.yml
添加:
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093']
#- alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
- /data/marvin/pkg/app/prometheus-2.20.1/rules/node.yml # "first_rules.yml"
# - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: 'prometheus'
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ['localhost:9090']
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'service1_job'
static_configs:
- targets: ['service1_address:8000']
- job_name: 'service2_job'
static_configs:
- targets: ['service2_address:8003']
其中node_exporter
是在上面部署的node_exporter, 其默认port为9100, 后面service1,service2是需要监控的服务
启动:
supervisorctl start prometheus
在浏览器输入:
http://server_ip_address:9090/graph
可以查看类似如下页面,可在其中输入promQL语句
4 alertmanager
4.1 安装alertmanager
cd /app
wget https://github.com/prometheus/alertmanager/releases/download/v0.23.0/alertmanager-0.23.0.linux-amd64.tar.gz
tar xvf alertmanager-0.23.0.linux-amd64.tar.gz
mv alertmanager-0.23.0.linux-amd64.tar.gz alertmanager-0.23.0
vi /etc/supervisord.d/alertmanager.ini
# 添加如下内容:
[program:altermanager]
directory=/app/alertmanager-0.23.0
command=./app/alertmanager-0.23.0
autostart=true
autorestart=true
startsecs=1
startretries=3
user=root
redirect_stderr=true
stdout_logfile=/tmp/altermanager.log
然后配置alertmanager配置文件:
cd /app/alertmanager-0.23.0
vim alertmanager.yml
# cat alertmanager.yml
route:
group_by: ['alertname']
group_wait: 5s
group_interval: 20s
repeat_interval: 1m
receiver: 'web.hook'
receivers:
- name: 'web.hook'
webhook_configs:
- url: 'http://127.0.0.1:1111/' # 这个是下面bridge服务的地址,可按需修改
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
5 grafana
5.1 安装grafana
cd /app
wget https://dl.grafana.com/oss/release/grafana-7.1.3.linux-amd64.tar.gz
tar xvf grafana-7.1.3.linux-amd64.tar.gz
vi /etc/supervisord.d/grafana-server.ini
# 添加如下内容:
[program:grafana-server]
directory=/app/grafana-7.1.3
command=/app/grafana-7.1.3/bin/grafana-server -homepath /app/grafana-7.1.3
autostart=true
autorestart=true
startsecs=1
startretries=3
user=root
redirect_stderr=true
stdout_logfile=/tmp/grafana.log
supervisorctl start grafana-server
5.2 grafana board
在浏览器中输入
http://your_server_address:3000
点击左侧边栏上面的“+”加号可添加新的看版:
点击+ Add new panel
即可添加新的看版,在下图的metrics中编写promQL语句(本处示例为: prometheus_http_requests_total
)即可生成统计图:
上图上面的Alert
按钮可以为此统计数据设置告警,不过在这里设置告警之前需要先在Alerting
页中添加告警通道:
然后点击New channel
即可新建:
这里我们选择的是webhook, 下面的url添加企业微信机器人的webhook地址.
6 新建企业微信机器人
在想要告警的群,右键->添加群机器人,按提示来后,会生成webhook 地址, 类似下面:
https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=b0221169-eg78-349i-87we-09ef4g4ctyu1
7 编写 bridge服务
-
编写请求转移程序
alertmanage的将向此bridge服务发送请求,request的信息即为告警信息,然后,bridge服务将以此告警信息为数据请求企业微信机器人:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import sys sys.path.append(os.getcwd()) import json from tornado.ioloop import IOLoop from tornado.httpserver import HTTPServer from tornado.web import RequestHandler, Application from alter_manager_info_format import parse_info import json import requests # 下面为企业微信机器人对应的webhook地址 url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxxxxxxxxxxxxxxx" head = {"Content-type": "application/json", "Accept": "*/*"} class BaseHandler(RequestHandler): def set_default_headers(self): self.set_header("Access-Control-Allow-Origin", "*") self.set_header("Access-Control-Allow-Headers", "x-requested-with") self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS') def post(self): jsonstr = str(self.request.body, encoding="utf8") jd = json.loads(jsonstr) res = grafana_extract(jd) data = json.dumps({"msgtype": "markdown", "markdown": { "content": res }}) res = requests.post(url, data=data, headers=head) def get(self): self.write('some get') def options(self): # no body self.set_status(204) self.finish() if __name__ == '__main__': import time # 创建 APPlication对象,进行若干个对服务器的设置 # 例如:路由列表,模版路径,静态资源路径等 app = Application([('/', BaseHandler)]) # 创建服务器程序 server = HTTPServer(app) server.bind(1111) server.start(2) # Forks multiple sub-processes IOLoop.instance().start()
-
编写告警信息解析程序
企业微信机器人支持多种解析格式,比如文本、markdown等。
def _parse(msg): tmp = '' if type(msg) is dict: for key, value in msg.items(): if key == 'receiver' or key == 'status': continue if type(value) is str or type(value) is int or type(value) is float: color = 'comment' if value == 'warning': color = 'warning' elif key in {'instance', 'job', 'description', 'summary','device','mountpoint'}: color = 'info' if key == "alertname": tmp += f"# {value}\n" elif color != 'comment': tmp += f"**{key}:<font color=\"{color}\">{value}</font>**\n" else: tmp += f">{key}:<font color=\"{color}\">{value}</font>\n" else: tmp += _parse(value) elif type(msg) is list: for ele in msg: tmp += _parse(ele) return tmp
8 服务监控服务
在python有prometheus_client
可以使用,助力监控服务构建。
from prometheus_client import start_http_server, Summary, Counter
class Monitor(object):
def __init__(self, name, description=None, labels=None, port=8000):
_ = start_http_server(port)
self.Counter = Counter(name, description, labels)
self.http_counter = Counter('xxx_http_request', 'descrtiption', ['business', 'code'])
def info_inc(self, labels, value):
self.Counter.labels(*labels).inc(value)
def http_inc(self, labels):
self.http_counter.labels(*labels).inc(1.)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架