MENU

Prometheus+Grafana全方位监控系统

• 2020 年 08 月 30 日 • Linux技术,DevOps


title: Prometheus+Grafana全方位监控系统
categories: DevOps
tags: [Prometheus]
date: 2020-08-30 16:38:00


Prometheus+Grafana全方位监控系统

emmm,前段时间写了一篇关于使用Prometheus+grafana+node-exporter监控k8s的文章,那篇写的很简单,只是单纯的搭建出来了,目前我对这东西一点都不了解,所以先来了解一下Prometheus和他常用的组件吧,包括Prometheus/Grafana/node-exports/Alertmanager,开始吧。

本文包括Prometheus概述、部署、配置、监控、告警、之前我做监控用的都是zabbixzabbix也算是一个全面型的监控系统,但是他不太适合容器监控,他对容器监控集成欠缺很多,他比较偏向于非容器监控。

Prometheus算是一个全能型选手,原生支持容器监控,当然监控传统应用也不是吃干饭的,所以就是容器和非容器他都支持,所有的监控系统都具备这个流程,数据采集→数据处理→数据存储→数据展示→告警,本文就是针对Prometheus展开的,所以先看看Prometheus概述

Prometheus概述

先来看一下Prometheus是个啥

Prometheus是什么

中文名普罗米修斯,最初在SoundCloud上构建的监控系统,自2012年成为社区开源项目,用户非常活跃的开发人员和用户社区,2016年加入CNCF,成为继kubernetes之后的第二个托管项目,官方网站

Prometheus特点

官方扒过来的

  • 多维数据模型:由度量名称和键值对标识的时间序列数据
  • PromSQL: —种灵活的查询语言,可以利用多维数据完成复杂的查询
  • 不依赖分布式存储,单个服务器节点可直接工作
  • 基于HTTP的pull方式釆集时间序列数据
  • 推送时间序列数据通过PushGateway组件支持
  • 通过服务发现或静态配罝发现目标
  • 多种图形模式及仪表盘支持(grafana)

Prometheus 组成与架构

来看一张图,官方扒到的

20190702133835

名称说明
Prometheus Server收集指标和存储时间序列数据,并提供查询接口
Push Gateway短期存储指标数据,主要用于临时性任务
Exporters采集已有的三方服务监控指标并暴露metrics
Alertmanager告警
Web UI简单的WEB控制台

集成了数据的采集,处理,存储,展示,告警一系列流程都已经具备了

数据模型

Prometheus将所有数据存储为时间序列,具有相同度量名称以及标签属于同个指标,也就是说Prometheus从数据源拿到数据之后都会存到内置的TSDB中,这里存储的就是时间序列数据,它存储的数据会有一个度量名称,譬如你现在监控一个nginx,首先你要给他起个名字,这个名称也就是度量名,还会有N个标签,你可以理解名称为表名,标签为字段,所以,每个时间序列都由度量标准名称和一组键值对(也称为标签)唯一标识。

时间序列的格式是这样的,

<metrice name> {<label name>=<label value>,...}

metrice name指的就是度量标准名称,label name也就是标签名,这个标签可以有多个,栗子

nginx_http_access{method="GET",uri="/index.html"}

这个度量名称为nginx_http_access,后面是两个标签,和他们各对应的值,当然你还可以继续指定标签,你指定的标签越多查询的维度就越多。

指标类型

看表格吧

类型名称说明
Counter递增计数器,适合收集接口请求次数
Guage可以任意变化的数值,适用CPU使用率
Histogram对一段时间内数据进行采集,并对有所数值求和于统计数量
Summary与Histogram类型类似

作业和实例

实例指的就是你可以抓取的目标,这个会在Prometheus 配置文件中提现,作业是具有相同目标的实例集合称为作业,你可以理解为是一个组,一会写配置文件的时候会详细解析,下面开始安装Prometheus

Prometheus部署

先通过二进制来部署Prometheus吧,下载地址,我们要下载服务端,也就是这个包

20190702152359

我在服务器上直接下载了,下载完后解压移动到别的目录。

[root@rj-bai ~]# wget https://github.com/prometheus/prometheus/releases/download/v2.10.0/prometheus-2.10.0.linux-amd64.tar.gz
[root@rj-bai ~]# tar zxf prometheus-2.10.0.linux-amd64.tar.gz 
[root@rj-bai ~]# mv prometheus-2.10.0.linux-amd64 /usr/local/prometheus
[root@rj-bai ~]# cd /usr/local/prometheus/ && ls
console_libraries  consoles  LICENSE  NOTICE  prometheus  prometheus.yml  promtool

先配置一下监控本机吧,它默认的配置文件是prometheus.yml,已经配置好了,也就是这一段,

  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:9090']

targets就是一个作业,也就是被监控端,监控本机的9090端口,启动选项也有很多,了解一下,主要是关注两点,分别如下。

      --storage.tsdb.path="data/"   ##存储数据的目录,默认/data
      --storage.tsdb.retention.time ##数据存储时间,默认15天

这里提一下存储的问题,TSDB不太适合长期去存储数据,数据量大了支持并不是很好,官方声明也是不会对这一块存储进行改善,给你的建议是使用外部存储,譬如使用InfluxDB,这里暂时就不改他的默认存储了,把他进入系统服务吧,写一个systemd的配置文件,直接启动了

[root@rj-bai /usr/local/prometheus]# cat > /usr/lib/systemd/system/prometheus.service <<OEF 
> [Unit]
> Description=prometheus server daemon
> 
> [Service]
> Restart=on-failure
> ExecStart=/usr/local/prometheus/prometheus --config.file=/usr/local/prometheus/prometheus.yml
> 
> [Install]
> WantedBy=multi-user.target
> OEF
[root@rj-bai /usr/local/prometheus]# systemctl daemon-reload && systemctl start prometheus.service

这样就启动了撒,去访问9090端口就可以看到页面了,这个页面能看到的东西很多,自己点点看吧,能看到这个页面就表示莫得问题。

20190702163712

目前使用二进制部署主要是因为方便改配置文件,下面开始看配置文件。

全局配置文件介绍

prometheus 已经安装起来了,下面看一下配置文件与核心功能,很多功能都是通过配置文件去实现的,比较多,所以先熟悉一下他的配置文件。

全局配置文件

也就是prometheus.yml,官方说明地址,大概分为这几块,我把注释去掉了,全局配置选项

global:
  [ scrape_interval: <duration> | default = 1m ]      ##采集间隔
  [ scrape_timeout: <duration> | default = 10s ]      ##采集超时时间
  [ evaluation_interval: <duration> | default = 1m ]  ##告警评估周期
  external_labels:                                    ##外部标签             
    [ <labelname>: <labelvalue> ... ]

指定告警规则

rule_files:
  [ - <filepath_glob> ... ]

配置被监控端

scrape_configs:
  [ - <scrape_config> ... ]

配置告警方式

alerting:
  alert_relabel_configs:
    [ - <relabel_config> ... ]
  alertmanagers:
    [ - <alertmanager_config> ... ]

指定远程存储

remote_write:
  [ - <remote_write> ... ]
remote_read:
  [ - <remote_read> ... ]

这就是一个整体的配置文件,现在再看默认的配置文件就能看懂某一段是干啥的了,现在开始配置scrape_configs

scrape_configs

这块就是来配置我们要监控的东西,在这一块中配置的东西又有很多了,看一下官方的,一堆,我还是去掉注释分段贴出来吧。

job_name: <job_name>  ##指定job名字
[ scrape_interval: <duration> | default = <global_config.scrape_interval> ]
[ scrape_timeout: <duration> | default = <global_config.scrape_timeout> ]  ##这两段指定采集时间,默认继承全局
[ metrics_path: <path> | default = /metrics ]  ##metrics路径,默认metrics
[ honor_labels: <boolean> | default = false ]  ##默认附加的标签,默认不覆盖

它默认暴露监控数据的接口就是ip:9090/metrics,你可以去指定这个名称,访问一下这里看看,

20190702171903

ip:9090/targets能看到当前监控的主机,现在只有本机一个,标签显示也在这里。

20190702171956

在看下一段,这里定义的是要如何去访问采集目标

[ scheme: <scheme> | default = http ]  ## 默认使用http方式去访问
params:
  [ <string>: [<string>, ...] ]        ## 配置访问时携带的参数
basic_auth:
  [ username: <string> ]
  [ password: <secret> ]
  [ password_file: <string> ]          ## 配置访问接口的用户名密码
[ bearer_token: <secret> ]
[ bearer_token_file: /path/to/bearer/token/file ]  ##指定认证token
tls_config:
  [ <tls_config> ]                     ## 指定CA证书
[ proxy_url: <string> ]                ## 使用代理模式访问目标

下一段,服务发现配置,贴了几个,不是完整的

consul_sd_configs:                   ##通过consul去发现
  [ - <consul_sd_config> ... ]
dns_sd_configs:                      ##通过DNS去发现
  [ - <dns_sd_config> ... ]
file_sd_configs:                   ##通过文件去发现
  [ - <file_sd_config> ... ]
kubernetes_sd_configs:               ##通过kubernetes去发现
  [ - <kubernetes_sd_config> ... ]

静态配置被监控端

static_configs:
  [ - <static_config> ... ]

刚刚监控本机的就是静态配置去监控的,也是就这一段,

scrape_configs:
  - job_name: 'prometheus'

    static_configs:
    - targets: ['localhost:9090']

最后标签配置

relabel_configs:
  [ - <relabel_config> ... ]          ##在数据采集前对标签进行重新标记
metric_relabel_configs:
  [ - <relabel_config> ... ]          ##在数据采集之后对标签进行重新标记
[ sample_limit: <int> | default = 0 ] ##采集样本数量,默认0

下面看一下relabel_configs

relabel_configs

就是用来重新打标记的,对于prometheus 数据模型最关键点就是一个指标名称和一组标签来组成一个多维度的数据模型,你想完成一个复杂的查询就需要你有很多维度,relabel_configs 就是对标签进行处理的,他能帮你在数据采集之前对任何目标的标签进行修改,重打标签的意义就是如果标签有重复的可以帮你重命名,看一哈现在的,上面铁锅

20190708111918

现在instance是他默认给我加的标签,想改的话就需要relabel_configs去帮你重打标签,他也可以删除标签,如果某个标签用不到了也可以删掉,再就是过滤标签,再看一下relabel_configs的配置有哪些,也就是这一段

relabel_configs: 
  [ source_labels: '[' <labelname> [, ...] ']' ]   ##源标签,指定对哪个现有标签进行操作
  [ separator: <string> | default = ; ]            ##多个源标签时连接的分隔符
  [ target_label: <labelname> ]                    ##要将源标签换成什么名字
  [ regex: <regex> | default = (.*) ]              ##怎么来匹配源标签,默认匹配所有
  [ modulus: <uint64> ]                            ##不怎么会用到
  [ replacement: <string> | default = $1 ]         ##替换正则表达式匹配到的分组,分组引用$1,$2,$3
  [ action: <relabel_action> | default = replace ] ##基于正则表达式匹配执行的操作,默认替换

这东西到底怎么用,做个演示,根据两台服务器聚合查看CPU使用率,说白了就是同时去查看这两台服务器的CPU利用率,用这个标签就可以实现了。

添加标签

WEB界面看一下当前被监控端CPU使用率,用sql去查,也就是这个值。

20190708111918

可以看到一个度量名称和两个默认附加的标签,我现在想统计两台服务器的CPU使用率,就需要加一个标签了,说白了就是添加一个维度去获取这两台服务器CPU使用率,接下来去改配置文件吧,给他加个标签,如下,

    static_configs:
    - targets: ['localhost:9090']
      labels:
        server: local 

热更新一下,

[root@rj-bai /usr/local/prometheus]# ps aux | grep prometheus.yml  | grep -v grep  | awk {'print $2'} | xargs kill -hup

看一下有没有生效,刷新一下页面就能看到了,

20190708113120

然后可以根据这个标签去查了,语法是这样的,内置函数,

sum(process_cpu_seconds_total{server="local"})

201907081124

所以就算你有N个被监控的服务器打上这个标签之后在这里就可以看到总数了,添加标签很简单,下面看一下重命名标签,就是将现有的标签进行重命名。

标签重命名

就是将一个已有的标签重命名一个新的标签,实际操作一下,之前的标签去掉了,现在要把job_name改个名字,也就是这一块的配置,

  - job_name: 'prometheus'

    static_configs:
    - targets: ['localhost:9090']

目前job_nameprometheus,当前这个虚拟机是跑在IP地址为21的物理机上,所以现在把他的job_name改成server21

scrape_configs:
  - job_name: 'server21'

    static_configs:
    - targets: ['localhost:9090']

重启一下,刷新页面就可以看到了,

20190708160319

我现在要将job这个标签标记为local,也就是将job="server21改为local="server21,下面开始用relabel进行重命名,改完之后的配置是这样的,

scrape_configs:
  - job_name: 'server21'

    static_configs:
    - targets: ['localhost:9090']
    relabel_configs:
    - action: replace
      source_labels: ['job']  ##源标签
      regex: (.*)             ##正则,会匹配到job值,也就是server21
      replacement: $1         ##引用正则匹配到的内容,也就是server21
      target_label: local     ##赋予新的标签,名为local

这样就可以了撒,重新加载一下,看页面,

20190708161317

新的数据已经有了,之前的标签还会保留,因为没有配置删除他,这样就可以了,现在就可以聚合了,

20190708161530

这样他就会将所有实例使用率相加求和。

action重新打标签动作

如表所示,上面就是用了一个默认的。

描述
replace默认,通过正则匹配source_label的值,使用replacement来引用表达式匹配的分组
keep删除regex于链接不匹配的目标source_labels
drop删除regex与连接匹配的目标source_labels
labeldrop匹配Regex所有标签名称
labelkeep匹配regex所有标签名称
hashmod设置target_label为modulus连接的哈希值source_lanels
labelmap匹配regex所有标签名称,复制匹配标签的值分组,replacement分组引用(${1},${2})替代

比如说我现在不想采集本机的数据了,就可以用上面的标签进行操作了,加点东西就行了,

scrape_configs:
  - job_name: 'server21'

    static_configs:
    - targets: ['localhost:9090']
    relabel_configs: 
    - action: replace
      source_labels: ['job']
      regex: (.*)
      replacement: $1
      target_label: local
    - action: drop
      source_labels: ["job"]

删除标签为job的节点,目前只有一个节点,所以这个跑了之后就看不到数据了,如果真的要用这个给不需要监控的节点打一个标签,然后在这里匹配就行了,所以现在重新载入的话就没数据了,

20190708164048

最后看一下删除标签。

删除标签

刚刚我新打了一个标签,也就是local标签,所以之前的job标签可以不要了,下面直接给他删了吧,

scrape_configs:
  - job_name: 'server21'

    static_configs:
    - targets: ['localhost:9090']
    relabel_configs: 
    - action: replace
      source_labels: ['job']
      regex: (.*)
      replacement: $1
      target_label: local
    - action: labeldrop 
      regex: job

重载一下就看到job的标签了。

20190708164600

这样就可以了撒,下面看看基于文件的服务发现功能

基于文件的服务发现

下面会涉及到基于文件的服务发现,还有就是基于kubernetes的服务发现,这个到监控k8s集群的时候再说吧,先看基于文件的吧,现在还没准备别的服务器,还是发现本身吧,先把配置文件改成这样,重载之后就看不到本机了。

[root@rj-bai /usr/local/prometheus]# cat prometheus.yml
global:
  scrape_interval:     15s 
  evaluation_interval: 15s 

alerting:
  alertmanagers:
  - static_configs:
    - targets:

rule_files:

scrape_configs:
  - job_name: 'prometheus'

20190708171041

然后就可以去改配置文件了,通过服务发现将自身加入进去,

[root@rj-bai /usr/local/prometheus]# cat prometheus.yml
global:
  scrape_interval:     15s 
  evaluation_interval: 15s 

alerting:
  alertmanagers:
  - static_configs:
    - targets:

rule_files:

scrape_configs:
  - job_name: 'prometheus'
    file_sd_configs: 
      - files: ['/usr/local/prometheus/files_sd_configs/*.yaml']  ##指定服务发现文件位置
        refresh_interval: 5s                                      ##刷新间隔改为5秒

重载服务,然后去写服务发现的YAML文件吧,

[root@rj-bai /usr/local/prometheus/files_sd_configs]# cat configs.yml 
- targets: ['localhost:9090'] 
  labels:
    name: server21

