使用 Prometheus 和 Grafana 监控自己的 Linux 机器

最近在研究如何给应用添加合适的 Metrics,用来分析应用的使用情况以及调试,整体思路是使用 Prometheus 收集数据,Grafana 进行数据的展示。过程中发现了 node-exporter 项目,觉得可以直接拿来监控自己平时使用的 Linux 机器,就有了这篇文章。

整个系统使用了三个组件:

  • node-exporter:运行在主机上收集操作系统上各种数据的 Agent,Prometheus 中称为 exporter
  • Prometheus:开源的时序数据库,作为数据存储和分析的中心
  • Grafana:数据展示分析界面,提供各种强大的 Dashboard,可以从多个数据源读取数据,其中就包括 Prometheus

NOTE:所有的服务都是通过 Docker 启动的,需要安装 Docker 和 docker-compose,并熟悉它们的使用。

安装配置 Prometheus

Prometheus 最早是 SoundCloud 开发的一款时序数据库,用来作为 Metrics 数据收集和存储,目前已经成为 CNCF 基金会下面的一个项目,也是 Kubernetes 官方推荐的 Metrics 收集和监控工具。

首先,我们创建一个 docker-compose.yml 文件,里面只包含 Prometheus 一个服务:

version: '2'

services:

prometheus:

image: prom/prometheus:v2.0.0

volumes:

  - ./prometheus.yml:/etc/prometheus/prometheus.yml

command:

  - '--config.file=/etc/prometheus/prometheus.yml'

ports:

  - '9090:9090'

如果对 Docker 和 docker-compose 熟悉的话,上面的内容容易理解:

  • image 后面指定了使用的 Prometheus 容器镜像,该文件使用的是 v2.0.0 版本
  • volumes 把当前目录下面的 prometheus.yml 文件挂载到容器里,这样是因为后面会一直修改这个文件,利用 Volume 挂载的方式比较灵活
  • command 指定了 Prometheus 运行的命令行参数,这里只指定配置文件的位置,更多参数可以使用 –help 来查看
  • ports 把 Prometheus 服务监听的端口映射到主机上,这样可以直接访问主机端口使用它

其中比较重要的是 prometheus.yml 文件,它的内容如下:

global:

scrape_interval: 5s

external_labels:

    monitor: 'my-monitor'

scrape_configs:

- job_name: 'prometheus'

  static_configs:

      - targets: ['localhost:9090']

这个配置文件一共分为两个部分:global 和 scrape_configs,前者是全局的配置,如果后面的任务没有对特定配置项进行覆盖,这里的选项会生效。这里有两个配置项,scrape_interval 表示 Prometheus Server 抓取的周期,如果太频繁会导致 Prometheus 压力比较大,如果太久,可能会导致某些关键数据漏掉,推荐根据每个任务的重要性和集群规模分别进行配置。

scrape_configs 配置了每个抓取任务,因此是一个列表,这里我们只有一个任务,那就是抓取 Prometheus 本身的 Metrics。配置里面最重要的是 static_configs.targets,表示要抓取任务的 HTTP 地址,默认会在 /metrics url 出进行抓取,比如这里就是 http://localhost:9090/ 。 这是 Prometheus 本身提供的监控数据,可以在浏览器中直接查看。

每个数据都是有一个名字和一系列称为 Label 的键值对组成的,Prometheus 在抓取数据的时候还会自动添加上 instance(节点的 host:port 标识) 和 Job(任务名称) 两个 Label 作为任务之间的区分。

这些数据本身没有时间信息,当 Prometheus 抓取的时候会自动添加上当时的时间戳。此外这些数据在客户端会分成四种不同的类型:Counter、Gauge、Histogram 和 Summary。更多关于 Prometheus Metrics 数据类型的说明请查阅官方文档。

运行 docker-compose up -d 启动服务,然后在浏览器中打开 http://server-ip:9090/status 查看 Prometheus 运行的状态信息:

