1、概念简述 prometheus(普罗米修斯):天生为采集存储监控数据而生的时序数据库。prometheus通过各种Exporter采集到监控数据,然后存储进prometheus中,以供查询展示
grafana:一个监控仪表系统。grafana的数据来源可以有很多(如:Prometheus、Graphite、OpenTSDB、InfluxDB、MySQL/PostgreSQL、Microsoft SQL Serve等等),其中用得最多的数据源是prometheus
注:prometheus也有自己的UI,不过功能没有grafana强大
2、安装 prometheus 第一步:确保安装有docker 查看docker版本
第二步:拉取镜像 1 2 docker pull prom/prometheus:v3.2.0
第三步:准备相关挂载目录及文件 准备目录
1 2 3 4 5 6 7 8 mkdir -p /opt/prom/{data,config,rules} chmod -R 777 /opt/prom/data chmod -R 777 /opt/prom/config chmod -R 777 /opt/prom/rules
准备文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 cat > /opt/prom/config/prometheus.yml << \EOF global: scrape_interval: 45s evaluation_interval: 45s rule_files: - /prometheus/rules/*.rules scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090' ] EOF cat /opt/prom/config/prometheus.yml
prometheus配置项说明
global:全局配置 (如果有内部单独设定,会覆盖这个参数)
alerting:告警插件定义。这里会设定alertmanager这个报警插件
rule_files:告警规则。 按照设定参数进行扫描加载,用于自定义报警规则,其报警媒介和route路由由
alertmanager插件实现
scrape_configs:采集配置。配置数据源,包含分组job_name以及具体target。又分为静态配置和服务发现
remote_write:用于远程存储写配置
remote_read:用于远程读配置第四步:启动容器 1 2 3 4 5 6 7 8 9 10 11 docker run --name prometheus -d \ -p 9090:9090 \ -v /etc/localtime:/etc/localtime:ro \ -v /opt/prom/data:/prometheus/data \ -v /opt/prom/config:/prometheus/config \ -v /opt/prom/rules:/prometheus/rules \ prom/prometheus:v3.2.0 --config.file=/prometheus/config/prometheus.yml --web.enable-lifecycle
第五步:访问测试 访问{ip}:9090即可
3、安装 grafana 第一步:确保安装有docker 略过 参考安装 prometheus 过程
第二步:拉取镜像 镜像有哪些版本,可以通过查看一个docker镜像有哪些版本 查看
1 2 docker pull grafana/grafana:11.5.2
第三步:准备相关挂载目录及文件 准备目录
1 2 3 4 5 6 7 8 mkdir -p /opt/grafana/{data,plugins,config} chmod -R 777 /opt/grafana/data chmod -R 777 /opt/grafana/plugins chmod -R 777 /opt/grafana/config
准备配置文件
1 2 3 4 5 6 7 8 9 10 docker run --name grafana-tmp -d -p 3000:3000 grafana/grafana:11.5.2 docker cp grafana-tmp:/etc/grafana/grafana.ini /opt/grafana/config/grafana.ini docker stop grafana-tmp docker rm grafana-tmp
第四步:启动容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 docker run -d \ -p 3000:3000 \ --name=grafana \ -v /etc/localtime:/etc/localtime:ro \ -v /opt/grafana/data:/var/lib/grafana \ -v /opt/grafana/plugins/:/var/lib/grafana/plugins \ -v /opt/grafana/config/grafana.ini:/etc/grafana/grafana.ini \ -e "GF_SECURITY_ADMIN_PASSWORD=admin" \ -e "GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource,grafana-piechart-panel" \ grafana/grafana:11.5.2
第五步:访问测试 访问{ip}:3000即可,使用账密admin/admin进行登录即可
第六步:使用测试 1、添加数据源 选择普罗米修斯作为数据源 保存按钮在最下面
2、制作(或导入)仪表盘 grafana官网提供了很多模板,选择你喜欢的样式,直接输入Dashboard Id即可直接导入 这里列出几个本人使用的Dashboard Id 监控模版ID: 12633:Linux主机详情
此时,界面就出来了 提示:这会儿还没有数据,是因为prometheus里面本来就没有数据,后面我们只需要使用相应的exporter往prometheus录入一些监控数据(如:安装node-exporter),这里就会显示出来了
4、安装 node-exporter 安装exporter监控采集程序,采集数据进prometheus node-exporter
官方不建议通过Docekr方式部署node-exporter,因为它需要访问主机系统 node-exporter 可以采集机器(物理机、虚拟机、云主机等)的监控指标数据,能够采集到的指标包括 CPU, 内存,磁盘,网络,文件数等信息
1、安装node-exporter
1 2 3 4 5 6 7 8 9 10 https://github.com/prometheus/node_exporter/releases/download/v1.9.0/node_exporter-1.9.0.linux-amd64.tar.gz tar -xvf node_exporter-1.9.0.linux-amd64.tar.gz cd /opt/prom/node_exporter-1.9.0.linux-amd64nohup ./node_exporter --web.listen-address=":9101" &
2、访问一下,确保node-exporter已正常启动
或者直接curl 192.168.12.218:9101 进行验证也可
3、在prometheus中配置当前采集项 编辑配置文件
1 vim /opt/prom/config/prometheus.yml
增加当前采集项目
1 2 3 4 - job_name: 'node-exporter-hdp216-218' static_configs: - targets: ['192.168.12.216:9101' ,'192.168.12.217:9101' ,'192.168.12.218:9101' ]
完整配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 global: scrape_interval: 45s evaluation_interval: 45s rule_files: - /prometheus/rules/*.rules scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090' ] - job_name: 'node-exporter-hdp216-218' static_configs: - targets: ['192.168.12.216:9101' ,'192.168.12.217:9101' ,'192.168.12.218:9101' ]
4、使得最新的prometheus配置生效
你可以重启prometheus或者使用热加载使新配置生效,这里我们使用热加载的方式
1 2 3 curl -X POST http://192.168.12.218:9090/-/reload
注:若你触发热加载后,过个一会儿还没看到监控的变化, 那么你可以使用docker logs {prometheus容器}查看prometheus日志,看到底是否触发了热加载
1 2 docker logs --tail=1000 -f ./prometheus
5、验证一下
此时,我们再在grafana上看监控面板,就会发现有数据了
5、安装 alertmanager 安装alertmanager, 集成进 prometheus
第一步:确保安装有docker 略过 参考安装 prometheus 过程
第二步:拉取镜像 镜像有哪些版本,可以通过查看一个docker镜像有哪些版本查看
1 2 docker pull prom/alertmanager:v0.28.0
第三步:准备相关挂载目录及文件 准备目录
1 2 3 4 5 6 mkdir -p /opt/alertmanager/{config,template} chmod -R 777 /opt/alertmanager/config chmod -R 777 /opt/alertmanager/template
准备配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 cat > /opt/alertmanager/config/alertmanager.yml << \EOF global: resolve_timeout: 5m smtp_from: 'yichao0803@163.com' smtp_smarthost: 'smtp.163.com' smtp_auth_username: 'yichao0803@163.com' smtp_auth_password: '你的授权码' smtp_require_tls: false smtp_hello: '163.com' templates: - '/etc/alertmanager/template/email.tmpl' route: group_by: ['alertname' ] group_wait: 5s group_interval: 5m repeat_interval: 5m receiver: 'justrydeng163email' routes: - receiver: justrydeng163email match_re: alarmClassify: normal - receiver: justrydengQQemail match_re: alarmClassify: special receivers: - name: 'justrydeng163email' email_configs: - to: '13548417409@163.com' send_resolved: true headers: {Subject: "alertmanager报警邮件" } - name: 'justrydengQQemail' email_configs: - to: '1249823187@qq.com' send_resolved: true headers: {Subject: "alertmanager报警邮件" } inhibit_rules: - source_match: severity: 'critical' target_match: severity: 'warning' equal: ['alertname' , 'dev' , 'instance' ] EOF cat /opt/alertmanager/config/alertmanager.yml
准备预警内容模板文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 cat > /opt/alertmanager/template/email.tmpl << \EOF {{ define "email.html" }} <table border="1" > <tr> <td>报警项</td> <td>实例</td> <td>报警阀值</td> <td>开始时间</td> <td>告警信息</td> </tr> {{ range $i , $alert := .Alerts }} <tr> <td>{{ index $alert .Labels "alertname" }}</td> <td>{{ index $alert .Labels "instance" }}</td> <td>{{ index $alert .Annotations "value" }}</td> <td>{{ $alert .StartsAt }}</td> <td>{{ index $alert .Annotations "description" }}</td> </tr> {{ end }} </table> {{ end }} EOF cat /opt/alertmanager/template/email.tmpl
提示:模板文件中,占位符取值,取的是prometheus的rules文件中对应的值,你可以先写好prometheus的规则文件后,再来编写模板文件
第四步:启动容器 1 2 3 4 5 6 7 docker run -d --name=alertmanager \ -p 9093:9093 \ -v /etc/localtime:/etc/localtime:ro \ -v /opt/alertmanager/config/alertmanager.yml:/etc/alertmanager/alertmanager.yml \ -v /opt/alertmanager/template:/etc/alertmanager/template \ prom/alertmanager:v0.28.0
第五步:确保alertmanager正常启动 1 2 3 4 docker ps | grep alertmanager docker logs --tail=50 alertmanager
6、集成进prometheus 第一步:启用alertmanager 编辑配置文件
1 vim /opt/prom/config/prometheus.yml
启用alertmanager
1 2 3 4 5 6 7 alerting: alertmanagers: - static_configs: - targets: - 192.168 .12 .218 :9093
第二步:增加prometheus预警规则 提示:prometheus的rules机制,即便不集成alertmanager也是可以用的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 cat > /opt/prom/rules/os.rules << \EOF groups: - name: os rules: - alert: instance不可用(宕机或忙)告警 expr: up == 0 for : 1m labels: alarmClassify: normal annotations: summary: "监控程序{{ $labels .job }}所监控机器不可用" description: "监控程序 {{ $labels .job }}(监控程序地址为{{ $labels .instance }}) down机超过1分钟了" - alert: CPU告警 expr: 100-(avg(irate(node_cpu_seconds_total{mode="idle" }[5m])) by(instance)* 100) > 90 for : 5m labels: alarmClassify: normal annotations: summary: "CPU告警:CPU使用大于90%(目前使用:{{$value }}%)" description: "CPU告警:监控程序{{$labels .instance}}所监控机器的CPU使用大于90%(目前使用:{{$value }}%). 已经持续5分钟了" - alert: 内存告警 expr: 100 - ((node_memory_MemAvailable_bytes * 100) / node_memory_MemTotal_bytes) > 90 for : 30m labels: alarmClassify: normal annotations: summary: "内存告警:内存使用大于80%(目前使用:{{$value }}%)" description: "内存告警:监控程序{{$labels .instance}}所监控机器的内存使用大于80%(目前使用:{{$value }}%)" - alert: 磁盘分区使用率报警 expr: 100 - ((node_filesystem_avail_bytes{fstype=~"rootfs|xfs" ,mountpoint=~"/|/etc/hosts" } * 100) / node_filesystem_size_bytes{fstype=~"rootfs|xfs" ,mountpoint=~"/|/etc/hosts" }) > 80 for : 1m labels: alarmClassify: normal annotations: summary: "磁盘分区告警:{{$labels .mountpoint}} 磁盘分区使用大于80%(目前使用:{{$value }}%)" description: "磁盘分区告警:监控程序{{$labels .instance}}所监控机器的磁盘分区使用量大于80%(目前使用:{{$value }}%). 其它信息:device:{{$labels .device}}, mount:{{$labels .mountpoint}} " - alert: 挂载磁盘分区使用率报警 expr: 100 - ((node_filesystem_avail_bytes{mountpoint=~"/rootfs/newDisk|/backup" } * 100) / node_filesystem_size_bytes{mountpoint=~"/rootfs/newDisk|/backup" }) > 80 for : 1m labels: alarmClassify: normal annotations: summary: "挂载磁盘分区告警:{{$labels .mountpoint}} 挂载磁盘分区使用大于80%(目前使用:{{$value }}%)" description: "挂载磁盘分区告警:监控程序{{$labels .instance}}所监控机器的挂载磁盘分区使用量大于80%(目前使用:{{$value }}%). 其它信息:device:{{$labels .device}}, mount:{{$labels .mountpoint}} " - alert: IO性能 expr: ((irate(node_disk_io_time_seconds_total[30m]))* 100) > 95 for : 1m labels: alarmClassify: normal annotations: summary: "{{$labels .mountpoint}} 流入磁盘IO使用率过高" description: "监控程序{{$labels .instance}}所监控机器的{{$labels .mountpoint }}流入磁盘IO大于95%(目前使用:({{$value }}))" - alert: 网络(入) expr: ((sum(rate (node_network_receive_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*' }[5m])) by (instance)) / 100) > 10240 for : 5m labels: alarmClassify: normal annotations: summary: "{{$labels .mountpoint}} 流入网络带宽过高" description: "监控程序{{$labels .instance}}所监控机器的 {{$labels .mountpoint }} 流入网络带宽持续5分钟高于10Mb. RX带宽使用率{{$value }}" - alert: 网络(出) expr: ((sum(rate (node_network_transmit_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*' }[5m])) by (instance)) / 100) > 10240 for : 5m labels: alarmClassify: normal annotations: summary: "{{$labels .mountpoint}} 流出网络带宽过高" description: "监控程序{{$labels .instance}}所监控机器的 {{$labels .mountpoint }} 流出网络带宽持续5分钟高于10Mb. RX带宽使用率{{$value }}" EOF cat /opt/prom/rules/os.rules
一条告警规则主要由以下几部分组成:
alert:告警规则的名称
expr:基于PromQL表达式告警触发条件,用于计算是否有时间序列满足该条件
for:评估等待时间,可选参数。用于表示只有当触发条件持续一段时间后才发送告警。在等待期间新产生告警的状态为pending
labels:自定义标签,允许用户指定要附加到告警上的一组附加标签(注:如果自定义的标签名与prometheus.yml下内置的或配置的标签名一样,则会以这里设置的标签为主) 注:labels下标签 = prometheus.yml下设置的标签(scrape_configs.job_name[].static_configs.labels[ ]) + rule文件中用户设置的标签(groups.rules.alert[].labels[ ]) 注:labels下默认有这些标签
alertname:告警规则的名称(即:alert指定的名称)
device:机器设备
fstype:文件系统类型
mountpoint:挂载点
job:采集任务名。(即:当前预警所属采集任务名,假设prometheus.yml如下所示,采集项aliyun-node预警了,那么这里对应的job值为:xxx)
instance:采集对象。(即:当前预警所属采集项地址,假设prometheus.yml如下所示,采集项aliyun-node预警了,那么这里对应的instance值为:47.105.39.189:9100)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 global: 。。。省略 alerting: 。。。省略 rule_files: 。。。省略 scrape_configs: - job_name: 'xxx' static_configs: - targets: ['47.105.39.189:9100' ] labels: env: prod name: justrydeng instance: xxx-instance group: 'ds'
annotations:用于指定一组附加信息,比如用于描述告警详细信息的文字等,annotations的内容在告警产生时会一同作为参数发送到Alertmanager 占位符,用于取值xxx对应的值
如:,取当前规则文件下,instance标签的值
如:在annotations中,使用取触发当前预警的预警值 检查预警规则文件是否正确1 2 3 4 5 6 docker exec -it prometheus /bin/sh promtool check rules /prometheus/rules/os.rules
第三步:使得最新的prometheus配置生效 因为这里启用了alertmanager,为保险起见,本人这里选择重启prometheus(而不是使用prometheus的热加载)来使生效
1 2 3 4 docker restart prometheus docker logs --tail=50 prometheus
第四步:验证预警生效 访问prometheus,查看预警规则是否有了
预警状态说明:
Inactive:未触发预警
Pending:满足预警规则里面的预警表达式expr了,但是持续时间不满足预警规则里面的for,尚未发送预警信息
Firing:触发预警且已发送预警信息
查看邮箱,发现收到了预警消息 注:因为本人后来优化了上面的rule规则的配置内容,所以这里email里面的截图和上面的配置有点出入
7、常用命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 curl -X POST http://192.168.12.218:9090/-/reload docker exec -it prometheus /bin/sh promtool check rules /prometheus/rules/os.rules docker logs --tail=1000 -f ./prometheus
8、Web 地址 1 2 3 4 5 6 7 http://192.168.12.218:9090/query http://192.168.12.218:3000 admin/123abcABC
9、问题记录 遗留问题
1 2 3 告警内容的连接信息不正确 192.168.12.218 alertmanager 192.168.12.218 prometheus
问题1:Docker compose mysql_exporter start error
详细信息日志:
1 2 time=2025-02-20T02:58:58.997Z level=ERROR source =config.go:141 msg="failed to validate config" section=client err="no user specified in section or parent" time=2025-02-20T02:58:58.997Z level=INFO source =mysqld_exporter.go:244 msg="Error parsing host config" file=.my.cnf err="no configuration found"
mysqld-exporter 文件配置信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 version: '3' networks: monitor: driver: bridge services: mysql_xporter: image: prom/mysqld-exporter:v0.16.0 container_name: mysql-exporter hostname: mysql-exporter restart: always ports: - "9104:9104" environment: DATA_SOURCE_NAME: 'exporter:123456_abc@(192.168.12.174:3306)/' networks: - monitor
调整后即可 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 version: '3' networks: monitor: driver: bridge services: mysql_xporter: image: prom/mysqld-exporter:v0.16.0 container_name: mysql-exporter hostname: mysql-exporter restart: always ports: - "9104:9104" command: - "--mysqld.username=exporter:123456_abc" - "--mysqld.address=192.168.12.174:3306" networks: - monitor
重新生成doker 容器1 2 3 4 5 6 7 docker-compose -f ./docker-compose.yml up -d time=2025-02-20T03:04:40.454Z level=INFO source =mysqld_exporter.go:252 msg="Scraper enabled" scraper=info_schema.query_response_time time=2025-02-20T03:04:40.455Z level=INFO source =tls_config.go:347 msg="Listening on" address=[::]:9104 time=2025-02-20T03:04:40.455Z level=INFO source =tls_config.go:350 msg="TLS is disabled." http2=false address=[::]:9104
问题2:AlertManager 中国移动 193 邮箱 邮件发送失败的问题 establish TLS connection to server: EOF 中国移动 193 邮箱,能够正常发送邮件配置
1 2 3 4 5 6 7 8 9 10 11 12 13 global: resolve_timeout: 5m smtp_from: '13520642397@139.com' smtp_smarthost: 'smtp.139.com:25' smtp_auth_username: '13520642397@139.com' smtp_auth_password: '授权码' smtp_require_tls: false smtp_hello: '139.com'
附详细调试过程如下:异常1:establish TLS connection to server: EOF alertManager 的 193 邮箱,配置如下,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 global: resolve_timeout: 5m smtp_from: '135****2397@139.com' smtp_smarthost: 'smtp.139.com:465' smtp_auth_username: '135****2397@139.com' smtp_auth_secret: '授权码' smtp_require_tls: true smtp_hello: '139.com'
告警邮件未发送,查看 alertManager 的异常信息如下:
1 2 3 4 5 6 `docker logs --tail=200 -f alertmanager ` ... ... time=2025-02-20T12:04:21.135Z level=WARN source =notify.go:866 msg="Notify attempt failed, will retry later" component=dispatcher receiver=justrydengKeendataMail integration=email[0] aggrGroup="{}/{alarmClassify=~\"^(?:normal)$\"}:{alertname=\"网络(出)\"}" attempts=1 err="establish TLS connection to server: EOF" time=2025-02-20T12:09:20.981Z level=ERROR source =dispatch.go:360 msg="Notify for alerts failed" component=dispatcher num_alerts=1 err="justrydengKeendataMail/email[0]: notify retry canceled after 18 attempts: establish TLS connection to server: EOF"
根据提示信息 TLS 问题,关闭 TLS 配置,调整配置为
1 2 smtp_require_tls: false
重启 alertManger 容器 ,docker restart alertmanager; 再次测试,发送告警邮件,异常信息发生变化。异常2: missing password for LOGIN auth mechanism; missing password for PLAIN auth mechanism 详细异常信息如下
1 time=2025-02-20T12:16:51.246Z level=WARN source =notify.go:866 msg="Notify attempt failed, will retry later" component=dispatcher receiver=justrydengKeendataMail integration=email[0] aggrGroup="{}/{alarmClassify=~\"^(?:normal)$\"}:{alertname=\"网络(出)\"}" attempts=1 err="find auth mechanism: missing password for LOGIN auth mechanism; missing password for PLAIN auth mechanism"
调整 alertManager 的配置
1 2 3 smtp_auth_password: '授权码'
可以正常发送邮件,完整配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 global: resolve_timeout: 5m smtp_from: '13520642397@139.com' smtp_smarthost: 'smtp.139.com:25' smtp_auth_username: '13520642397@139.com' smtp_auth_password: '授权码' smtp_require_tls: false smtp_hello: '139.com'
10、相关资料
docker安装prometheus+grafana安装详细教程
AlertManager简介与告警模板
本文已被收录进*《程序员成长笔记》* ,笔者JustryDeng
docker-compose 搭建 Prometheus+Grafana监控系统
Docker compose mysql_exporter starterror
Node Exporter Dashboard EN 20201010-StarsL.cn
Prometheus之Alertmanager钉钉报警配置
Alertmanager配置钉钉+邮件同时告警