这样就可以了,文件保存五秒后就能看到发现的主机了,查数据也没问题

20190708173554

20190708173611

20190708173654

就是这种原理,下面开始监控linux和一些服务吧

监控栗子

监控linux服务器

emmmm,在被监控端需要装一个名为node_exporter的导出器,他会帮你收集系统指标和一些软件运行的指标,把指标暴露出去,这样prometheus就可以去采集了,具体node_exporter能采集哪些东西,看官方的github吧,还是蛮多的,现在随便找个服务器下载一下node_exporter运行起来就行了。

[root@kubeadm-node ~]# wget https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-amd64.tar.gz
[root@kubeadm-node ~]# tar zxf node_exporter-0.18.1.linux-amd64.tar.gz 
[root@kubeadm-node ~]# mv node_exporter-0.18.1.linux-amd64 /usr/local/node_exporter
[root@kubeadm-node ~]# cd /usr/local/node_exporter

在启动之前看一下他的启动参数,

[root@kubeadm-node /usr/local/node_exporter]# ./node_exporter --help

可以看到一堆,她就是一个收集器,配置你要收集或不收集哪些信息,看default就能看出来撒,加到系统服务中吧,用systemctl去管理。

[root@kubeadm-node /usr/local/node_exporter]# cat > /usr/lib/systemd/system/node_exporter.service <<OEF 
> [Unit]
> Description=node_exporter
> 
> [Service]
> Restart=on-failure
> ExecStart=/usr/local/node_exporter/node_exporter
> 
> [Install]
> WantedBy=multi-user.target
> OEF
[root@kubeadm-node /usr/local/node_exporter]# systemctl daemon-reload 
[root@kubeadm-node /usr/local/node_exporter]# systemctl start node_exporter.service
[root@kubeadm-node /usr/local/node_exporter]# curl -s 127.0.0.1:9100/metrics | head 

20190709105800

正常启动了撒,现在要配置prometheus来监控这个主机了,之前配置过动态发现了,现在再加一个,把服务端和被监控端分开,所以新加了这个。

[root@rj-bai /usr/local/prometheus]# cat prometheus.yml
  - job_name: 'nodes'
    file_sd_configs: 
      - files: ['/usr/local/prometheus/nodes_sd_configs/*.yml']
        refresh_interval: 5s 
[root@rj-bai /usr/local/prometheus]# mkdir nodes_sd_configs && cd nodes_sd_configs
[root@rj-bai /usr/local/prometheus]# ps aux | grep prometheus.yml  | grep -v grep  | awk {'print $2'} | xargs kill -hup
[root@rj-bai /usr/local/prometheus/nodes_sd_configs]# cat nodes.yml
- targets: ['192.168.1.248:9100'] 
  labels:
    name: server20

直接去看页面吧,应该已经添加进去了,顺便查一下数据

20190709111843

20190709112040

这样就可以了,莫得问题,下面用PromSQL获取CPU&内存硬盘使用率

使用PromSQL

想查数据就需要写PromSQL去查询了,

查询CPU使用率

比如果我想查看刚刚加进来的nodes CPU利用率,以node开头的sql都是node_expores采集的指标,度量很多,看CPU使用率看着一个指标就够了,

CPU使用情况,会列出你处理器多少核,每个核的使用情况,这个CPU是干什么使用的,用户态还是内核态还是操作IO等待的时间,还有优先级调度使用的CPU,他会通过一个名为mode的标签去区分这些,一般不会这么去统计,现在统计一下刚刚加进去的那个nodes五分钟之内CPU平均使用率是多少,还是得写PromSQL,大概是这样,

100 - irate(node_cpu_seconds_total{mode="idle"}[5m])*100

emmmnode_cpu_seconds_total{mode="idle"}[5m]这一段是统计出了服务器最近5分钟CPU的空闲率,执行之后是这种效果,

20190709114438

这是五分钟之内所有值,然后使用了irate函数来统计它的平均值,转化成了百分比,乘了一百,所以执行结果如下。

20190709114935

这就是所有CPU的空闲率了,我要取的是所有CPU的使用率,所以又一百减去了空闲率的值就是使用率了,所以上面第一条sql执行发回的结果如下。

20190709115136

这就是五分钟之内总的CPU的平均使用率了,我的那个节点就是四核CPU,每个都被列出来了,真鸡儿麻烦,再看一下内存使用率,和上面其实一样,值都有了,求出他的百分比就行了,

查询内存使用率

linux内核有一个内存缓存机制,所以buff/cache的占用不算是已被使用的物理内存,所以计算方式就是将这三个值加到一起就是剩余内存了,

20190709134042

sql的话这样写,直接查一下,

node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes

20190709134504

这就是总共剩余的内存,单位是bite,现在我要计算使用内存百分比,和上面看CPU使用率的方法一致,sql如下

100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes *100

20190709135149

下面看看硬盘使用率

查询硬盘使用率

你的磁盘和挂载点可能不止一个,先看一下目前收集到的信息,

20190709145758

所以就要指定分区进行计算了,所以匹配这里写了一个正则去匹配你挂载的磁盘,如下

100- (node_filesystem_free_bytes{mountpoint="/",fstype=~"ext4|xfs"} / node_filesystem_size_bytes{mountpoint="/",fstype=~"ext4|xfs"} *100)

node_filesystem_size_bytes查的是/总大小,node_filesystem_free_bytes查的是剩余大小,只匹配ext4&xfs类型的,像是什么tmpfs&shm类型的都不匹配,还是算出了剩余的百分比,所以执行后的结果是这样,

20190709150539

20190709150559

计算方式大概就是这样,现在还没涉及到图形展示这一块,下面看一下获取系统服务运行状态。

查询系统服务运行状态

就是监控系统服务运行状态,说白了就是监控以systemctl启动的服务,现在监控一下这个,node_exports就支持对这种服务进行监控,目前还没有启用这个功能,现在启动一下撒,直接去改node_exports的启动文件,加两条参数即可。

[root@kubeadm-node ~]# cat /usr/lib/systemd/system/node_exporter.service 
[Unit]
Description=node_exporter

[Service]
Restart=on-failure
ExecStart=/usr/local/node_exporter/node_exporter --collector.systemd --collector.systemd.unit-whitelist=(docker|sshd).service

[Install]
WantedBy=multi-user.target

第二段就是制定我要监控哪些系统服务,我写了docker&sshd,重启后可以去查询了,

[root@kubeadm-node ~]# systemctl daemon-reload         
[root@kubeadm-node ~]# systemctl restart node_exporter.service 

我查一下当前docker&sshd的运行状态是什么,可以直接这样写了,

node_systemd_unit_state{exported_name=~"(docker|sshd).service"}

20190709153503

目前state=active的值为0,说明正常运行,所以之后写告警规则的时候就去判断这个值是不是1,如果不是就要进行某些操作了,下面装一下grafana

部署grafana

grafana就是一个图形展示系统,他主要是对度量指标进行分析可视化,他本身不会存储任何数据,他只会展示数据库里面的数据,支持很多类型的数据库,官网,刚好我装有docker,其实目前在操作的这两台服务是一个k8s集群,用kubeadm启动的,所以我直接用docker启动了,还是写个deployment,算了直接用docker命令启吧,

[root@kubeadm-node ~]# docker run \
> -u 0 \
> -d \
> -p 3000:3000  \
> --name=grafana   \
> -v /var/lib/grafana:/var/lib/grafana \
> grafana/grafana

这样就行了,直接访问3000端口就好了,用户名密码默认admin/admin,初次登陆会让你修改密码,就可以看到主页了,然后直接添加数据源,把prometheus加进去,保存就行了,

20190709163321

然后直接导入一个仪表盘进来吧,ID9276,大概是这种效果,

img

然后网络带宽那里没数据,我看了一下他的sql,只需要将$nic改为你的网卡名就有数据了,所以现在监控linux服务器是没问题了,下面试试监控docker

监控docker

想要监控docker需要用到名为cadvisor的工具,是谷歌开源的,它用于收集正在运行的容器资源使用和性能信息,github地址,你需要在要监控的服务器上部署cadvisor,直接用docker去启动就完了,命令如下

docker run \
  --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 \
  google/cadvisor:latest

容器启动后也是会暴露一个指标接口,默认是8080/metrics,这里就不访问了,下一步就是加入到普罗米修斯中进行监控了,去改他的配置文件,静态配置一个吧,

  - job_name: 'docker'
    static_configs: 
    - targets: ['192.168.1.248:8080']

加完直接重载,页面直接导入一个图表吧,ID193或者11277再或者11600!!!,效果是这样的,

20190709181607

主要就是监控容器的CPU内存网络流量的,都可看到,目前我248就运行了六个容器,就是这样,下面在看看监控mysql

监控mysql

监控mysql就会用到mysql_exporter,这个也能在官网下到,也就是这里,这个东西需要你安装到运行mysql的实例上,本地的mysql比较多,我随便找了一个扔了上去,先去mysql创建一个用户吧,这个程序需要连接明月三千里才能获取到指标。

mysql> CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'exporter';
Query OK, 0 rows affected (0.02 sec)

mysql> GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> select user,host from mysql.user;

20190709184630

用户创建好了去解压包吧,

[root@mysql ~]# tar zxf mysqld_exporter-0.11.0.linux-amd64.tar.gz -C /usr/local/ && cd /usr/local/
[root@mysql local]# mv mysqld_exporter-0.11.0.linux-amd64/ mysqld_exporter && cd mysqld_exporter

需要写一个文件,mysqld_exporter直接读这个文件就可以连接mysql了,

[root@mysql mysqld_exporter]# cat .my.cnd
[client]
user=exporter
password=exporter

文件有了,在启动的时候指定一下读取这个文件,直接启动

[root@mysql mysqld_exporter]# ./mysqld_exporter --config.my-cnf=.my.cnf

img

现在把这个加到普罗米修斯中,

  - job_name: 'mysql'
    static_configs: 
    - targets: ['192.168.1.126:9104']

然后导入一个仪表盘,ID7362,看页面,

img

还是有些空值,而且官方也说了5.6版本有些不支持,我看了一下Buffer Pool Size of Total RAMsql,是这样写的,

(mysql_global_variables_innodb_buffer_pool_size{instance="$host"} * 100) / on (instance) node_memory_MemTotal_bytes{instance="$host"}

现在应该能看的差不多了,他去查了mysql节点的总内存,但是我明月三千里节点并没有装node_exports,所以就没数据了,总之支持采集的数据和仪表盘模板很多,自行琢磨吧,上面只是最简单的几个例子,下面来看看告警这一块的东西。

alertmanager

普罗米修斯本身是不支持告警的,告警是由alertmanager这个组件完成的,普罗米修斯将告警收集起来会推送给alertmanageralertmanager接收到告警后决定怎么去处理这些告警,应该发给谁,下面先部署一下alertmanager吧,我直接下载了,在普罗米修斯服务器上,

部署alertmanager