整个 Prometheus 体系的工作原理如下所示:

  • Prometheus Server 位于中心,负责时序数据的收集、存储和查询
  • 左边是数据来源,Prometheus 统一采用拉取的模式(pull mode)从兼容的 HTTP 接口处获取数据,数据源可以分为三种:
    • 本身就暴露 Prometheus 可读取 Metrics 数据的或者专门为某个组件编写的 exporter,称为 Jobs 或者 Exporters,比如 node exporter,HAProxy、Nginx、MySQL 等服务的 exporter
    • 通过 push gateway 可以把原来 push 类型的数据转换成 pull 类型
    • 其他 Prometheus Server
  • 上面是目标自动发现机制。对于生产的很多情况,手动配置所有的 Metrics 来源可能会非常繁琐,所以 Prometheus 支持 DNS、Kubernetes、Consul 等服务发现机制来动态地获取目标源进行数据抓取
  • 右下方是数据输出,一般是用来进行 UI 展示,可以使用 Grafana 等开源方案,也可以直接读取 Prometheus 的接口进行自主开发
  • 右上方是告警部分,用户需要配置告警规则,一旦 alertManager 发现监控数据匹配告警规则,就把告警信息通过邮件、社交账号发送出去

使用 Node Exporter 收集监控数据

虽然监控 Prometheus 服务自身是件有趣而且有用的事情,但是我们的目标是监控 linux 主机。因为 Prometheus 只能从 HTTP 接口的某个地址来拉取监控数据,因此需要一个工具把 Linux 提供的系统数据以 HTTP 服务的形式暴露出来。庆幸的是,Prometheus 官方社区有很多 Exporter,它们负责把某个组件或者系统的监控数据以 Prometheus 能理解的方式暴露出来,其中 Node Exporter 就是导出 Unix/Linux 系统监控数据的工具。

Grafana 主要是从 /proc 中读取 Linux 提供的各种数据,修改 docker-compose.yml 文件,添加上 node-exporter 相关的内容,node-exporter 默认会监听在 9100 端口:

version: '2'

services:

prometheus:

image: prom/prometheus:v2.0.0

volumes:

  - ./prometheus.yml:/etc/prometheus/prometheus.yml

command:

  - '--config.file=/etc/prometheus/prometheus.yml'

ports:

  - '9090:9090'

node-exporter:

image: prom/node-exporter:v0.15.2

ports:

  - '9100:9100'

为了让 Prometheus 收集 node-exporter 的内容,我们需要在配置文件中加上一个单独的任务:

global:

scrape_interval: 5s

external_labels:

    monitor: 'my-monitor'

scrape_configs:

- job_name: 'prometheus'

  static_configs:

      - targets: ['localhost:9090']

- job_name: 'node resources'

  scrape_interval: 10s

  static_configs:

    - targets:

      - 'node-exporter:9100'

因为 docker-compose 会自动做服务到 IP 地址的解析,因此这里可以直接使用 node-exporter:9100 作为地址。

再次运行,确认 Prometheus 中 targets 列表中有 node-exporter。

安装配置 Grafana

Prometheus 自带的 Web 界面可以用来查询配置内容、监控节点是否运行正常,也可以用来查询某个 Metric 的数值,以及提供简单的图形化功能。但是它的图形化功能比较单一, 当有很多数据要同时进行展示时,就需要借助更强大的 Dashboard 工具,比如这里要介绍的 Grafana。

Grafana 是一款强大的 Dashboard 工具,界面设计很好看,功能强大,可配置性非常灵活。

同样,在 docker-compose.yml 文件中加入 Grafana 服务:

version: '2'

services:

prometheus:

image: prom/prometheus:v2.0.0

volumes:

  - ./prometheus.yml:/etc/prometheus/prometheus.yml

  - prometheus_data:/prometheus

command:

  - '--config.file=/etc/prometheus/prometheus.yml'

ports:

  - '9090:9090'

node-exporter:

image: prom/node-exporter:v0.15.2

ports:

  - '9100:9100'

grafana:

image: grafana/grafana:4.6.2

volumes:

    - grafana_data:/var/lib/grafana

environment:

  - GF_SECURITY_ADMIN_PASSWORD=pass

depends_on:

  - prometheus

ports:

  - '3000:3000'

volumes:

grafana_data: {}

prometheus_data: {} 

这里使用 Docker 的 volumes 来保存 Grafana 和 Prometheus 运行过程中产生的数据来保证持久化,而且使用 GF_SECURITY_ADMIN_PASSWORD=pass 环境变量设置 admin 的密码。

docker-compose 运行之后,Grafana 会运行在 http://host-ip:3000 地址,使用浏览器打开会出现登陆页面,输入用户名和刚才配置的密码进入服务。

