Prometheus+Grafana+K8S
Prometheus+Grafana+K8S
作者 |
刘畅 |
时间 |
2021-07-06 |
实验环境: Centos7.5
主机名 |
IP |
软件 |
controlnode |
172.16.1.120 |
docker、prometheus、grafana、ansiable、consul、alertmanager、prometheus-webhook-dingtalk |
slavenode1 |
172.16.1.121 |
node-exporter、mysql-exporter、docker、mysql、cadvisor |
slavenode2 |
172.16.1.122 |
node-exporter |
k8s-admin |
172.16.1.70 |
k8s主节点 |
k8s-node1 |
172.16.1.71 |
k8s从节点1 |
k8s-node2 |
172.16.1.72 |
k8s从节点2 |
目录
6.2 配置Prometheus与Alertmanager通信41
1 Prometheus的基本使用
1.1 Prometheus介绍
Prometheus(普罗米修斯)是一个最初在SoundCloud上构建的监控系统。自2012年成为社区开源项目,拥有非常活跃的开发人员和用户社区。为强调开源及独立维护,Prometheus于2016年加入云原生云计算基金会(CNCF),成为继Kubernetes之后的第二个托管项目。
Prometheus官方网站:https://prometheus.io
GitHub项目地址:https://github.com/prometheus
Prometheus 特点:
1) 多维数据模型: 由度量名称和键值对标识的时间序列数据
2) PromQL: 一种灵活的查询语言,可以利用多维数据完成复杂的查询
3) 不依赖分布式存储,单个服务器节点可直接工作
4) 基于HTTP的pull方式采集时间序列数据
5) 推送时间序列数据通过PushGateway组件支持
6) 通过服务发现或静态配置发现目标
7) 多种图形模式及仪表盘支持(grafana)
1.2 Prometheus组件与架构
1) Prometheus Server: 收集指标和存储时间序列数据,并提供查询接口
2) ClientLibrary: 客户端库
3) Push Gateway: 短期存储指标数据。主要用于临时性的任务
4) Exporters: 采集已有的第三方服务监控指标并暴露metrics
5) Alertmanager: 告警
6) Web UI: 简单的Web控制台
1.3 Prometheus部署
在172.16.1.120节点上操作
1 二进制部署
官方文档: https://prometheus.io/docs/prometheus/latest/getting_started/
(1) 下载二进制包
下载地址: https://github.com/prometheus/prometheus/releases/download/v2.28.1/prometheus-2.28.1.linux-amd64.tar.gz
(2) 部署
# tar -xzf prometheus-2.28.1.linux-amd64.tar.gz
# mv prometheus-2.28.1.linux-amd64 /usr/local/prometheus
(3) 加入systemd管理
# vim /usr/lib/systemd/system/prometheus.service
[Unit]
Description=prometheus
[Service]
ExecStart=/usr/local/prometheus/prometheus --config.file=/usr/local/prometheus/prometheus.yml --storage.tsdb.path=/usr/local/prometheus/data
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl start prometheus
# systemctl enable prometheus
(4) 访问
http://172.16.1.120:9090/
2 docker 部署
官方文档: https://prometheus.io/docs/prometheus/latest/installation/
(1) 部署
1) 将二进制安装包中的prometheus.yml配置文件上传到/opt/prometheus/config目录下
# mkdir -p /opt/prometheus/config
# cp -a /usr/local/prometheus/prometheus.yml /opt/prometheus/config/
2) 授权prometheus TSDB存储目录
# mkdir -p /opt/prometheus/data && chown -R 65534.64434 /opt/prometheus/data
3) 启动
# docker run -d \
-p 9090:9090 \
--restart=always \
--name=prometheus \
-v /opt/prometheus/config:/etc/prometheus \
-v /opt/prometheus/data:/prometheus \
prom/prometheus
(2) 访问
http://172.16.1.120:9090
1.4 Prometheus配置文件
参考文档: https://prometheus.io/docs/prometheus/latest/configuration/configuration/
1 prometheus命令常用参数
# /usr/local/prometheus/prometheus --help
1) --config.file=prometheus.yml# 指定配置文件
2) --web.listen-address=0.0.0.0:9090# 监听地址和端口
3) --log.level=info # 日志级别
4) --alertmanager.timeout=10s # 报警组件的超时时间
5) --storage.tsdb.path=./data/ # 数据目录,默认在当前目录的data目录下
6) --storage.tsdb.retention.time=15d # 数据保存时间,默认15天
2 prometheus.yml默认配置
# cat /usr/local/prometheus/prometheus.yml
3 prometheus参数说明
(1) global: 全局配置
scrape_interval: 15s # 采集数据时间间隔,默认1分钟
evaluation_interval: 15s # 评估告警规则时间间隔,默认1分钟
scrape_timeout: 10s # 采集数据超时时间,默认10秒
(2) rule_files: 告警规则
(3) scrape_configs: # 配置被监控端,称为target,每个target用job_name分组管理,又分为静态配置和服务发现。
(4) alerting:告警配置
(5) remote_write: remote_read: # 从远程数据库读写
4 prometheus被监控项配置说明
scrape_configs:
- job_name: 'prometheus'
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ['localhost:9090']
targets(目标) # 被监控端
Instances(实例)# 每个被监控端称为实例
job(作业)# 具有相同目标的实例集合称为作业,也可以当作组
5 监控指标数据模型
1) Prometheus将所有数据存储为时间序列;
2) 具有相同度量名称以及标签属于同一个指标;
3) 每个时间序列都由度量标准名称和一组键值对(称为标签)唯一标识,通过标签查询指定指标。
4) 指标格式: <metric name>{<label name>=<label value>,...}
2 Prometheus监控案例
2.1 如何监控服务
如果要想监控服务,前提是能获取被监控端指标数据,并且这个数据格式必须遵循Prometheus数据模型,这样才能识别和采集,一般使用exporter提供监控指标数据。
exporter列表: https://prometheus.io/docs/instrumenting/exporters
2.2 Grafana部署
在172.16.1.120节点上操作
1 Grafana介绍
Grafana是一个开源的度量分析和可视化系统。
Grafana只用于展示数据,数据源需要你根据提供数据的服务选择。
2 二进制部署
官方文档: https://grafana.com/grafana/download
(1) 下载二进制文件
https://dl.grafana.com/oss/release/grafana-7.5.9.linux-amd64.tar.gz
(2) 部署
# tar -zxf grafana-7.5.9.linux-amd64.tar.gz
# mv grafana-7.5.9 /usr/local/grafana
(3) 将grafana加入systemd管理
# vim /usr/lib/systemd/system/grafana.service
[Unit]
Description=grafana
[Service]
ExecStart=/usr/local/grafana/bin/grafana-server -homepath=/usr/local/grafana
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl start prometheus
# systemctl enable prometheus
(4) 访问
http://172.16.1.120:3000/
用户名/密码: admin/admin,第一次需要重置密码。
3 docker部署
官方文档: https://grafana.com/docs/grafana/latest/installation/docker/
(1) 部署
1) 创建grafana本地存储目录并授权
# mkdir -p /opt/grafana/
# chown -R 472.472 /opt/grafana/
2) 启动
# docker run -d \
--name grafana \
-p 3000:3000 \
-v /opt/grafana:/var/lib/grafana \
--restart=always \
grafana/grafana:7.5.9
(2) 访问
4 连接prometheus
2.3 监控Linux服务器
在172.16.1.121、122节点上操作
1 说明
node_exporter用于监控Linux系统的指标采集器。
常用指标CPU、内存、硬盘、网络流量、文件描述符、系统负载、系统服务。
数据接口: http://IP:9100
使用文档: https://prometheus.io/docs/guides/node-exporter/
GitHub: https://github.com/prometheus/node_exporter
2 下载node-exporter
https://github.com/prometheus/node_exporter/releases/download/v1.1.2/node_exporter-1.1.2.linux-amd64.tar.gz
3 部署
# tar -xzf node_exporter-1.1.2.linux-amd64.tar.gz
# mv node_exporter-1.1.2.linux-amd64/ /usr/local/node_exporter/
4 将node_exporter加入systemd管理
(1) 启用node_exporter的HTTP认证
1) 生成加密密码
# yum install httpd-tools -y
# htpasswd -nBC 12 '' | tr -d ':\n'
New password: 123456
Re-type new password: 123456
$2y$12$k/dJzjEoHfhgOWNr/3UsY.iKtsdiE3uhXjGu4fVTzefPTkYOOH.Ka
2) 配置认证文件
# vim /usr/local/node_exporter/config.yml
basic_auth_users:
prometheus: $2y$12$k/dJzjEoHfhgOWNr/3UsY.iKtsdiE3uhXjGu4fVTzefPTkYOOH.Ka
(2) 启动服务
# vim /usr/lib/systemd/system/node_exporter.service
[Unit]
Description=node_exporter
[Service]
ExecStart=/usr/local/node_exporter/node_exporter --web.config=/usr/local/node_exporter/config.yml
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl start node_exporter
# systemctl enable node_exporter
(3) 访问node_exporter的metric需要密码验证
http://172.16.1.121:9100/metrics
5 在prometheus.yml文件中添加被监控端
在172.16.1.120节点上操作
(1) 添加配置
# vim /usr/local/prometheus/prometheus.yml
……
(2) 验证配置是否正确
# /usr/local/prometheus/promtool check config /usr/local/prometheus/prometheus.yml
Checking /usr/local/prometheus/prometheus.yml
SUCCESS: 0 rule files found
(3) 重启prometheus
# systemctl restart prometheus.service
6 在prometheus ui界面查看target
7 使用grafana展示node_exporter数据指标
仪表盘ID: 9276
2.4 监控systemd服务运行状态
在172.16.1.121、122节点上操作
1 将监控加入到node_exporter.service中
# vim /usr/lib/systemd/system/node_exporter.service
[Unit]
Description=node_exporter
[Service]
ExecStart=/usr/local/node_exporter/node_exporter --web.config=/usr/local/node_exporter/config.yml --collector.systemd --collector.systemd.unit-include=(docker|sshd|nginx).service
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl restart node_exporter.service
2 收集数据
2.5 监控docker服务
1 部署cadvisor
在172.16.1.121节点上操作
(1) 说明
cAdvisor(Container Advisor): 用于收集正在运行的容器资源使用和性能信息。
项目地址: https://github.com/google/cadvisor
(2) 部署
# docker run -d \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:ro \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--volume=/dev/disk/:/dev/disk:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
--restart=always \
google/cadvisor:latest
2 加入到prometheus.yml配置文件
在172.16.1.120节点上操作
(1) 修改配置
# vim /usr/local/prometheus/prometheus.yml
(2) 重启prometheus
# /usr/local/prometheus/promtool check config /usr/local/prometheus/prometheus.yml
# systemctl restart prometheus.service
(3) 在prometheus UI上查看注册的docker监控实例
3 添加docker监控图表
(1) 仪表盘模板ID: 193
(2) 修改模板变量,实现只对docker实例进行监控
变量:
label_values(up,instance)
.*8080
(3) 在图表中添加变量
所有图表按如下实例进行操作
图表:
count(container_last_seen{image!="",instance="$Node"})
(4 查看仪表盘
2.6 监控mysql服务
在172.16.1.121节点上操作
1 部署mysql
# docker run -d --name db --restart=always -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
# docker exec -it db bash
root@4afdf5d50e76:/# mysql -uroot -p123456
mysql> grant PROCESS, REPLICATION CLIENT, SELECT ON *.* to 'exporter'@'%' identified by '123456';
mysql> exit
root@4afdf5d50e76:/# exit
2 部署mysqld_exporter
(1) 说明
mysql_exporter用于收集MySQL性能信息,监听端口是9104。
项目地址: https://github.com/prometheus/mysqld_exporter
(2) 下载包
https://github.com/prometheus/mysqld_exporter/releases/download/v0.13.0/mysqld_exporter-0.13.0.linux-amd64.tar.gz
(3) 部署
# tar -xzf mysqld_exporter-0.13.0.linux-amd64.tar.gz
# mv mysqld_exporter-0.13.0.linux-amd64/ /usr/local/mysqld_exporter/
# vim /usr/lib/systemd/system/mysqld_exporter.service
[Unit]
Description=mysqld_exporter
[Service]
ExecStart=/usr/local/mysqld_exporter/mysqld_exporter --web.config.file=/usr/local/mysqld_exporter/config.yml --config.my-cnf=/usr/local/mysqld_exporter/.my.cnf
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
# cp -a /usr/local/node_exporter/config.yml /usr/local/mysqld_exporter/
# cat /usr/local/mysqld_exporter/.my.cnf
[client]
user=exporter
password=123456
# systemctl daemon-reload
# systemctl restart mysqld_exporter.service
# systemctl enable mysqld_exporter.service
(4) 加入到prometheus.yml文件中
在172.16.1.120节点上操作
# vim /usr/local/prometheus/prometheus.yml
# /usr/local/prometheus/promtool check config /usr/local/prometheus/prometheus.yml
# systemctl restart prometheus.service
(5) 查看prometheus UI中注册的实例
3 添加mysql监控图表
(1) 仪表盘id使用7362
(2) 查看图表
3 Prometheus自动化监控
3.1 Prometheus服务发现
(1) Prometheus添加被监控端支持两种方式
1) 静态配置: 手动配置
2) 服务发现: 动态发现需要监控的Target实例
(2) 支持服务发现的来源
1) azure_sd_configs
2) consul_sd_configs
3) dns_sd_configs
4) ec2_sd_configs
5) openstack_sd_configs
6) file_sd_configs
7) gce_sd_configs
8) kubernetes_sd_configs
9) marathon_sd_configs
10) nerve_sd_configs
11) serverset_sd_configs
12) triton_sd_configs
3.2 基于文件的服务发现
在172.16.1.120节点上进行操作
1 启用基于文件的服务发现
# vim /usr/local/prometheus/prometheus.yml
# mkdir -p /usr/local/prometheus/sd_config/
# vim /usr/local/prometheus/sd_config/file_sd.yml
- targets: ['172.16.1.121:9100', '172.16.1.122:9100']
# /usr/local/prometheus/promtool check config /usr/local/prometheus/prometheus.yml
# systemctl restart prometheus.service
2 在prometheus UI上查看注册的实例
3.3 基于Consul的服务发现
1 Consul说明
Consul是一个分布式的服务发现和键/值存储系统。
2 部署Consul
在172.16.1.120节点上操作
# docker run -d --name consul -p 8500:8500 --restart=always consul
# 访问consul的UI
http://172.16.1.120:8500/
3 向Consul注册服务
在172.16.1.120节点上操作
(1) 注册172.16.1.121主机
curl -X PUT -d '{"id": "172.16.1.121","name": "Linux-Server","address": "172.16.1.121","port": 9100,"tags": ["slavenode1"],"checks": [{"http": "http://172.16.1.121:9100","interval": "5s"}]}' http://172.16.1.120:8500/v1/agent/service/register
(2) 注册172.16.1.122主机
curl -X PUT -d '{"id": "172.16.1.122","name": "Linux-Server","address": "172.16.1.122","port": 9100,"tags": ["slavenode2"],"checks": [{"http": "http://172.16.1.122:9100","interval": "5s"}]}' http://172.16.1.120:8500/v1/agent/service/register
(3) 参数说明
id # 自定义被监控实例id,可以理解为prometheus中的instance,唯一
name # 定义的监控组,可以理解为prometheus中的job
tags # 自定义标签,可以根据项目名设置
address# 被监控实例的ip
port # 被监控实例的端口号
checks# 检查被监控实例的状态
http://172.16.1.120:8500/v1/agent/service/register # 注册中心访问地址
(4) 在consul UI中查看注册上的被监控实例信息
说明: 由于node_exporter设置了http验证,所以状态检查不通过,但是node_exporter的ip及端口号已经注册上来了,所以不影响prometheus读取数据。
补充: 在consul中取消注册主机的方法
Usage:
curl --request PUT http://<Consul_IP>:8500/v1/agent/service/deregister/<instance_id>
例:
# curl --request PUT http://172.16.1.120:8500/v1/agent/service/deregister/172.16.1.121
# 在consul中取消已经注册上的被监控实例,则prometheus中相应监控的实例也会去除。
4 修改prometheus.yml文件
在172.16.1.120节点上操作
# vim /usr/local/prometheus/prometheus.yml
# systemctl restart prometheus.service
5 在prometheus UI中查看目标实例
3.4 Ansible+Consul实现主机自动监控
在172.16.1.120节点上操作
# pwd
/root/ansible
1 安装ansible
# yum install ansible -y
# 取消ansible主机验证
# vim /etc/ansible/ansible.cfg
host_key_checking = False
2 ansible配置
# tree /root/ansible
/root/ansible
├── config.yml# node_exporter的http验证配置
├── consul-register.sh# consul注册node_exporter脚本
├── hosts# ansible主机清单
├── node_exporter-1.1.2.linux-amd64.tar.gz# node_exporter压缩包
├── node_exporter.service# node_exporter 启动服务
└── playbook.yaml# ansible playbook文件
0 directories, 6 files
(1) # cat config.yml
basic_auth_users:
prometheus: $2y$12$k/dJzjEoHfhgOWNr/3UsY.iKtsdiE3uhXjGu4fVTzefPTkYOOH.Ka
(2) cat consul-register.sh
#!/bin/bash
instance_id=$1
service_name=$2
ip=$3
port=$4
consul_server=$5
curl -X PUT -d '{"id": "'"$instance_id"'","name": "'"$service_name"'","address": "'"$ip"'","port": '"$port"',"tags": ["'"$service_name"'"],"checks": [{"http": "http://'"$ip"':'"$port"'","interval": "5s"}]}' ${consul_server}
(3) cat hosts
[LinuxServers]
172.16.1.121 ansible_ssh_user=root ansible_ssh_pass='123456' name=slavenode1
172.16.1.122 ansible_ssh_user=root ansible_ssh_pass='123456' name=slavenode2
(4) cat node_exporter.service
[Unit]
Description=node_exporter
[Service]
ExecStart=/usr/local/node_exporter/node_exporter --web.config=/usr/local/node_exporter/config.yml --collector.systemd --collector.systemd.unit-include=(docker|sshd|nginx).service
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
(5) cat playbook.yaml
- hosts: LinuxServers
gather_facts: no
vars:
server_port: 9100
consul_server: http://172.16.1.120:8500/v1/agent/service/register
tasks:
- name: 推送二进制文件
unarchive: src=node_exporter-1.1.2.linux-amd64.tar.gz dest=/usr/local
- name: 重命名
shell: |
cd /usr/local/
if [ ! -d "node_exporter" ];then
mv node_exporter-1.1.2.linux-amd64/ node_exporter/
fi
- name: 推送配置文件
copy: src=config.yml dest=/usr/local/node_exporter
notify:
- restart node_exporter
- name: 拷贝systemd文件
copy: src=node_exporter.service dest=/usr/lib/systemd/system
notify:
- restart node_exporter
- name: 启动服务
systemd: name=node_exporter state=started enabled=yes daemon_reload=yes
- name: 推送注册脚本
copy: src=consul-register.sh dest=/usr/local/bin/
- name: 注册当前节点
# 服务名 实例名 IP 端口
shell: /bin/bash /usr/local/bin/consul-register.sh {{ name }} {{ group_names[0] }} {{ inventory_hostname }} {{ server_port }} {{ consul_server }}
handlers:
- name: restart node_exporter
service: name=node_exporter state=restarted
3 执行ansible
# ansible-playbook -i hosts playbook.yaml
4 在consul UI中查看注册上来的主机
5 配置prometheus.yml
# vim /usr/local/prometheus/prometheus.yml
# systemctl restart prometheus.service
6 在prometheus UI中查看目标实例
3.5 监控kubernetes
(1) 监控指标
Kubernetes本身监控: Node资源利用率、Node数量、Pods数量(Node)、资源对象状态
Pod监控: Pod数量(项目)、容器资源利用率、应用程序
监控指标 |
具体实现 |
举例 |
Node资源利用率 |
node-exporter |
节点CPU,内存利用率 |
Pod资源利用率 |
cAdvisor |
容器CPU,内存利用率 |
K8S资源对象状态 |
kube-state-metrics |
Pod、Deployment、Service |
(2) 监控架构
服务发现类型 |
描述 |
node |
发现集群中的节点,默认地址为kubelete的http端口 |
service |
发现所有Service及端口为目标 |
pod |
发现所有pod为目标 |
endpoints |
从Service列表中的Endpoint发现Pod为目标 |
ingress |
发现Ingress路径为目标 |
官方文档:
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
2 在k8s集群上部署rbac授权及kube-state-metrics
(1) k8s RBAC授权
# kubectl apply -f rbac.yaml
(2) 获取Token并保存到文件
# kubectl get ServiceAccount prometheus -n kube-system -o yaml
……
secrets:
- name: prometheus-token-55pdv
# kubectl describe secret prometheus-token-55pdv -n kube-system >token.k8s
清理上面的token文件,只保留"token:"以下的内容,并将该文件scp到172.16.1.120节点的/opt/monitor/prometheus/目录下。
[root@controlnode ~]# mkdir -p /opt/monitor/prometheus/
[root@k8s-admin k8s-prometheus]# scp -p token.k8s root@172.16.1.120:/opt/monitor/prometheus/
(3) 部署kube-state-metrics
# kubectl apply -f kube-state-metrics.yaml
3 在prometheus.yml文件中创建Job和kubeconfig_sd_configs
在172.16.1.120节点上操作
(1) 上传配置好的prometheus.yml文件到/usr/local/prometheus/目录下。
(2) 修改prometheus.yml配置文件中k8s api-server的地址为现k8s集群api-server地址。
[root@k8s-admin k8s-prometheus]# kubectl get ep
NAME ENDPOINTS AGE
kubernetes 172.16.1.70:6443 77d
(3) 打通prometheus应用所在controlnode节点和k8s-admin、k8s-nod1、k8s-node2节点的pod路由
,否则在prometheus中名为"kubernetes-service-endpoints"的job会挂掉。
[root@controlnode ~]# route add -net 10.244.0.0/16 gw 172.16.1.70 dev eth1
[root@controlnode ~]# route add -net 10.244.0.0/16 gw 172.16.1.71 dev eth1
[root@controlnode ~]# route add -net 10.244.0.0/16 gw 172.16.1.72 dev eth1
(4) 重启prometheus
# systemctl restart prometheus.service
(5) 在prometheus UI中查看注册的target instance
4 grafana导入仪表盘
在172.16.1.120节点上操作
(1) 导入K8S集群资源监控模板
(2) 导入K8S资源对象状态监控模板
4 PromQL常用语句
PromSQL文档:
https://yunlzheng.gitbook.io/prometheus-book/parti-prometheus-ji-chu/promql/prometheus-query-language
在prometheus UI上操作
PromQL(Prometheus Query Language)是Prometheus自己开发的数据查询DSL语言,语言表现力
非常丰富,支持条件查询、操作符,并且内建了大量内置函数,供我们针对监控数据的各种维度进行查询。
4.1 瞬时向量与范围向量查询
官方文档: https://prometheus.io/docs/prometheus/latest/querying/examples/
1 目标实例状态
up
2 查询指标最新样本(称为瞬时向量)
node_cpu_seconds_total
可以通过附加一组标签来进一步过滤这些时间序列:
node_cpu_seconds_total{instance="172.16.1.121:9100",job="Linux Server",mode="system"}
3 查询指标近5分钟样本(称为范围向量,时间单位为s,m,h,d,w,y)
node_cpu_seconds_total{cpu="0",instance="172.16.1.121:9100",job="Linux Server",mode="system"}[5m]
4.2 常用操作符
官方文档: https://prometheus.io/docs/prometheus/latest/querying/operators/
类型 |
操作符 |
示例 |
比较操作符 |
= 等于 != 不等于 > 大于 < 小于 >= 大于等于 <= 小于等于 |
示例1 |
算术操作符 |
+ 加法 - 减法 * 乘法 / 除法 |
示例2 |
正则匹配操作符 |
=~ 正则表达式匹配 !~ 正则表达式匹配结果取反 |
示例3 |
聚合操作符 |
sum (在维度上求和) max (在维度上求最大值) min (在维度上求最小值) avg (在维度上求平均值) count (统计样本数量) |
示例4 |
逻辑操作符 |
and 与 or 或 |
示例5 |
node_cpu_seconds_total{job="Linux Server",mode="iowait"}
node_cpu_seconds_total{job="Linux Server",mode=~"user|system"}
node_cpu_seconds_total{job="Linux Server",mode=~"user|system",cpu!="0"}
示例2
CPU使用率:
100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100)
内存使用率:
100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100
示例3
磁盘使用率:
100 - (node_filesystem_free_bytes{mountpoint="/",fstype=~"ext4|xfs"} / node_filesystem_size_bytes{mountpoint="/",fstype=~"ext4|xfs"} * 100)
示例4
所有实例CPU system使用率总和:
sum(node_cpu_seconds_total{job="Linux Server",mode="system"})
所有实例CPU system变化速率平均值:
avg(irate(node_cpu_seconds_total{job="Linux Server",mode="system"}[5m]))
统计CPU数量:
count(node_cpu_seconds_total{job="Linux Server",mode="system"})
示例5
大于10并且小于50:
prometheus_http_requests_total > 10 and prometheus_http_requests_total < 50
大于10或者小于50:
prometheus_http_requests_total > 10 or prometheus_http_requests_total < 50
4.3 常用函数
官方文档: https://prometheus.io/docs/querying/functions/
irate(): 计算指标在一定时间间隔内的变化速率。
示例:
irate(node_cpu_seconds_total{job="Linux Server",mode="system"}[5m])
5 Prometheus标签管理
在172.16.1.120节点上操作
5.1 标签的作用
Prometheus中存储的数据为时间序列,是由Metric的名字和一系列的标签(键值对)唯一标识的,
不同的标签代表不同的时间序列,即通过指定标签查询指定数据。
5.2 Metadata标签
在Prometheus所有的Target实例中,都包含一些默认的Metadata标签信息。可以通过
Prometheus UI的Targets页面中查看这些实例的Metadata标签的内容。
__address__# 当前Target实例的访问地址<host>:<port>
__metrics_path__# 采集目标服务访问地址的访问路径
__scheme__# 采集目标服务访问地址的HTTP Scheme,HTTP或者HTTPS
上面这些标签将会告诉Prometheus如何从该Target实例中获取监控数据。除了这些默认的标签
以外,我们还可以为Target添加自定义的标签。
5.3 自定义标签
1 修改prometheus.yml文件
# vim /usr/local/prometheus/prometheus.yml
2 重启prometheus
# systemctl restart prometheus.service
3 在prometheus UI中查看新增的标签
5.4 重新标记标签
1 为什么要重新标记标签
(1) 重新标记标签的目的是为了更好的标识监控指标。
(2) 在两个阶段可以重新标记
1) relabel_configs# 在采集之前
准备抓取指标数据时,可以使用relabel_configs添加一些标签、也可以只采集特定目标或过滤目标。
2) metric_relabel_configs# 在存储之前
已经抓取到指标数据时,可以使用metric_relabel_configs做最后的重新标记和过滤。
(3) 重新标记标签的一般途径
动态生成新标签、过滤采集的Target、删除不需要或者敏感标签、添加新标签
(4) action重新标记标签动作
1) replace# 默认,通过regex匹配source_label的值,使用replacement来引用表达式
匹配的分组,分组使用$1,$2...引用,标签值。
2) keep# 删除regex与连接不匹配的目标 source_labels,标签值
3) drop# 删除regex与连接匹配的目标 source_labels,标签值
4) labeldrop# 删除regex匹配的标签,标签名称
5) labelkeep# 删除regex不匹配的标签,标签名称
6) labelmap# 匹配regex所有标签名称,并将捕获的内容分组,用第一个分组内容作为
新的标签名。
2 重命名标签
(1) 修改prometheus.yml文件
# vim /usr/local/prometheus/prometheus.yml
(2) 重启prometheus
# systemctl restart prometheus.service
(3) 在prometheus UI中查看
3 过滤Target
在采集标签之前,删除采集的target
(1) 修改prometheus.yml文件
# vim /usr/local/prometheus/prometheus.yml
(2) 重启prometheus
# systemctl restart prometheus.service
(3) 在prometheus UI中查看
4 删除标签
删除不需要或者敏感的标签
在收集标签之前删除标签
(1) 修改prometheus.yml文件
# vim /usr/local/prometheus/prometheus.yml
(2) 重启prometheus
# systemctl restart prometheus.service
(3) 在prometheus UI中查看
6 Alertmanager告警
在172.16.1.120节点上操作
6.1 部署Alertmanager
官方文档: https://github.com/prometheus/alertmanager
1 安装包下载
下载地址:
https://github.com/prometheus/alertmanager/releases/download/v0.22.2/alertmanager-0.22.2.linux-amd64.tar.gz
2 将alertmanager加入到systemd
# tar -xzf alertmanager-0.22.2.linux-amd64.tar.gz
# mv alertmanager-0.22.2.linux-amd64/ /usr/local/alertmanager/
# vim /usr/lib/systemd/system/alertmanager.service
[Unit]
Description=grafana
[Service]
ExecStart=/usr/local/alertmanager/alertmanager --config.file=/usr/local/alertmanager/alertmanager.yml
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl start alertmanager.service
# systemctl enable alertmanager.service
# netstat -tunlp | grep alertmanager
6.2 配置Prometheus与Alertmanager通信
1 配置prometheus.yml
# vim /usr/local/prometheus/prometheus.yml
2 重启prometheus
# systemctl restart prometheus.service
6.3 编写告警规则
1 配置prometheus.yml
# vim /usr/local/prometheus/prometheus.yml
# mkdir -p /usr/local/prometheus/rules
2 编写rule规则
(1) 监控实例状态
# cat /usr/local/prometheus/rules/general.yml
groups:
- name: general.rules # 告警规则组名称
rules:
- alert: InstanceDown # 告警规则名称,alertname
expr: up == 0 # 基于PromQL的触发条件
for: 2m # 规则触发持续多长时间发送告警
labels: # 自定义标签
severity: critical # 告警级别,warning等
annotations: # 告警附加信息
summary: "Instance {{ $labels.instance }} 停止工作"
description: "{{ $labels.instance }}: job {{ $labels.job }} 已经停止5分钟以上."
(2) 监控cpu、内存、磁盘使用率
# cat /usr/local/prometheus/rules/node.yml
groups:
- name: node.rules
rules:
- alert: NodeFilesystemUsage
expr: 100 - (node_filesystem_free_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"} * 100) > 80
for: 2m
labels:
severity: warning
annotations:
summary: "{{$labels.instance}}: {{$labels.mountpoint }} 分区使用过高"
description: "{{$labels.instance}}: {{$labels.mountpoint }} 分区使用大于 80% (当前值: {{ $value }})"
- alert: NodeMemoryUsage
expr: 100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100 > 80
for: 2m
labels:
severity: warning
annotations:
summary: "{{$labels.instance}}: 内存使用过高"
description: "{{$labels.instance}}: 内存使用大于 80% (当前值: {{ $value }})"
- alert: NodeCPUUsage
expr: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100) > 80
for: 2m
labels:
severity: warning
annotations:
summary: "{{$labels.instance}}: CPU使用过高"
description: "{{$labels.instance}}: CPU使用大于 80% (当前值: {{ $value }})"
3 重启prometheus
# systemctl restart prometheus.service
4 在prometheus UI中查看告警规则
# 没有触发任何警告
6.4 alertmanager钉钉告警
参考文档: https://github.com/timonwong/prometheus-webhook-dingtalk
1 安装prometheus-webhook-dingtalk插件(二进制)
# wget \
https://github.com/timonwong/prometheus-webhook-dingtalk/releases/download/v1.4.0/prometheus-webhook-dingtalk-1.4.0.linux-amd64.tar.gz
# tar -xzf prometheus-webhook-dingtalk-1.4.0.linux-amd64.tar.gz
# mv prometheus-webhook-dingtalk-1.4.0.linux-amd64/ /usr/local/prometheus-webhook-dingtalk/
2 钉钉创建机器人并获取token和secret(加签)
点击钉钉右上角加号(+) >>> 选择"发起群聊" >>> 选择"项目群" >>> 填写"群名称"
>>> 点击"创建" >>> 点击"群设置" >>> 选择"智能群助手" >>> 选择"添加机器人"
>>> 选择"自定义"机器人 >>> 点击"添加" >>> 后续如下截图
加签: SEC530dfec7dcde0c8c31c98196fedf9c8c7ae767336ce3267bf8f6e94df78131bf
webhook:
https://oapi.dingtalk.com/robot/send?access_token=a9285933068d63b3612d4f3caf2da1cfc85fc7ebf09ae04ce38955f76bec597f
3 配置prometheus-webhook-dingtalk
(1) 配置config.yml
# cd /usr/local/prometheus-webhook-dingtalk/
# cp -a config.example.yml config.yml
# vim config.yml
## Request timeout
timeout: 10s
## Customizable templates path
templates:
- /usr/local/prometheus-webhook-dingtalk/template.tmpl
## Targets, previously was known as "profiles"
targets:
webhook1:
url: https://oapi.dingtalk.com/robot/send?access_token=a9285933068d63b3612d4f3caf2da1cfc85fc7ebf09ae04ce38955f76bec597f
secret: SEC530dfec7dcde0c8c31c98196fedf9c8c7ae767336ce3267bf8f6e94df78131bf
mention:
all: true
(2) 配置告警模板template.tmpl
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
{{ define "__alertmanagerURL" }}{{ .ExternalURL }}/d/9CWBz0bik/k8sji-qun-shou-ye?orgId=1 {{ end }}
{{ define "__text_alert_list" }}{{ range . }}
**Labels**
{{ range .Labels.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}
**Annotations**
{{ range .Annotations.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}
**Source:** [{{ .GeneratorURL }}]({{ .GeneratorURL }})
{{ end }}{{ end }}
{{ define "default.__text_alert_list" }}{{ range . }}
---
**告警级别:** {{ .Labels.severity | upper }}
**触发时间:** {{ dateInZone "2006.01.02 15:04:05" (.StartsAt) "Asia/Shanghai" }}
**事件信息:**
{{ range .Annotations.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}{{ end }}
{{ end }}
{{ define "default.__text_alertresolve_list" }}{{ range . }}
---
**告警级别:** {{ .Labels.severity | upper }}
**触发时间:** {{ dateInZone "2006.01.02 15:04:05" (.StartsAt) "Asia/Shanghai" }}
**结束时间:** {{ dateInZone "2006.01.02 15:04:05" (.EndsAt) "Asia/Shanghai" }}
**事件信息:**
{{ range .Annotations.SortedPairs }}> - {{ .Name }}: {{ .Value | markdown | html }}
{{ end }}{{ end }}
{{ end }}
{{/* Default */}}
{{ define "default.title" }}{{ template "__subject" . }}{{ end }}
{{ define "default.content" }}#### \[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}\] **[{{ index .GroupLabels "alertname" }}]({{ template "__alertmanagerURL" . }})**
{{ if gt (len .Alerts.Firing) 0 -}}
![警报 图标](http://wx4.sinaimg.cn/large/006APoFYly1g0ggpt1aq3j306o06o3yt.jpg)
**=====侦测到故障=====**
{{ template "default.__text_alert_list" .Alerts.Firing }}
{{- end }}
{{ if gt (len .Alerts.Resolved) 0 -}}
![警报 图标](https://i01piccdn.sogoucdn.com/2dbf8a9d48e921e7)
**=====故障已修复=====**
{{ template "default.__text_alertresolve_list" .Alerts.Resolved }}
{{- end }}
{{- end }}
{{/* Legacy */}}
{{ define "legacy.title" }}{{ template "__subject" . }}{{ end }}
{{ define "legacy.content" }}#### \[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}\] **[{{ index .GroupLabels "alertname" }}]({{ template "__alertmanagerURL" . }})**
{{ template "__text_alert_list" .Alerts.Firing }}
{{- end }}
{{/* Following names for compatibility */}}
{{ define "ding.link.title" }}{{ template "default.title" . }}{{ end }}
{{ define "ding.link.content" }}{{ template "default.content" . }}{{ end }}
补充: template.tmpl中包含了"/d/9CWBz0bik/k8sji-qun-shou-ye?orgId=1,这正是 grafana 的 url。因为 alertmanager 的 --web.external-url
(3) 将prometheus-webhook-dingtalk加入到systemd管理
# vim /usr/lib/systemd/system/prometheus-webhook-dingtalk.service
[Unit]
Description=prometheus-webhook-dingtalk-1.4.0
[Service]
ExecStart=/usr/local/prometheus-webhook-dingtalk/prometheus-webhook-dingtalk --config.file=/usr/local/prometheus-webhook-dingtalk/config.yml --web.enable-ui
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl restart prometheus-webhook-dingtalk.service
# systemctl enable prometheus-webhook-dingtalk.service
# netstat -tunlp | grep prometheus-web
(4) 访问http://172.16.1.120:8060/ui/进行模板验证
4 将钉钉接入Prometheus AlertManager WebHook
# vim /usr/local/alertmanager/alertmanager.yml
global:
resolve_timeout: 1m # 每1分钟检查一次状态是否恢复
route: # 配置路由树
group_by: ['alertname'] # 根据告警规则名进行分组
group_wait: 15s # 组告警等待时间,也就是告警产生后等待10s,如果有同组告警一起发出
group_interval: 15s # 两组告警的间隔时间
repeat_interval: 1h # 重复告警的间隔时间,减少相同告警的发送频率
receiver: 'web.hook' # 配置告警消息接受者信息
receivers:
- name: 'web.hook' # 告警接受者
webhook_configs:
- send_resolved: true # 告警被解决之后通知
url: 'http://172.16.1.120:8060/dingtalk/webhook1/send' # 钉钉告警插件地址
inhibit_rules: # 抑制规则配置,当存在与另一组匹配的警报(源)时,抑制规则将禁用与一组匹配的警报(目标)
- source_match:
severity: 'critical' # 指定告警级别
target_match:
severity: 'warning' # 指定抑制告警级别
equal: ['alertname', 'instance']
#####################
# 1 例如收到一条告警
# alertname=down level=critical instance=172.16.1.120:9100 job=Linux Server
# 2 进入抑制处理流程
# 3 判断告警带 level=critical 这个标签
# 4 抑制带有 level=warning 标签的告警
# 5 这两条规则必须满足相同的标签 alertname=down instance=172.16.1.120:9100
# 6 不发送告警
# ##################
# systemctl restart alertmanager.service
5 测试
(1) 停掉172.16.1.121实例
查看prometheus Alerts界面,发现触发了告警,告警处于PENDING状态。
(2) 等待大概4分钟左右,钉钉收到告警邮件
(3) 恢复172.16.1.121实例后,钉钉收到恢复告警邮件
6 补充: 使用源码安装
(1) 安装依赖
1) 安装Go
官方文档: https://golang.org/doc/install#install
# wget https://golang.org/dl/go1.16.6.linux-amd64.tar.gz
# rm -rf /usr/local/go && tar -C /usr/local -xzf go1.16.6.linux-amd64.tar.gz
# echo 'export PATH=/usr/local/go/bin:$PATH' >> /etc/profile
# source /etc/profile
# go version
2) 安装Nodejs
官方文档: https://github.com/nodejs/help/wiki/Installation
# wget https://nodejs.org/dist/v14.17.3/node-v14.17.3-linux-x64.tar.xz
# tar -xJf node-v14.17.3-linux-x64.tar.xz
# mv node-v14.17.3-linux-x64/ /usr/local/nodejs/
# echo 'export PATH=/usr/local/nodejs/bin:$PATH' >> /etc/profile
# source /etc/profile
# node -v
v14.17.3
# npx -v
6.14.13
# npm version
3) 安装Yarn
官方文档: https://yarnpkg.com/getting-started/install
# npm install -g yarn
# yarn -v
1.22.10
(2) 下载源码并编译
# git clone https://github.com/timonwong/prometheus-webhook-dingtalk.git
# cd prometheus-webhook-dingtalk/
# make build
(4) 配置
# mkdir -p /usr/local/prometheus-webhook-dingtalk/
# cp -a prometheus-webhook-dingtalk /usr/local/prometheus-webhook-dingtalk/
# vim /usr/local/prometheus-webhook-dingtalk/config.yml
# vim /usr/local/prometheus-webhook-dingtalk/template.tmpl
# vim /usr/lib/systemd/system/prometheus-webhook-dingtalk.service
6.5 告警触发流程
(1) 告警状态说明
Inactive# 这里什么都没有发生。
Pending# 已触发阈值,但未满足告警持续时间。
Firing# 已触发阈值且满足告警持续时间,警报发送给接受者。
(2) 告警收敛
分组(group)# 将类似性质的警报分类为单个通知
抑制(Inhibition)# 当警报发出后,停止重复发送由此警报引发的其他警报
静默(Silences)# 是一种简单的特定时间静音提醒的机制
(3) 告警流程
prometheus处理告警时间:
1) 指标采集间隔时长(scrape_interval: 15s)
2) 根据告警规则对采集指标评估的间隔时长(evaluation_interval: 15s)
3) 告警持续等待时间,在告警规则内自定义时长(for: 2m)
AlertManger处理告警时间:
1) 分组等待时长(group_wait: 15s)
2) 告警发送间隔时长(group_interval: 15s)
(4) altermanager静默设置
7 Grafana可视化展示
7.1 制作grafana导航栏
1 创建一个名为linux_dashboard的表盘
2 添加变量
(1) 添加分组变量
(2) 添加Target实例变量
3 查看添加的导航栏
7.2 自定义图标
以下图表的制作只提供参考之用,具体可以参考官网做好的模板
1 stat(单个统计)
(1) 统计cpu个数
count(node_cpu_seconds_total{instance=~"$node", mode='system'})
(2) 统计内存总量
node_memory_MemTotal_bytes{instance=~"$node"}
2 gauge(百分比,1分钟cpu使用率)
100 - (avg(irate(node_cpu_seconds_total{instance=~"$node",mode="idle"}[1m])) * 100)