alertmanager没必要和普罗米修斯放在一个服务器上,他们之间能通讯就可以了,我目前资源紧张就扔到一起了,直接wget了,

[root@rj-bai ~]# wget https://github.com/prometheus/alertmanager/releases/download/v0.18.0/alertmanager-0.18.0.linux-amd64.tar.gz

让他先下着,聊一下普罗米修斯和alertmanager是怎么通讯的,首先你需要在prometheus中定义你的监控规则,说白了就是写一个触发器,某个值超过了我设置的阈值我就要告警了,触发告警之后prometheus会推送当前的告警规则到alertmanageralertmanager收到了会进行一系列的流程处理,然后发送到接收人手里,他的处理规则也是很复杂的,后面会说,现在也下载完了,解压

[root@rj-bai ~]# tar zxf alertmanager-0.18.0.linux-amd64.tar.gz 
[root@rj-bai ~]# mv alertmanager-0.18.0.linux-amd64 /usr/local/alertmanager && cd /usr/local/alertmanager && ls
alertmanager  alertmanager.yml  amtool  LICENSE  NOTICE

有两个二进制文件,分别是启动程序和一个工具,还有一个主配置文件,先来了解一下他的主配置文件,

global:
  resolve_timeout: 5m

全局配置,设置解析超时时间,

route:
  group_by: ['alertname']      ##alertmanager中的分组,选哪个标签作为分组的依据
  group_wait: 10s              ##分组等待时间,拿到第一条告警后等待10s,如果有其他的一起发送出去
  group_interval: 10s          ##各个分组之前发搜告警的间隔时间
  repeat_interval: 1h          ##重复告警时间,默认1小时
  receiver: 'web.hook'         ##接收者

这里是配置告警的,配置告警怎么发送,怎么来分配,

receivers:
- name: 'web.hook'
  webhook_configs:
  - url: 'http://127.0.0.1:5001/'

这里是配置告警的接收者,我要发送给谁,

inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'dev', 'instance']

这里用于配置告警收敛的,主要就是减少发送告警,来发送一些关键的,所以先把这段注释了吧,暂时用不到,之后会用到,所以基于这个配置文件改改,暂时先发送email吧,所以改完的配置文件如下,

[root@rj-bai /usr/local/alertmanager]# cat alertmanager.yml 
global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.163.com:25'         #smtp服务地址
  smtp_from: 'xxx@163.com'                  #发送邮箱
  smtp_auth_username: 'xxx@163.com'         #认证用户名
  smtp_auth_password: 'xxxx'                #认证密码
  smtp_require_tls: false                   #禁用tls

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1m
  receiver: 'email'                      #定义接受告警组名
receivers:                                  
- name: 'email'                          #定义组名
  email_configs:                         #配置邮件
  - to: 'xx@xxx.com'                     #收件人

保存后检查一下这个文件有没有问题,命令如下,

[root@rj-bai /usr/local/alertmanager]# ./amtool check-config alertmanager.yml 
Checking 'alertmanager.yml'  SUCCESS

然后去启动吧,还是加到系统服务中吧,

[root@rj-bai /usr/local/alertmanager]# cat > /usr/lib/systemd/system/alertmanager.service <<OEF 
> [Unit]
> Description=alertmanager
> 
> [Service]
> Restart=on-failure
> ExecStart=/usr/local/alertmanager/alertmanager --config.file=/usr/local/alertmanager/alertmanager.yml
> 
> [Install]
> WantedBy=multi-user.target
> OEF
[root@rj-bai /usr/local/alertmanager]# systemctl start alertmanager

现在alertmanager是装完了,需要和prometheus融合一下,需要配置两部分,分别如下,

alerting:
  alertmanagers:
  - static_configs:
    - targets:
       - 127.0.0.1:9093   ##配置alertmanager地址,我的在本机

rule_files:
  - "rules/*.yml"         ##配置告警规则的文件

配置这两项就够了,保存之后创建rules目录,接下来就可以配置告警规则了。

配置告警规则并邮件通知

我直接在官方复制过来了一个例子顺便改了改,如下,

[root@rj-bai /usr/local/prometheus/rules]# cat example.yml
groups:
- name: exports.rules     ##定义这组告警的组名,同性质的,都是监控实例exports是否开启的模板
  rules:

  - alert: 采集器凉了     ## 告警名称
    expr: up == 0        ## 告警表达式,监控up指标,如果等于0就进行下面的操作
    for: 1m              ## 持续一分钟为0进行告警
    labels:              ## 定义告警级别
      severity: ERROR
    annotations:         ## 定义了告警通知怎么写,默认调用了{$labels.instance&$labels.job}的值
      summary: "实例 {{ $labels.instance }} 采集器凉了撒"
      description: "实例 {{ $labels.instance }} job 名为 {{ $labels.job }} 的采集器凉了有一分钟了撒"

每个实例都会有一个up的指标,上面的标签名job都能看到,用sql去查一下,

img

采集器在开启状态下返回值就是1,如果采集器出现问题没启动或是什么别的异常都会返回00就是代表异常了,所以说白了就是那条规则就是监控所有实例的up指标,如果指标值为0且持续时间超过一分钟我就要告警了,保存吧,直接重启prometheus吧,重启之后可以在web控制台看到你配置的规则了,

img

emmmm,既然配置完了,验证一下吧,随便关掉一个采集器,等邮件就行了,我把明月三千里的关掉了,然后发现有一条告警处于PENDING状态,他已经准备去通知alertmanager了,

一分钟之后我收到邮件了,长这样,

20190711154859

如果问题没解决他每分钟都会给你发一封邮件,刚刚配置了,发送邮件的等待时间一会会细说一下,我再停一个,我再把docker停了,看看他发出的邮件是什么样的,

img

这里两条告警被合并到一个邮件里发出来了,这就是做了分组,如果你有同类告警的,也就是根据alertname 去区分的,都会给你合并,mysql&docker被合并到一起了,再看一下他还是支持哪些方式来告警,看这里吧,拉到最下面可以看到支持微信,丁丁目前是不支持的,有第三方的,我将来会对接企业微信的撒,暂时现用邮件吧,下面看看alertmanager的告警状态吧。

告警状态

目前alertmanager告警状态分为三种,如下

说明
Inactive什么都没有发生
Pending已触发阈值,但未满足告警持续时间,for时间
Firing已触发阈值且满足告警持续时间,通知alertmanager你可以发送告警了

在这个阶段是有个时间的,并不是出现问题告警会马上发出去,这个时间包含了数据采集时间、告警评估时间,这两个时间是在prometheus中配置的,也就是这里,

global:
  scrape_interval:     15s 
  evaluation_interval: 15s 

目前是十五秒采集一次数据,评估告警规则时间也是十五秒,这个评估告警规则的时间就是我每隔多长时间要进行一次评估是否到达的阈值了,说白了这东西的目的就是为了减少告警的次数,更加精确的判断当前的状态是不是ok的,下面在看看告警的分配

告警的分配

具体告警要怎么去分配,也是在alertmanager中配置的,也就是这一段,

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1m
  receiver: 'email'

这就是设置告警的分发策略了,这个route可以拆分成多个子路由,目前所有的告警都会发送到名为email的接收器里面,email接收器的规则也是在配置文件中指定的,也就是这一段,

receivers:
- name: 'email'
  email_configs:
  - to: 'xx@xxx.com'

接收器目前只有一个名为email的,也可以有多个,如果你有什么特殊需求,需要将不同类型的告警发送给不同的人,就需要配置多个接收器去区分了,如下,

global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.163.com:25'
  smtp_from: 'xxx@163.com'
  smtp_auth_username: 'xxx@163.com'
  smtp_auth_password: 'xxx'
  smtp_require_tls: false

route:
  receiver: 'default-receiver'                  ##定义默认接收器名,如果其他的匹配不到走这个
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  group_by: [cluster, alertname]                ##分组设置
  routes:                                       ##子路由
  - receiver: 'database-pager'                  ##定义接收器名字          
    group_wait: 10s                             ##分组设置
    match_re:                                   ##正则匹配
      service: mysql|cassandra                  ##他会接收标签service值为mysql&&cassandra的告警
  - receiver: 'frontend-pager'                  ##接收器名
    group_by: [product, environment]            ##分组设置
    match:                                      ##直接匹配
      team: frontend                            ##匹配标签team值为frontend的告警
receivers:                                      ##定义接收器
- name: 'default-receiver'                      ##接收器名字
  email_configs:                                ##邮件接口
  - to: 'xxx.xx.com'                            ##接收人,下面以此类推
- name: 'database-pager'
  email_configs:
  - to: 'xxx.xx.com'
- name: 'frontend-pager'
  email_configs:
  - to: 'xxx@.xx.com'

我就不掩饰了,配置其实很简单,演示很麻烦撒,算了算了,过,下面看一哈告警收敛

告警收敛

收敛就是尽量压缩告警邮件的数量,太多了谁都会懵逼,可能有些关键的呗淹没了,alertmanager中有很多收敛机制,最主要的就是分组抑制静默,alertmanager收到告警之后他会先进行分组,然后进入通知队列,这个队列会对通知的邮件进行抑制静默,再根据router将告警路由到不同的接收器,这就是alertmanager收到一个告警后经历的阶段,只是一个大概的情况,下面深入了解一下这几个阶段到底是什么原理怎么去配置,先来简单看一下他们的定义

机制说明
分组(group)将类似性质的告警合并为单个进行通知
抑制(Inhibition)当告警发生后,停止重复发送由此告警引发的其他告警
静默(Silences)是一种简单的特定时间静音提醒的机制

分组

举个栗子,比如说我在阿里云有10台服务器,但是我忘续费了,结果服务器到期都被停掉了(真实发生过),这时候node_exports肯定也无法访问了,服务器都停了,这时候普罗米修斯发现这10个服务器都凉了,我要准备通知alertmanager告警了,在不做分组的情况下你的告警媒介会有十条信息发出来,这种情况下我们可以他这些信息合并到一起撒,一条信息列出哪些服务器凉了。

其实分组设置最开始的时候我就做了,这一段就是设置分组的,

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1m

这里配置了分组的依据,默认就是alertname,这个名字可以随便写的,做了分组之后他会去匹配你告警时的名字,告警的名字是在这里配置的,

  - alert: 采集器凉了

如果是相同名字的告警在一定时间内出现多条,这个一定时间指的就是group_wait的时间,那么多条就会合并成一条告警信息发出来,这个之前就配置了,所以在我停掉mysql&docker采集器之后他就把这两条告警合并成一条信息发了出来,也就是这张图,上面贴过了。

img

这两条的告警名字都是采集器凉了撒,而且在十秒钟之内出现了两条,所以就被合并成一条发出来了,分组的目的就是为了减少告警信息的数量,同类告警聚合,所以现在总结一下配置分组的参数。

  group_by: ['alertname']  #根据标签进行alert分组,可以写多个
  group_wait: 10s          #发送告警等待时间,
  group_interval: 10s      #分组告警信息间隔时间,譬如两组,第一组发送后等待十秒发送第二组
  repeat_interval: 1m      #重复发送告警时间,时间不要太短,也不要太长

抑制

他的主要作用就是消除冗余告警,我们会受到一个关键的告警信息,这个也是在alertmanager中配置的,我标签只留了一个,

inhibit_rules:
  - source_match:          
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['instance']

这段配置意思就是当我收到一个告警级别为critical时,他就会抑制掉warning这个级别的告警,这个告警等级是在你编写规则的时候定义的,最后一行就是要对哪些告警做抑制,通过标签匹配的,我这里只留了一个instance,举个最简单的例子,当现在alertmanager先收到一条critical、又收到一条warninginstance值一致的两条告警他的处理逻辑是怎样的。

我现在监控nginxnginx宕掉的告警级别为warning,宿主机宕掉的告警级别为critical,譬如说现在我跑nginx的服务器凉了,这时候nginx肯定也凉了,普罗米修斯发现后通知alertmanager,普罗米修斯发过来的是两条告警信息,一条是宿主机凉了的,一条是nginx凉了的,alertmanager收到之后,发现告警级别一条是critical,一条是warning,而且instance标签值一致,也就是说这是在一台机器上发生的,所以他就会只发一条critical的告警出来,warning的就被抑制掉了,我们收到的就是服务器凉了的通知,大概就是这样,暂时不演示了。

静默

就是一个简单的特定时间静音提醒的机制,主要是使用标签匹配这一批不发送告警,譬如说我某天要对服务器进行维护,可能会涉及到服务器重启,在这期间肯定会有N多告警发出来,所以你可以子啊这期间配置一个静默,这类的告警就不要发了,我知道发生了啥子事情,配置静默就很简单了,直接在web页面配置就行了,9093端口,

img

img

选择开始时间结束时间,通过标签匹配去做,我匹配了job=docker的机器,创建,所以我先在把容器采集器停掉也不会有告警出来了,我就不停了,就是这样配置,比较简单,扯了一堆,是时候自己写一个告警规则了,结合上面一切的东西。

编写告警规则栗子

来监控内存吧,内存使用率超过80我就要告警了,还是先需要写sql,把我想要的值查出来,所以要查当前内存使用率大于百分之八十的sql如下,

(node_memory_MemTotal_bytes - node_memory_MemFree_bytes - node_memory_Buffers_bytes - node_memory_Cached_bytes) / (node_memory_MemTotal_bytes )* 100 > 80

下面就是要写规则了,我写的规则如下,顺便把之前的规则也改了一下,

[root@rj-bai /usr/local/prometheus/rules]# cat memory.yml 
groups:
- name: memeory_rules
  rules:

  - alert: 内存炸了
    expr: (node_memory_MemTotal_bytes - node_memory_MemFree_bytes - node_memory_Buffers_bytes - node_memory_Cached_bytes) / (node_memory_MemTotal_bytes )* 100 > 80
    for: 1m
    labels:
      severity: warning
    annotations:
      summary: "{{ $labels.instance }} 内存炸了"
      description: "{{ $labels.instance }} 内存炸了,当前使用率为 {{ $value }}"

这样就可以了撒,我又把明月三千里加入到监控,也就是安装了node_exports,现在也能正常获取到使用率了,下面试试上面提到的那个告警分配,我要把明月三千里的告警信息发送到我另一个邮箱,job名字mysql

  - job_name: 'mysql'
    static_configs: 
    - targets: ['192.168.1.126:9104']
    - targets: ['192.168.1.126:9100']

重启一下撒,能看到这些,

img

img

然后去配置一下告警的分配,我要把关于明月三千里的告警发送到另一个邮箱,所以这里改了一哈,

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 5m
  receiver: 'default-receiver'
  routes: 
    - group_by: ['mysql']
      group_wait: 10s
      group_interval: 10s
      repeat_interval: 5m
      receiver: 'mysql-pager'
      match_re:
        job: mysql

receivers:
- name: 'default-receiver'
  email_configs:
  - to: 'xxx@xx.com'
- name: 'mysql-pager'
  email_configs:
  - to: 'xxx@xx.cn'

inhibit_rules:
  - source_match:          
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['instance']

所以一会收到明月三千里的邮件是我cn的邮箱,这样就可以了撒,重启alertmanager,为了让他发出告警邮件,我调一下阈值,改为百分之20,所以我com收到的邮件如下,

img

cn收到的邮件如下

img

然后再试一下抑制,我再加一个监控项,我要监控TCP连接数,状态是ESTABLISHED的,超过300我就要告警了,定义告警级别为critical,所以rule文件如下,

[root@rj-bai /usr/local/prometheus/rules]# cat tcp-established.yml 
groups:
- name: tcp-established_rules
  rules:

  - alert: TCP连接数过高
    expr: node_sockstat_TCP_alloc > 300 
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "{{ $labels.instance }} TCP连接数过高"
      description: "{{ $labels.instance }} TCP连接数过高,当前连接数 {{ $value }}"

重启后看页面,

img

有三条告警已经进入Pending状态了,没意外的话cn邮箱只有一条告诉你连接数过高的告警信息发出来了,内存使用率过高的就会被抑制,看一下,

img

所以这条已经被抑制了,

img

248服务器不受影响,com邮箱还是会收到内存炸了的告警,

img

就是这样撒,你想编写其他的告警规则流程和上面是一样的,告警的分配和抑制不是必需的,自行琢磨吧,下一篇准备重写K8S监控方面的东西,了解这些东西之后之后就应该很简单了撒,本篇就这样,过。

返回文章列表 文章二维码 打赏
本页链接的二维码
打赏二维码