Grafana 本身只是一个 Dashboard,它可以从多个数据源(时序数据库)中获取数据进行展示,比如我们这里使用的 Prometheus。所以在正式配置界面之前,需要先添加数据源,点击 Grafana 左上角按钮找到 Data Sources 页面或者直接输入 http://host-ip:3000/datasources 地址,会进入对应页面。按照下面的内容进行填写,主要是 Type 要选择 Prometheus,URL 添加 Grafana 服务能访问的 Prometheus 地址(因为它们都是通过 docker-compose 运行的,所以这里可以直接使用名字来标识);Name 字段随便填写一个用来标记来源的名字即可。

然后创建一个 Dashboard,并里面添加 Graph(为了简单,我用了 test dashboard 这个名字),在 Graph 中添加一个 panel,我们用这个 panel 展示系统的 load 数据。编辑 panel 数据,选择 data source 为之前添加的 Prometheus,然后填写 query,系统 node 比较简单,一共是 node_load1、node_load5 和 node_load15,分别是系统最近一分钟、五分钟和十五分钟的 load 数值。输入完成后点击输入框之外,Grafana 会自动更新上面的图表:

类似的,可以添加其他的 panel,展示系统方方面的监控数据,比如 CPU、memory、IO、网络等。Grafana 更多配置可以参考 官方文档 ,选择合适的图表来展示想要的结果。

手动通过界面对 Grafana 可以很灵活地创建出很强大的图表,但是这无疑会耗费很多时间(想想,每次搭建 Grafana 都要重新做一遍),而且 node exporter 这种监控数据是通用的,如果所有人都手动创建一遍无疑是很多重复工作。为此,Grafana 支持导入和导出配置,并且提供 官方社区 供大家分享 Dashboard 配置。

每个 Dashboard 都有一个编号,比如 编号 22 的 Dashboard 就是专门为 node-exporter 设计的展示图表。在 Grafana 中点击导入 Dashboard,添加编号选择数据源,就能得到已经配置完整的图表:

如果对 Dashboard 有什么不满,可以直接在页面进行添加和编辑,然后可以导出 json 文件,以便重复使用。

配置告警

通过 Grafana 图表我们可以知道系统各种指标随着时间的变化,方便轻松判断系统某个资源是否异常。但是我们不能一直盯着 Dashboard,还需要系统发生异常的时候能立即通过邮件或者其他方式通知我们,这就是告警的功能。

Prometheus 提供用户可以自己配置的告警规则,在处理 Metrics 数据的时候,如果发现某个规则被触发,就执行对应的告警动作,通过发邮件或者其他方式通知用户。

对于我们的单节点主机来说,可以定义两个简单的告警规则:当主机 download 掉,或者 CPU load 持续过高一段时间就发送告警。对此,需要新建一个 alert.rules 文件,用来保存告警规则,按照需求对应的内容如下:

➜  monitor git:(master) ✗ cat alert.rules

groups:

- name: node-alert

rules:

- alert: service_down

expr: up == 0

for: 2m

- alert: high_load

expr: node_load1 > 0.5

for: 5m

在启动 Prometheus 服务的时候把告警规则文件 mount 到 Pod 中,如下添加一个 volume:

➜  monitor git:(master) ✗ cat docker-compose.yml

version: '2'

services:

prometheus:

image: prom/prometheus:v2.0.0

volumes:

  - ./prometheus.yml:/etc/prometheus/prometheus.yml

  - ./alert.rules:/etc/prometheus/alert.rules

......

然后,告知 promethues 加载这些规则:

➜ monitor git:(master) ✗ cat prometheus.yml

……

rule_files:

– ‘alert.rules’}}}

为了验证告警规则是否生效,可以把 node-exporter 服务停掉:

docker-compose stop node-exporter

在 Prometheus 的告警页面(alert)查看告警:

类似地,可以运行一些消耗 CPU 资源的服务来触发系统 load 过高的告警规则,比如运行下面这个 Docker 容器(一直 while 循环霸占 CPU 资源可以轻松把 CPU load 提到很高):

docker run --rm -it busybox sh -c "while true; do :; done"

Prometheus 还提供了 Alertmanager 可以自动化根据告警规则触发对应的动作,一般是各种方式通知用户和管理员,这里就不再介绍了。

总结

本文中使用的完整配置文件放到了 GitHub 上,可以作为参考。

需要注意的是,这只是一个本地的 test 环境,不能直接在生产上使用。首先我们没有配置安全访问,所有的服务都是 HTTP;其次 docker-compose 运行的话,所有的服务都是在同一台机器上,无法做到分布式监控和高可用。

如果想在生产中使用 Prometheus 和 Grafana,请参考官方文档。

参考资料:

原文链接: