【监控】Prometheus+Grafana监控简介

96
whaike
3.1 2019.01.28 17:18* 字数 4855
文章目的:

1、向没听过或者刚听过但是还对这个监控系统没有任何概念的开发者介绍Prometheus的应用场景。
2、向有需要深入的了解的人推荐一些博客、书籍。
3、内心真实想法:本想写个系统一点的,但是列出那些博文书籍之后,感觉已经没有必要了。。。

什么是Prometheus?

prometheus是一个开源的监控系统。。。算了官方的话一大把看得太累

那么到底什么是Prometheus呢,他确实是用来做监控系统的,但是这里我们先不讨论它,我们来看个小工具node_exporter

什么是 node_exporter

举个例子,如果你有一台服务器,你想要获取它运行时候的参数,比如当前的CPU负载、系统负载、内存消耗、硬盘使用量、网络IO等等,那么你就可以在服务器上运行一个node_exporter,它能帮你把这些参数收集好,并且暴露出一个HTTP接口以便你访问查询。废话不多说我们直接试一试

准备一台Linux服务器,外网互通:

IP:10.19.70.139
系统:ubuntu 16.04

登录系统进入/opt目录(目录随便指定,空间大于待会儿下载的文件大小即可)

下载并运行最新版的node_exporter 【如果你想看源码,可以访问gihub开源地址,它是Go语言编写的,部署很方便】

cd /opt
sudo wget https://github.com/prometheus/node_exporter/releases/download/v0.17.0/node_exporter-0.17.0.linux-amd64.tar.gz
sudo tar -zxvf node_exporter-0.17.0.linux-amd64.tar.gz
cd node_exporter-0.17.0.linux-amd64
sudo ./node_exporter

可以看到如下的输出


image.png

访问方式:IP+Port
我们访问http://10.19.70.139:9100点击Metrics(如果你使用老版本的node_exporter那么可能没有这个Metric标题页)就可以看到暴露出来的系统参数了

指标举例

#HELP node_cpu_seconds_total Seconds the cpus spent in each mode.
#TYPE node_cpu_seconds_total counter
node_cpu_seconds_total{cpu="0",mode="idle"} 1.40181324e+06

这是其中一条指标,由指标名+{标签键值对}+值 组成。
#HELP开头的行用来说明下面指标node_cpu_seconds_total的意义:
指标node_cpu_seconds_total用来表示CPU在每种模式下工作的秒数,而大括号里的称之为标签,以键值对的形式出现,可以用来细分同一个指标下的不同部分,比如这里的cpu="0"表示CPU的第0个核心,mode="idle"表示工作模式为idle,也就是没被任何程序使用的空闲模式。
#TYPE开始的第二行表示指标的数值类型为counter类型。在Prometheus的规范中,counter类型表示只增长的类型,也就是只会增加不会减少的值,且数值只能是正整数。大数值会启用科学计数法。
此时可以看出指标node_cpu_seconds_total{cpu="0",mode="idle"} 1.40181324e+06表示节点的CPU0的空闲时间共计1.40181324e+06秒。数值从系统开机时算起,重启归零。

问题与答案:

此时我们可以从页面中看到很多类似的指标以及值,如果只打算监控这一台,又或者只需要这一个值,我们可以自行编写代码访问这个接口,匹配出想要的指标和值即可。但是如果有很多台服务器,而且想要综合多台进行对比分析,更有甚者希望将指标绘制成图表,或者说保留历史数据以便查询过去的某个时间点其服务器的运行状态,那么这将会变得很麻烦。而Prometheus就是干这个事情的。

什么是Prometheus?

现在当我们再一次讨论什么是Prometheus的时候,我想你心里一定有个大概的猜测了,如果你认真思考了上面的问题与答案的话。我们想要获取所有的服务器上node_exporter暴露出来的数据,就必须有个程序去定时访问这些接口,如果想要增加或者修改这些接口,那么就需要有个配置文件来记录这些服务器的地址,如果想要访问历史的某个时间点的数据,那么就必须按照时间顺序存储获取到的指标和值。而如果想要将值绘制成图,也需要有代码去查询、计算和渲染。最后你可能还希望当服务器的某个指标超过一定的阈值时,向指定的接口发出告警信息。一切的一切其实都可以使用Prometheus来解决,现在我们可以去了解什么是Prometheus了。

先上一张官方的架构图


image.png

从架构图中可以看到,我们先前验证的node_exporter属于jobs/exporter部分,称之为exporter导出器,是Prometheus主要的指标来源。
Prometheus Server是服务核心组件,存储使用时序数据库TSDB将数据保存在硬盘上,由于官方对SSD做了专门的优化,所以使用SSD性能会更优。
配置方式包含多种,可以直接在写在yaml文件中,但如果配置较长也可以写入其他文件并启用文件发现(file_sd)功能让其自行侦听配置文件变化,甚至可以使用consul或者kubernetes这样的服务发现来动态更新配置以适应频繁的节点变更。
Prometheus使用pull模型从节点暴露出来的端口拉取配置,这相比push方式更容易避免节点异常带来的干扰和繁琐的工作。
pushgateway类似于一个中转站,Prometheus的server端只会使用pull方式拉取数据,但是某些节点因为某些原因只能使用push方式推送数据,那么它就是用来接收push而来的数据并暴露给Prometheus的server拉取的中转站。
Prometheus支持告警系统,自带的alertmanager可以通过在配置文件中添加规则的方式,计算并发出警报,它支持多种发送方式比如pagerduty、Email等等。
对于已经存储的历史数据,Prometheus提供了PromQL语言进行查询,并自带了一个简易的UI界面,可以在界面上进行查询、绘图、查看配置、告警等等。

架构图中,Grafana等其他API客户端可以通过PromQL查询语言查询Prometheus中存储的数据。在这里,大部分用户喜欢将Grafana与Prometheus配合使用,因为Prometheus自带的UI界面太过简陋,而Grafana提供的界面非常的美观,且可以长期保留。

话休繁绪,跑一个测试看看
Prometheus的官方下载地址为 https://prometheus.io/download/
我们另起一个ssh连接到服务器,选择一个版本下载并启动

cd /opt
sudo wget https://github.com/prometheus/prometheus/releases/download/v2.6.0/prometheus-2.6.0.linux-amd64.tar.gz
sudo tar -zxvf prometheus-2.6.0.linux-amd64.tar.gz
cd prometheus-2.6.0.linux-amd64/

编辑配置文件sudo vim prometheus.yml在scrape_configs栏添加如下配置

  - job_name: "node"
    static_configs:
    - targets: ["localhost:9100"]

此时的配置文件加上原来已经默认存在的,如下(可能因为版本不同而不同):


#my global config
global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  #scrape_timeout is set to the global default (10s).

#Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      #- alertmanager:9093

#Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  #- "first_rules.yml"
  #- "second_rules.yml"

#A scrape configuration containing exactly one endpoint to scrape:
#Here it's Prometheus itself.
scrape_configs:
  #The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

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

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


  - job_name: "node"
    static_configs:
    - targets: ["localhost:9100"]

yaml文件要尤其注意缩颈,这里我默认你已经懂得了yaml文件的规则。
启动Prometheus

sudo ./prometheus

此时Prometheus的输出如下

level=info ts=2018-12-29T08:51:26.126230419Z caller=main.go:243 msg="Starting Prometheus" version="(version=2.6.0, branch=HEAD, revision=dbd1d58c894775c0788470944b818cc724f550fb)"
level=info ts=2018-12-29T08:51:26.126302838Z caller=main.go:244 build_context="(go=go1.11.3, user=root@bf5760470f13, date=20181217-15:14:46)"
level=info ts=2018-12-29T08:51:26.126419034Z caller=main.go:245 host_details="(Linux 4.4.0-132-generic #158-Ubuntu SMP Thu Aug 2 09:08:04 UTC 2018 x86_64 master1 (none))"
level=info ts=2018-12-29T08:51:26.126497022Z caller=main.go:246 fd_limits="(soft=1000000, hard=1000000)"
level=info ts=2018-12-29T08:51:26.126567171Z caller=main.go:247 vm_limits="(soft=unlimited, hard=unlimited)"
level=info ts=2018-12-29T08:51:26.127332045Z caller=main.go:561 msg="Starting TSDB ..."
level=info ts=2018-12-29T08:51:26.127414745Z caller=web.go:429 component=web msg="Start listening for connections" address=0.0.0.0:9090
level=info ts=2018-12-29T08:51:26.135164421Z caller=main.go:571 msg="TSDB started"
level=info ts=2018-12-29T08:51:26.135204665Z caller=main.go:631 msg="Loading configuration file" filename=prometheus.yml
level=info ts=2018-12-29T08:51:26.136207062Z caller=main.go:657 msg="Completed loading of configuration file" filename=prometheus.yml
level=info ts=2018-12-29T08:51:26.136232588Z caller=main.go:530 msg="Server is ready to receive web requests."

最后一行显示Server is ready to receive web requests.,也就是服务已经准备好了。我们访问链接
http://10.19.70.139:9090
在首页可以看到Prometheus自带的UI界面如下

image.png

从界面中可以看到,标题栏Graph链接到图形查询界面,在输入框中允许输入查询语句,点击execute执行,insert metric at cursor下拉列表中列举了当前所有的存在的指标可以不用输入而直接选择。
往下,默认的console栏表示查询结果以文字的形式显示,而Graph栏表示绘制图表。
我们试一下,在输入框中输入先前的指标名node_cpu_seconds_total单机Execute。
可以看到很多指标被列举了出来

image.png

为了更精确的查询,我们输入node_cpu_seconds_total{cpu="0",mode="idle"}
可以看到很精确的查询结果被展示出来

node_cpu_seconds_total{cpu="0",instance="localhost:9100",job="node",mode="idle"}     1420025.1

为了方便我直接拷贝出来了,可以看到,指标新增了很多的标签
比如instance就表示IP地址和端口号,是配置文件中输入的
点击Graph查看图形


image.png

可以看到图形一直处于增长状态,这是合理的,因为他是counter类型,而且我们还没有做任何运算。

这个图本身对开发者或者用户而言并没有什么作用可言,但是想象一下,如果我们截取每一分钟内变化的数据,将其除以60秒,是否可以得到每秒中CPU0空闲率。这么理解,如果在某段时间计算出来的值越高,则说明CPU0的使用率越低,而数值越低,说明CPU0利用率越高,也就是越繁忙。
在搜索栏键入rate(node_cpu_seconds_total{cpu="0",mode="idle"}[1m])
这段的意思为选取1分钟内的数据的差值以60秒,rate函数就是用来做这个事情的。
得到以下图形

image.png

可以看出,我这台服务器的CPU0一直还是比较闲的
当然也可以使用稍微复杂一点的公式计算出整个CPU的工作状态
键入
(((count(count(node_cpu_seconds_total) by (cpu))) - avg(sum by (mode)(irate(node_cpu_seconds_total{mode='idle'}[5m])))) * 100) / count(count(node_cpu_seconds_total) by (cpu))

image.png

这段查询语句表示计算出CPU所有核数的busy状态总和在整个CPU时间的占比。从图中可以看到CPU时而忙碌时而悠闲。

在targets面板,我们可以查看所有配置,如果该配置能够成功拉取数据,则为状态为绿色UP,否则为红色DOWN。如果配置了alert规则,还可以在Alert面板查看到他们。
我这里就不一一演示了。


image.png
配置、存储、图表与告警

现在我们已经可以利用Prometheus进行数据拉取,并且绘制图形了,但是对于生产环境中面临的情况来说,完全不够。我们要可配置、可存储、随时查看图表、指定阈值告警等等。

为了与本机环境隔离,我将使用docker进行后续的演示,在这里我默认你已有了docker的基本知识以及可以使用docker-compose进行服务编排。

为了长期存储,我们需要指定Prometheus的存储目录
为了绘图与保留图形以便二次查看,我们引入Grafana作为仪表板
对于告警,由于Prometheus自带的告警配置相对复杂,这里我使用了Grafana所提供的告警,它的告警很简单,所见即所得,拖动滑块就可以配置阈值。

关闭先前启动的prometheus
(测试的时候我换了虚拟机,可能后续IP地址会有变化)
在/opt目录下建立配置目录,为方便操作我切换到管理员权限

sudo su
cd /opt
mkdir -p prometheus/config/
mkdir -p grafana/data
chmod 777 grafana/data
mkdir -p /data/prometheus
chmod 777 /data/prometheus

编辑docker-compose.yml文件并键入

version: '2'

networks:
  monitor:
    driver: bridge

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    hostname: prometheus
    restart: always
    volumes:
      - /opt/prometheus/config:/etc/prometheus
      - /data/prometheus:/prometheus
    ports:
      - "9090:9090"
    expose:
      - "8086"
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--log.level=info'
      - '--web.listen-address=0.0.0.0:9090'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention=15d'
      - '--query.max-concurrency=50'
    networks:
      - monitor

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    hostname: grafana
    restart: always
    volumes:
      - /opt/grafana/data:/var/lib/grafana
    ports:
      - "3000:3000"
      - "25:25"
    networks:
      - monitor
    depends_on:
      - prometheus

拷贝先前的配置文件prometheus.yml到/opt/prometheus/config目录下并替换所有localhost为IP地址。
运行docker-compose up启动容器
此时可以看到docker-compose打印的日志部分如下

prometheus    | level=info ts=2019-01-28T03:43:24.580746431Z caller=web.go:429 component=web msg="Start listening for connections" address=0.0.0.0:9090
grafana       | t=2019-01-28T03:43:25+0000 lvl=info msg="HTTP Server Listen" logger=http.server address=0.0.0.0:3000 protocol=http subUrl= socket=

为了确保Prometheus可以顺利拉取node_exporter上的数据,我们仍需要检查下它的UI界面,访问http://192.168.112.129:9090/targets,选择targets。

image.png

如下图,status为UP,点击前面的URL可以顺利访问到详细信息则表示OK。

此时访问http://10.19.70.139:3000/就可以看到Grafana的登录界面

image.png

初始密码admin/admin

那么什么是Grafana

Grafana是一个跨平台的开源的度量分析和可视化工具,可以通过将采集的数据查询然后可视化的展示,并及时通知。它主要有以下六大特点:
1、展示方式:快速灵活的客户端图表,面板插件有许多不同方式的可视化指标和日志,官方库中具有丰富的仪表盘插件,比如热图、折线图、图表等多种展示方式;
2、数据源:Graphite,InfluxDB,OpenTSDB,Prometheus,Elasticsearch,CloudWatch和KairosDB等;
3、通知提醒:以可视方式定义最重要指标的警报规则,Grafana将不断计算并发送通知,在数据达到阈值时通过Slack、PagerDuty等获得通知;
4、混合展示:在同一图表中混合使用不同的数据源,可以基于每个查询指定数据源,甚至自定义数据源;
5、注释:使用来自不同数据源的丰富事件注释图表,将鼠标悬停在事件上会显示完整的事件元数据和标记;
6、过滤器:Ad-hoc过滤器允许动态创建新的键/值过滤器,这些过滤器会自动应用于使用该数据源的所有查询。

注:偷个懒,上面这段Grafana的介绍来自别人的博文可视化工具Grafana:简介及安装,有兴趣可以看看。

进入初始界面之后会看到这样的家目录

image.png

稍作解释,中间的一栏
Install Grafana、Add data source、Create your first dashboard等等是操作流程,表示已经完成了哪些操作以及进度,从左往右。

添加数据源
点击 Add data source,选择Prometheus,在URL输入框键入http://192.168.112.129:9090,点击save & test,如果出现下图中的绿色提示,则表示配置有效,否则可能是地址或者端口等其他错误,需要自行修改。

image.png

点击左侧的Home回到家目录

image.png

接下来是create一个Dashboard,这里,如果需要自定义一些图表,则可以手动添加。然而我们的node_exporter是开源的项目,而且也有他的开源的对应的图表,那么我们可以直接使用开源的图表以简化操作。现在我们来看看如何搜索和添加开源的图表。(对于很多需要监控的应用比如mysql、kafka等等,都可以去网上寻找开源的exporter和相应的dashboard图表,比如Prometheus的开源地址,【Default port allocations】)
单机左上角的Home

image.png

选择搜索功能
我们选择数据源为Prometheus并键入node_exporter使用Enter键开始搜索。

image.png

从搜索结果中选择一条,比如第一条,单机

image.png

界面中可以看到关于这个图表的简介,点击copy它的ID。

回到原先的Home界面,选择import dashboard


image.png
image.png

在Grafana.com Dashboard栏粘贴先前拷贝的ID
它会自动识别出dashboard的相关信息


image.png

我们需要选择它的数据源,这里是Prometheus,然后Import即可
在这个面板上,Name可以修改为自己想要的,Folder可以对该dashboard分类存放,其他也可以看到作者信息等。

添加完毕会自动来到dashboard页面【该dashboard需要node_exporter0.16以上版本,如果不是可以更换node_exporter版本或者选择其他dashboard】
在这里,我重新挑选了一个ID为5174的dashboard这是我最喜欢的的node_exporter版本。
import之后,在主界面此时并没有图像显示出来。点击右上角的设置,选择Variables

image.png

选择第一行 $node ,替换node_boot_time_secondsup,此时可以在最下方看到配置的主机IP地址,也有可能是localhost,最后选择Update

image.png
image.png

依葫芦画瓢,替换$port ,中的参数为label_values(up, instance)
这里注意一点,$port的编辑界面中,Hide参数先选择为空(如果默认为variable的话),否则port参数在主界面就看不到了。
点击左侧save之后,选择回到dashboard主界面。
此时,node_exporter的数据就以图表的形式展示出来了。

image.png

将系统指标以图形的形式展示出来,这无疑是有趣且实用的。
现在依然有一些问题
比如Prometheus的存储数据库默认只保留15天的数据,Grafana存储的配置以及图表都还在容器之中它自己生成的sqlit数据库中长期存储并不友好。

为了更适应老板的需求,我们可以添加时序数据库InfluxDB作为后端存储,可以修改grafana的存储为mysql以便自己做一些自定义操作的时候方便一点,添加pushgateway接收来自脚本推送的指标。这时我们的yml文件可以是这个样子的.

version: '2'

networks:
  monitor:
    driver: bridge

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    hostname: prometheus
    restart: always
    volumes:
      - /home/ubuntu/monitors/prometheus/config:/etc/prometheus
      - /data/monitors/prometheus_data:/prometheus
    ports:
      - "9090:9090"
    expose:
      - "8086"
    depends_on:
      - influxdb
    #environment:
      #- storage.tsdb.retention=168h0m0s
      #- storage.tsdb.retention=15d
      #- log.level=debug
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--log.level=info'
      - '--web.listen-address=0.0.0.0:9090'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention=15d'
      - '--query.max-concurrency=50'
    logging:
      driver: "json-file"
      options:
        max-size: "1g"
    networks:
      - monitor

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    hostname: grafana
    restart: always
    volumes:
      - /home/ubuntu/monitors/grafana/config:/etc/grafana
      - /home/ubuntu/monitors/grafana/logs:/var/log/grafana
      - /home/ubuntu/monitors/grafana/data:/var/lib/grafana
      - /home/ubuntu/monitors/grafana/dashboards:/etc/grafana/provisioning/dashboards
    ports:
      - "3000:3000"
      - "25:25"
      - "465:465"
    user: "104"
    networks:
      - monitor
    depends_on:
      - db

  db:
    image: mysql:5.7
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
    hostname: mysql
    restart: always
    volumes:
      - /home/ubuntu/monitors/mysql/config:/etc/mysql
      - /home/ubuntu/monitors/mysql/data:/var/lib/mysql
      - /home/ubuntu/monitors/mysql/log:/var/log/mysql
    networks:
      - monitor

  pushgateway:
    image: prom/pushgateway:latest
    container_name: pushgateway
    hostname: pushgateway
    restart: always
    ports:
      - "9091:9091"
    networks:
      - monitor

  influxdb:
    image: influxdb:latest
    container_name: influxdb
    hostname: influxdb
    restart: always
    volumes:
      - /home/ubuntu/monitors/influxdb/config:/etc/influxdb
      - /data/monitors/influxdb/data:/root/.influxdb
    #command: -config /etc/influxdb/influxdb.conf
    ports:
      - "8086:8086"
      - "8083:8083"
    expose:
      - "8086"
    environment:
      - INFLUXDB_DB=prometheus
      - INFLUXDB_ADMIN_ENABLED=true
      - INFLUXDB_ADMIN_USER=admin
      - INFLUXDB_ADMIN_PASSWORD=admin
      - INFLUXDB_USER=prom
      - INFLUXDB_USER_PASSWORD=prom
      - INFLUXDB_CONFIG_PATH=/etc/influxdb/influxdb.conf
    networks:
      - monitor
    logging:
      driver: "json-file"
      options:
        max-size: "1g"


从文件描述中可以看出,我重新指定了Prometheus的存储数据库为InfluxDB,指定Grafana存储图表的数据库为熟悉的MySQL,设置日志不超过1G等,当然,这些也需要Prometheus和Grafana的配合。
在Prometheus的配置文件中,添加远程读写。

scrape_configs:
  - job_name: mx-discovery
    file_sd_configs:
      - files:
        - '/etc/prometheus/fileconfig/mx-nodes.json'


remote_write:
  - url: "http://influxdb:8086/api/v1/prom/write?db=prometheus&u=prom&p=prom"
remote_read:
  - url: "http://influxdb:8086/api/v1/prom/read?db=prometheus&u=prom&p=prom"

file_sd_configs表示启动prometheus的文件发现功能。也就是说,可以将配置主机等信息写入文件中,如果用户修改了配置,比如增加或删除了某些主机,那么Prometheus会自动发现这些更改而不用每次reload甚至重启。

所以文件可以是这样的


[
    {
        "targets": ["192.168.1.8:9100"],
        "labels": {
            "alias": "test1",
            "job": "node"
        }
    },
    {
        "targets": ["192.168.1.9:9100"],
        "labels": {
            "alias": "test2",
            "job": "node"
        }
    }
]

还有Grafana的配置(如果找不到配置,或者容器无法将配置映射出来,那么直接进入容器拷贝一份出来即可)

[database]
# You can configure the database connection by specifying type, host, name, user and password
# as separate properties or as on string using the url properties.

type = mysql
host = mysql:3306
name = grafana
user = grafana
password =grafana
url = mysql://grafana:grafana@mysql:3306/grafana

[session]
# Either "memory", "file", "redis", "mysql", "postgres", default is "file"
#provider = file
provider = mysql
provider_config = `grafana:grafana@tcp(mysql:3306)/grafana`

关于了解入门,我就只介绍这么多了,更多的可以参考官网或者其他一些更专业的博文。
附录

Prometheus官方文档英文
Grafana官方文档英文
prometheus + grafana安装部署(centos6.8)
Prometheus入门与实践
全面学习Prometheus
Prometheus 非官方中文手册
Prometheus实战
Prometheus-book
大米哥-Prometheus普罗米修斯监控-合集专题付费视频专题
Grafana的一些实用技巧
Prometheus:Up & Running这本书对Prometheus介绍的很系统,可以用来学习提高,也可以用来当工具书,不过也是英文的,国内是可以下载到的。(我放的这个地址注册后可以免费看几天,作为了解)。

监控系统