1. 简介
Prometheus是一个开源监控系统,它前身是SoundCloud的警告工具包。从2012年开始,许多公司和组织开始使用Prometheus。该项目的开发人员和用户社区非常活跃,越来越多的开发人员和用户参与到该项目中。目前它是一个独立的开源项目,且不依赖与任何公司。为了强调这点和明确该项目治理结构,Prometheus在2016年继Kurberntes之后,加入了Cloud Native Computing Foundation。主要具有如下功能:
- 多维 数据模型(时序由 metric 名字和 k/v 的 labels 构成)。
- 灵活的查询语句(PromQL)。
- 无依赖存储,支持 local 和 remote 不同模型。
- 采用 http 协议,使用 pull 模式,拉取数据,简单易懂。
- 监控目标,可以采用服务发现或静态配置的方式。
- 支持多种统计数据模型,图形化友好。
2. 架构图
从这个架构图,也可以看出 Prometheus 的主要模块包含, prometheus server, exporters, pushgateway, PromQL, Alertmanager, WebUI 等。下面我就简单介绍各个组件实现的功能:
1. prometheus server: 定期从静态配置的 targets 或者服务发现(主要是DNS、consul、k8s、mesos等)的 targets 拉取数据。
2. exporters:负责向prometheus server做数据汇报的程序统。而不同的数据汇报由不同的exporters实现,比如监控主机有node-exporters,mysql有MySQL server exporter,更多请参考链接。
3. pushgateway:主要使用场景为:
Prometheus 采用 pull 模式,可能由于不在一个子网或者防火墙原因,导致 Prometheus 无法直接拉取各个 target 数据。在监控业务数据的时候,需要将不同数据汇总, 由 Prometheus 统一收集。
总结:实现类似于zabbix-proxy功能;
4. Alertmanager:实现prometheus的告警功能。
5. webui:主要通过grafana来实现webui展示。
3. 基础概念
3.1 数据模型
Prometheus 存储的是时序数据, 即按照相同时序(相同的名字和标签),以时间维度存储连续的数据的集合。时序(time series) 是由名字(Metric),以及一组 key/value 标签定义的,具有相同的名字以及标签属于相同时序。时序的名字由 ASCII 字符,数字,下划线,以及冒号组成,它必须满足正则表达式 [a-zA-Z_:][a-zA-Z0-9_:]*
, 其名字应该具有语义化,一般表示一个可以度量的指标,例如 http_requests_total
, 可以表示 http 请求的总数。
时序的标签可以使 Prometheus 的数据更加丰富,能够区分具体不同的实例,例如 http_requests_total{method="POST"}
可以表示所有 http 中的 POST 请求。标签名称由 ASCII 字符,数字,以及下划线组成, 其中 __
开头属于 Prometheus 保留,标签的值可以是任何 Unicode 字符,支持中文。
3.2 时序4种类型
Prometheus 时序数据分为 Counter, Gauge, Histogram, Summary 四种类型。
- Counter:表示收集的数据是按照某个趋势(增加/减少)一直变化的,我们往往用它记录服务请求总量,错误总数等。例如 Prometheus server 中
http_requests_total
, 表示 Prometheus 处理的 http 请求总数,我们可以使用data, 很容易得到任意区间数据的增量。 - Gauge:表示搜集的数据是一个瞬时的,与时间没有关系,可以任意变高变低,往往可以用来记录内存使用率、磁盘使用率等。
- Histogram:Histogram 由
<basename>_bucket{le="<upper inclusive bound>"}
,<basename>_bucket{le="+Inf"}
,<basename>_sum
,<basename>_count
组成,主要用于表示一段时间范围内对数据进行采样,(通常是请求持续时间或响应大小),并能够对其指定区间以及总数进行统计,通常我们用它计算分位数的直方图。 - Summary:Summary 和 Histogram 类似,由
<basename>{quantile="<φ>"}
,<basename>_sum
,<basename>_count
组成,主要用于表示一段时间内数据采样结果,(通常是请求持续时间或响应大小),它直接存储了 quantile 数据,而不是根据统计区间计算出来的。区别在于:
a. 都包含<basename>_sum
,<basename>_count。
b. Histogram 需要通过<basename>_bucket
计算 quantile, 而 Summary 直接存储了 quantile 的值。
4. prometheus 部署
使用二进制安装, 官网下载地址https://prometheus.io/download/
root@ubuntu-template:/apps# wget https://github.com/prometheus/prometheus/releases/download/v2.31.1/prometheus-2.31.1.linux-amd64.tar.gz
root@ubuntu-template:/apps# tar -zxvf prometheus-2.31.1.linux-amd64.tar.gz
prometheus-2.31.1.linux-amd64/
prometheus-2.31.1.linux-amd64/consoles/
prometheus-2.31.1.linux-amd64/consoles/index.html.example
prometheus-2.31.1.linux-amd64/consoles/node-cpu.html
prometheus-2.31.1.linux-amd64/consoles/node-disk.html
prometheus-2.31.1.linux-amd64/consoles/node-overview.html
prometheus-2.31.1.linux-amd64/consoles/node.html
prometheus-2.31.1.linux-amd64/consoles/prometheus-overview.html
prometheus-2.31.1.linux-amd64/consoles/prometheus.html
prometheus-2.31.1.linux-amd64/console_libraries/
prometheus-2.31.1.linux-amd64/console_libraries/menu.lib
prometheus-2.31.1.linux-amd64/console_libraries/prom.lib
prometheus-2.31.1.linux-amd64/prometheus.yml
prometheus-2.31.1.linux-amd64/LICENSE
prometheus-2.31.1.linux-amd64/NOTICE
prometheus-2.31.1.linux-amd64/prometheus
prometheus-2.31.1.linux-amd64/promtool
root@ubuntu-template:/apps# ln -sv prometheus-2.31.1.linux-amd64 prometheus
'prometheus' -> 'prometheus-2.31.1.linux-amd64'
4.1 配置启动脚本
root@ubuntu-template:/apps# cat /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview/
After=network.target
[Service]
Restart=on-failure
WorkingDirectory=/apps/prometheus/
ExecStart=/apps/prometheus/prometheus --config.file=/apps/prometheus/prometheus.yml
[Install]
WantedBy=muti-user.target
root@ubuntu-template:/apps# systemctl daemon-reload
4.2 启动
root@ubuntu-template:/apps/prometheus# systemctl start prometheus
# 设置开机启动
root@ubuntu-template:/apps/prometheus# systemctl enable prometheus
Created symlink /etc/systemd/system/muti-user.target.wants/prometheus.service → /etc/systemd/system/prometheus.service.
4.3 验证
5. PromQL
PromQL (Prometheus Query Language) 是 Prometheus 自己开发的数据查询 DSL 语言。
查询结果类型:
瞬时数据 (Instant vector): 包含一组时序,每个时序只有一个点,例如:http_requests_total
区间数据 (Range vector): 包含一组时序,每个时序有多个点,例如:http_requests_total[5m]
纯量数据 (Scalar): 纯量只有一个数字,没有时序,例如:count(http_requests_total)
查询条件:通过名称及标签进行查询,如http_requests_total等价于{name="http_requests_total"}
查询level="info"的event: logback_events_total{level="info"}
查询条件支持正则匹配:
http_requests_total{code!="200"} // 表示查询 code 不为 "200" 的数据
http_requests_total{code=~"2.."} // 表示查询 code 为 "2xx" 的数据
http_requests_total{code!~"2.."} // 表示查询 code 不为 "2xx" 的数据
内置函数:
如将浮点数转换为整数:
floor(avg(http_requests_total{code="200"}))
ceil(avg(http_requests_total{code="200"}))
查看每秒数据 :
rate(http_requests_total[5m])
基本查询:
1.查询当前所有数据
logback_events_total
2.模糊查询: level="inxx"
logback_events_total{level=~"in.."}
logback_events_total{level=~"in.*"}
3.比较查询: value>0
logback_events_total > 0
4.范围查询: 过去5分钟数据
logback_events_total[5m]
时间范围单位有以下:
- s: 秒
- m: 分钟
- h: 小时
- d: 天
- w: 周
- y: 年
在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准。
如果想查询5分钏前的瞬时样本数据,则需要使用位移操作,关键字:offset, 其要紧跟在选择器{}后面。如:
sum(http_requests_total{method="GET"} offset 5m)
rate(http_requests_total[5m] offset 1w)
聚合、统计高级查询:
count查询: count(logback_events_total)
sum查询: sum(logback_events_total)
svg查询:
topk: 如查询2的值:topk(2, logback_events_total)
irate: 如查询过去5分钟的平均值: irate( logback_events_total[5m])
6. node exporter
二进制安装node exporter进行数据采集
root@k8s-ansible-client:/usr/local/src# wget https://github.com/prometheus/node_exporter/releases/download/v1.3.0/node_exporter-1.3.0.linux-amd64.tar.gz
# 将安装包推送到k8s mater和work节点
root@k8s-ansible-client:/apps# mkdir -p /apps/
root@k8s-ansible-client:/apps# tar -zxvf node_exporter-1.3.0.linux-amd64.tar.gz
root@k8s-ansible-client:/apps# ln -sv node_exporter-1.3.0.linux-amd64 node_exporter
root@k8s-ansible-client:/apps#
root@k8s-ansible-client:/apps#
root@k8s-ansible-client:/apps#
root@k8s-ansible-client:/apps#
设置启动脚本
root@k8s-ansible-client:/apps# cat /etc/systemd/system/node-exporter.service
[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
ExecStart=/apps/node_exporter/node_exporter
[Install]
WantedBy=multi-user.target
root@k8s-ansible-client:/apps# systemctl daemon-reload
启动node_exporter
root@k8s-ansible-client:/apps# systemctl start node-exporter
# 设置开机启动
root@k8s-ansible-client:/apps# systemctl enable node-exporter.service
6.1 配置prometheus拉取k8s master和work节点监控数据
root@ubuntu-template:/apps/prometheus# vim prometheus.yml
...
- job_name: "k8s-master"
static_configs:
- targets: ["192.168.20.201:9100","192.168.20.189:9100","192.168.20.249:9100"]
- job_name: "k8s-node"
static_configs:
- targets: ["192.168.20.236:9100","192.168.20.147:9100","192.168.20.253:9100"]
- job_name: "k8s-client"
static_configs:
- targets: ["192.168.20.250:9100"]
使用promtool 检测配置文件否有问题
root@ubuntu-template:/apps/prometheus# ./promtool check config prometheus.yml
Checking prometheus.yml
SUCCESS: 0 rule files found
重启服务
root@ubuntu-template:/apps/prometheus# systemctl restart prometheus
6.2 验证
7. blackbox exporter
blackbox_exporter是Prometheus 官方提供的 exporter 之一,可以提供 http、dns、tcp、icmp 的监控数据采集。
7.1 安装
使用二进制安装
root@ubuntu-template:/apps# wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.19.0/blackbox_exporter-0.19.0.linux-amd64.tar.gz
root@ubuntu-template:/apps# tar zxvf blackbox_exporter-0.19.0.linux-amd64.tar.gz
blackbox_exporter-0.19.0.linux-amd64/
blackbox_exporter-0.19.0.linux-amd64/blackbox.yml
blackbox_exporter-0.19.0.linux-amd64/LICENSE
blackbox_exporter-0.19.0.linux-amd64/NOTICE
blackbox_exporter-0.19.0.linux-amd64/blackbox_exporter
root@ubuntu-template:/apps# ln -sv blackbox_exporter-0.19.0.linux-amd64 blackbox_exporter
'blackbox_exporter' -> 'blackbox_exporter-0.19.0.linux-amd64'
配置启动
root@ubuntu-template:/apps# cat /etc/systemd/system/blackbox-exporter.service
[Unit]
Description=Prometheus Blackbox exporter
After=network.target
[Service]
ExecStart=/apps/blackbox_exporter/blackbox_exporter --config.file="/apps/blackbox_exporter/blackbox.yml"
[Install]
WantedBy=multi-user.target
root@ubuntu-template:/apps# systemctl daemon-reload
启动blackbox-exporter
root@ubuntu-template:/apps# systemctl start blackbox-exporter
# 设置开机启动
root@ubuntu-template:/apps# systemctl enable blackbox-exporter
Created symlink /etc/systemd/system/multi-user.target.wants/blackbox-exporter.service → /etc/systemd/system/blackbox-exporter.service.
7.2 prometheus中加入blackbox_exporter
监控主机存活
root@ubuntu-template:/apps/prometheus# vim prometheus.yml
...
- job_name: node_status
metrics_path: /probe
params:
module: [icmp]
static_configs:
- targets: ["192.168.20.236", "192.168.20.147"]
labels:
instance: node_status
group: 'node'
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- target_label: __address__
replacement: 127.0.0.1:9115
监控主机端口存活状态
root@ubuntu-template:/apps/prometheus# vim prometheus.yml
...
- job_name: "prometheus_port_status"
metrics_path: /probe
params:
module: [tcp_connect]
static_configs:
- targets: ["192.168.20.201:6443", "192.168.20.189:6443"]
labels:
instance: 'port_status'
group: 'tcp'
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 127.0.0.1:9115
监控网站状态
root@ubuntu-template:/apps/prometheus# vim prometheus.yml
...
- job_name: "web_status"
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets: ["http://www.baidu.com", "http://www.xiaomi.com"]
labels:
instance: user_status
group: 'web'
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- target_label: __address__
replacement: 127.0.0.1:9115
重启prometheus服务
root@ubuntu-template:/apps/prometheus# systemctl restart prometheus
7.3 验证
8. cadvisor监控pod资源
cadvisor对Node机器上的资源及容器进行实时监控和性能数据采集,包括CPU使用情况、内存使用情况、网络吞吐量及文件系统使用情况,cadvisor集成在Kubelet中,当kubelet启动时会自动启动cadvisor,即一个cadvisor仅对一台Node机器进行监控。kubelet的启动参数–cadvisor-port可以定义cadvisor对外提供服务的端口,默认为4194。可以通过浏览器访问。项目主页:http://github.com/google/cadvisor
8.1 结构图
8.2部署
https://github.com/google/cadvisor/releases
# 下载镜像,导入并上传到自己的镜像仓库
root@k8s-harbor-1:/usr/local/src# docker load -i cadvisor-v0.39.2.tar.gz
32f366d666a5: Loading layer [==================================================>] 5.852MB/5.852MB
734cfba50248: Loading layer [==================================================>] 14.62MB/14.62MB
411834cad272: Loading layer [==================================================>] 13.85MB/13.85MB
08ff77729ef3: Loading layer [==================================================>] 7.901MB/7.901MB
4308421affed: Loading layer [==================================================>] 44.94MB/44.94MB
Loaded image: gcr.io/cadvisor/cadvisor:v0.39.2
root@k8s-harbor-1:/usr/local/src# docker tag gcr.io/cadvisor/cadvisor:v0.39.2 harbor.openscp.com/base/cadvisor:v0.39.2
root@k8s-harbor-1:/usr/local/src# docker push harbor.openscp.com/base/cadvisor:v0.39.2
The push refers to repository [harbor.openscp.com/base/cadvisor]
4308421affed: Pushed
08ff77729ef3: Pushed
411834cad272: Pushed
734cfba50248: Pushed
32f366d666a5: Pushed
v0.39.2: digest: sha256:77d1df2341c420adde2282ec06b281d704d3f73e4fe9d56c5120c05353758d03 size: 1373
在work节点启动
root@k8s-work-1:~# docker run -it -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 \
> --privileged \
> --device=/dev/kmsg \
> harbor.openscp.com/base/cadvisor:v0.39.2
Unable to find image 'harbor.openscp.com/base/cadvisor:v0.39.2' locally
v0.39.2: Pulling from base/cadvisor
339de151aab4: Pull complete
ee94623f4d1c: Pull complete
14c73469ff87: Pull complete
2df22c6b8a64: Pull complete
8661234b1461: Pull complete
Digest: sha256:77d1df2341c420adde2282ec06b281d704d3f73e4fe9d56c5120c05353758d03
Status: Downloaded newer image for harbor.openscp.com/base/cadvisor:v0.39.2
fee748dc2425dbd30f1d7d457799870a71f3012b4883c6c8191a45ae099a6a04
8.3 验证
9. prometheus告警
告警能力在Prometheus的架构中被划分成两个独立的部分。如下所示,通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息。
在Prometheus中一条告警规则主要由以下几部分组成:
告警名称:用户需要为告警规则命名,当然对于命名而言,需要能够直接表达出该告警的主要内容
告警规则:告警规则实际上主要由PromQL进行定义,其实际意义是当表达式(PromQL)查询结果持续多长时间(During)后出发告警
在Prometheus中,还可以通过Group(告警组)对一组相关的告警进行统一定义。当然这些定义都是通过YAML文件来统一管理的。
Alertmanager作为一个独立的组件,负责接收并处理来自Prometheus Server(也可以是其它的客户端程序)的告警信息。Alertmanager可以对这些告警信息进行进一步的处理,比如当接收到大量重复告警时能够消除重复的告警信息,同时对告警信息进行分组并且路由到正确的通知方,Prometheus内置了对邮件,Slack等多种通知方式的支持,同时还支持与Webhook的集成,以支持更多定制化的场景。例如,目前Alertmanager还不支持钉钉,那用户完全可以通过Webhook与钉钉机器人进行集成,从而通过钉钉接收告警信息。同时AlertManager还提供了静默和告警抑制机制来对告警通知行为进行优化。
9.1 Alertmanager特性
Alertmanager除了提供基本的告警通知能力以外,还主要提供了如:分组、抑制以及静默等告警特性:
分组
分组机制可以将详细的告警信息合并成一个通知。在某些情况下,比如由于系统宕机导致大量的告警被同时触发,在这种情况下分组机制可以将这些被触发的告警合并为一个告警通知,避免一次性接受大量的告警通知,而无法对问题进行快速定位。
例如,当集群中有数百个正在运行的服务实例,并且为每一个实例设置了告警规则。假如此时发生了网络故障,可能导致大量的服务实例无法连接到数据库,结果就会有数百个告警被发送到Alertmanager。
而作为用户,可能只希望能够在一个通知中中就能查看哪些服务实例收到影响。这时可以按照服务所在集群或者告警名称对告警进行分组,而将这些告警内聚在一起成为一个通知。
告警分组,告警时间,以及告警的接受方式可以通过Alertmanager的配置文件进行配置。
抑制
抑制是指当某一告警发出后,可以停止重复发送由此告警引发的其它告警的机制。
例如,当集群不可访问时触发了一次告警,通过配置Alertmanager可以忽略与该集群有关的其它所有告警。这样可以避免接收到大量与实际问题无关的告警通知。
抑制机制同样通过Alertmanager的配置文件进行设置。
静默
静默提供了一个简单的机制可以快速根据标签对告警进行静默处理。如果接收到的告警符合静默的配置,Alertmanager则不会发送告警通知。
静默设置需要在Alertmanager的Werb页面上进行设置。
9.2 部署Alertmanager
使用二进制文件部署
root@ubuntu-template:/apps# wget https://github.com/prometheus/alertmanager/releases/download/v0.23.0/alertmanager-0.23.0.linux-amd64.tar.gz
root@ubuntu-template:/apps# tar -zxvf alertmanager-0.23.0.linux-amd64.tar.gz
alertmanager-0.23.0.linux-amd64/
alertmanager-0.23.0.linux-amd64/alertmanager.yml
alertmanager-0.23.0.linux-amd64/LICENSE
alertmanager-0.23.0.linux-amd64/NOTICE
alertmanager-0.23.0.linux-amd64/alertmanager
alertmanager-0.23.0.linux-amd64/amtool
root@ubuntu-template:/apps# ln -sv alertmanager-0.23.0.linux-amd64 alertmanager
'alertmanager' -> 'alertmanager-0.23.0.linux-amd64'
设置启动文件
root@ubuntu-template:/apps# cat /etc/systemd/system/alertmanager.service
[Unit]
Description=Prometheus alertmanager
After=network.target
[Service]
Restart=on-failure
WorkingDirectory=/apps/alertmanager
ExecStart=/apps/alertmanager/alertmanager
[Install]
WantedBy=multi-user.target
root@ubuntu-template:/apps# systemctl daemon-reload
9.3 Alertmanager配置文件修改
root@ubuntu-template:/apps/alertmanager# cat alertmanager.yml
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.qq.com:465'
smtp_from: '97534xxx@qq.com'
smtp_auth_username: '97534xxx@qq.com'
smtp_auth_password: '邮箱认证码'
smtp_hello: '@qq.com'
smtp_require_tls: false
route:
group_by: ['alertname']
group_wait: 10s
group_interval: 10s
repeat_interval: 2m
receiver: 'web.hook'
receivers:
- name: 'web.hook'
#webhook_configs:
#- url: 'http://127.0.0.1:5001/'
email_configs:
- to: '97534xxx@qq.com'
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'dev', 'instance']
使用amtool检测配置文件
root@ubuntu-template:/apps/alertmanager# ./amtool check-config alertmanager.yml
Checking 'alertmanager.yml' SUCCESS
Found:
- global config
- route
- 1 inhibit rules
- 1 receivers
- 0 templates
启动
root@ubuntu-template:/apps/alertmanager# systemctl start alertmanager
root@ubuntu-template:/apps/alertmanager# systemctl enable alertmanager
Created symlink /etc/systemd/system/multi-user.target.wants/alertmanager.service → /etc/systemd/system/alertmanager.service.
9.4 配置prometheus报警规则
root@ubuntu-template:/apps/prometheus# vim prometheus.yml
...
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
- 127.0.0.1:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
- "/apps/prometheus/rules/example.yml"
# - "second_rules.yml"
...
规则文件
root@ubuntu-template:/apps/prometheus/rules# cat example.yml
groups:
- name: example
rules:
- alert: NodeMemoryUsage
expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 20
for: 1m
labels:
serverity: critical
annotations:
summary: "{{$labels.instance}}: High Memory usage detected"
description: "{{$labels.instance}}: Memory usage is above 20% (current value is:{{ $value }})"
在告警规则文件中,我们可以将一组相关的规则设置定义在一个group下。在每一个group中我们可以定义多个告警规则(rule)。一条告警规则主要由以下几部分组成:
alert:告警规则的名称。
expr:基于PromQL表达式告警触发条件,用于计算是否有时间序列满足该条件。
for:评估等待时间,可选参数。用于表示只有当触发条件持续一段时间后才发送告警。在等待期间新产生告警的状态为pending。
labels:自定义标签,允许用户指定要附加到告警上的一组附加标签。
annotations:用于指定一组附加信息,比如用于描述告警详细信息的文字等,annotations的内容在告警产生时会一同作为参数发送到Alertmanager。
重启服务
root@ubuntu-template:/apps/prometheus/rules# systemctl restart prometheus
9.5 验证
过了一会,邮箱已经收到告警信息,如下: