一、什么是Prometheus

Prometheus(普罗米修斯)是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB)。Prometheus使用Go语言开发,是Google BorgMon监控系统的开源版本。
2012年成为社区开源项目,拥有非常活跃的开发人员和用户社区。
2016年由Google发起Linux基金会旗下的原生云基金会(Cloud Native Computing Foundation), 将Prometheus纳入其下第二大开源项目。
Prometheus目前在开源社区相当活跃。
Prometheus和Heapster(Heapster是K8S的一个子项目,用于获取集群的性能数据。)相比功能更完善、更全面。Prometheus性能也足够支撑上万台规模的集群。

二、Prometheus的特点

  • 多维度数据模型。
  • 灵活的查询语言。
  • 不依赖分布式存储,单个服务器节点是自主的。
  • 通过基于HTTP的pull方式采集时序数据。
  • 可以通过中间网关进行时序列数据推送。
  • 通过服务发现或者静态配置来发现目标服务对象。
  • 支持多种多样的图表和界面展示,比如Grafana等。

先简单看一眼 Prometheus的整体框架图

三、Prometheus + Grafana 的个数据监控采集成图

Prometheus 由多个组件组成,但是其中许多组件是可选的

  • Prometheus Server用于收集指标和存储时间序列数据,并提供查询接口
  • client Library客户端库(例如Go,Python,Java等),为需要监控的服务产生相应的/metrics并暴露给Prometheus Server。目前已经有很多的软件原生就支持Prometheus,提供/metrics,可以直接使用。对于像操作系统已经不提供/metrics,可以使用exporter,或者自己开发exporter来提供/metrics服务。
  • push gateway主要用于临时性的 jobs。由于这类 jobs 存在时间较短,可能在 Prometheus 来 pull 之前就消失了。对此Jobs定时将指标push到pushgateway,再由Prometheus Server从Pushgateway上pull。

这种方式主要用于服务层面的 metrics

  • exporter用于暴露已有的第三方服务的 metrics 给 Prometheus。
  • alertmanager从 Prometheus server 端接收到 alerts 后,会进行去除重复数据,分组,并路由到对收的接受方式,发出报警。常见的接收方式有:电子邮件,pagerduty,OpsGenie, webhook 等。
  • Web UIPrometheus内置一个简单的Web控制台,可以查询指标,查看配置信息或者Service Discovery等,实际工作中,查看指标或者创建仪表盘通常使用Grafana,Prometheus作为Grafana的数据源。

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

四、基本原理

Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。

五、服务过程

  • Prometheus Daemon负责定时去目标上抓取metrics(指标)数据,每个抓取目标需要暴露一个http服务的接口给它定时抓取。Prometheus支持通过配置文件、文本文件、Zookeeper、Consul、DNS SRV Lookup等方式指定抓取目标。Prometheus采用PULL的方式进行监控,即服务器可以直接通过目标PULL数据或者间接地通过中间网关来Push数据。
  • Prometheus在本地存储抓取的所有数据,并通过一定规则进行清理和整理数据,并把得到的结果存储到新的时间序列中。
  • Prometheus通过PromQL和其他API可视化地展示收集的数据。Prometheus支持很多方式的图表可视化,例如Grafana、自带的Promdash以及自身提供的模版引擎等等。Prometheus还提供HTTP API的查询方式,自定义所需要的输出。
  • PushGateway支持Client主动推送metrics到PushGateway,而Prometheus只是定时去Gateway上抓取数据。
  • Alertmanager是独立于Prometheus的一个组件,可以支持Prometheus的查询语句,提供十分灵活的报警方式。

六、三大套件

  • Server 主要负责数据采集和存储,提供PromQL查询语言的支持。
  • Alertmanager 警告管理器,用来进行报警。
  • Push Gateway 支持临时性Job主动推送指标的中间网关。

七、报警

报警跟监控严格来说是需要分开对待的,因为报警也有专门的报警系统。报警系统 包括几种主要的展现形式:短信报警,邮件报警,电话报警(语音播报), 通讯软件。不像监控系统比较成型的报警系统,目前大多数都是收费的商业化。报警系统中最重要的一个概念之一就是对报警阈值的理解。阈值(Trigger Value) ,是监控系统中 对数据到达某一个临界值的定义。例如: 通过监控发现,当前某⼀台机器的CPU突然升高,到达了 99%的使用率,99 就是作为一次报警的触发阈值。

八、下载Prometheus

1、本地下载后上传到linux服务器

官网下载地址:https://prometheus.io/download/

2、直接在linux服务器上wget方式下载

# 新建目录
mkdir -p /data/prometheus/
# 进入目标目录
cd /data/prometheus/
# 下载
wget -c https://github.com/prometheus/prometheus/releases/download/v2.28.1/prometheus-2.28.1.linux-amd64.tar.gz
# 解压
tar -vxzf prometheus-2.28.1.linux-amd64.tar.gz
# 移动到安装目录
mv prometheus-2.28.1.linux-amd64 /usr/local/prometheus
# 进入目录
cd /usr/local/prometheus

九、将Prometheus配置为系统服务

1、进入systemd目录

cd /usr/lib/systemd/system

2、创建文件

vim prometheus.service

# 添加如下内容
[Unit]
Description=https://prometheus.io
  
[Service]
Restart=on-failure
ExecStart=/usr/local/prometheus/prometheus --config.file=/usr/local/prometheus/prometheus.yml

[Install]                      
WantedBy=multi-user.target

3、生效系统systemd文件

systemctl daemon-reload

4、启动和停止服务命令

# 启动
systemctl start prometheus.service
# 停止
systemctl stop prometheus.service

十、启动Prometheus

# 进入解压后的文件夹
cd /data/prometheus/prometheus-2.28.1.linux-amd64
# 前台启动
./prometheus --config.file=prometheus.yml
# 后台启动prometheus,并且重定向输入日志到当前目录的prometheus.out
nohup ./prometheus --config.file=prometheus.yml >> /data/prometheus/prometheus-2.28.1.linux-amd64/prometheus.out 2>&1 &

访问prometheus

http:192.168.0.102:9090,默认端口为 9090

十一、避坑指南

安装好 prometheus 以后,访问的默认端口号是 9090,但是当 9090 端口被占用了怎么处理?

命令行启动

如果要使用不同于9090的端口号,可以在命令行参数 --web.listen-address 中指定,如:

./prometheus --config.file=prometheus.yml --web.listen-address=:9091
# 后台启动命令一样

服务方式启动

安装完成以后,也可以把 prometheus 配置成自启动的服务,在其中的配置文件中也可以自定义prometheus的启动端口。步骤如下:

1. 在 /etc/systemd/system 目录下创建新文件 prometheus.service,其中 ExecStart 字段指定启动参数时,设置自定义端口,内容如下:

 --web.listen-address=:9091

[Unit]
Description=Prometheus Monitoring System
Documentation=Prometheus Monitoring System
 
[Service]
ExecStart=/opt/proe/prometheus-2.3.1.linux-amd64/prometheus \
  --config.file=/opt/proe/prometheus-2.3.1.linux-amd64/prometheus.yml --web.enable-admin-api \
  --web.listen-address=:9091
 
[Install]
WantedBy=multi-user.target

 2. 执行命令:

systemctl start prometheus.service

如果 prometheus 在运行,有时候要执行如下命令:

systemctl daemon-reload

3. 验证 prometheus 是否在新端口正常启动:

# 输入如下命令:
netstat -lnpt | grep prometheus

十二、prometheus.yml解读

# 此片段指定的是prometheus的全局配置,比如采集间隔,抓取超时时间等。如果有内部单独设定,会覆盖这个参数。
global:
  scrape_interval:     15s # 抓取间隔,默认继承global值(默认15s 全局每次数据收集的间隔)
  evaluation_interval: 15s # 评估规则间隔(规则扫描时间间隔是15秒,默认不填写是1分钟)
  # scrape_timeout 抓取超时时间,默认继承global值。

# 此片段指定告警配置,这里会设定alertmanager这个报警插件。
alerting:
  alertmanagers:
  - static_configs:
    - targets: ['localhost:9093']

# 此片段指定报警规则文件,按照设定参数进行扫描加载,用于自定义报警规则,其报警媒介和route路由由alertmanager插件实现。
rule_files:
  - "rules/*.yml"
  # - "first_rules.yml"
  # - "second_rules.yml"

# 此片段指定抓取配置。配置数据源,包含分组job_name以及具体target。又分为静态配置和服务发现。
scrape_configs:
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics' # 监控项访问的url路径
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:9090'] # 监控目标访问地址

  - job_name: 'suyuan' # 任务目标名,可以理解成分组,每个分组包含具体的target组员。
    scrape_interval: 30s # 这里如果单独设定的话,会覆盖global设定的参数,拉取时间间隔为30s
    static_configs:
    - targets: ['39.99.254.135:30101']
      labels:
        instance: 'bigdata(39.99.254.135:9000)'

    - targets: ['39.99.254.135:30102']
      labels:
        instance: 'web(39.99.254.135:9999)'

    - targets: ['39.99.254.135:30103']
      labels:
        instance: 'user(39.99.254.135:9003)'

说明:

告警配置 targets 和抓取配置 targets 的 localhost 最好替换成服务器的 ip,job_name 的名字对应的就是 grafana dashboard 的 job 的名称,instance 如果不通过 labels 单独指定,默认取的是 targets 的值,建议单独指定别名。

上述为静态规则,没有设置自动发现。这种情况下增加主机需要自行修改规则,通过 supervisor reload 对应任务,也是缺点:每次静态规则添加都要重启prometheus服务,不利于运维自动化。

prometheus支持服务发现(也是运维最佳实践经常采用的):
文件服务发现
基于文件的服务发现方式不需要依赖其他平台与第三方服务,用户只需将 要新的target信息以yaml或json文件格式添加到target文件中 ,prometheus会定期从指定文件中读取target信息并更新
好处:
(1)不需要一个一个的手工去添加到主配置文件,只需要提交到要加载目录里边的json或yaml文件就可以了;
(2)方便维护,且不需要每次都重启prometheus服务端。

动态注册

动态注册就是在Prometheus yaml文件的scrape_configs配置下配置服务发现的地址和服务名,Prometheus会去该地址,根据你提供的服务名动态发现实例列表,在Prometheus中,支持consul,DNS,文件,K8s等多种服务发现机制。基于consul的服务发现:

- job_name: "node_export_consul"
    metrics_path: /node_metrics
    scheme: http
    consul_sd_configs:
      - server: localhost:8500
        services:
          - node_exporter

我们consul的地址就是:localhost:8500,服务名是node_exporter,在这个服务下有一个exporter实例:localhost:9600。

 

注意:如果是动态注册,最好加上这两配置,静态注册指标拉取的路径会默认的帮我们指定为 metrics_path:/metrics,所以如果暴露的指标抓取路径不同或者是动态的服务注册,最好加上这两个配置。不然会报错“INVALID“ is not a valid start token,演示下,百度了一下,这里可能是数据格式不统一导致。

metrics_path: /node_metrics
scheme: http

最后可以在webUI中查看发现的实例:

 

目前,Prometheus支持多达二十多种服务发现协议:

<azure_sd_config>
<consul_sd_config>
<digitalocean_sd_config>
<docker_sd_config>
<dockerswarm_sd_config>
<dns_sd_config>
<ec2_sd_config>
<openstack_sd_config>
<file_sd_config>
<gce_sd_config>
<hetzner_sd_config>
<http_sd_config>
<kubernetes_sd_config>
<kuma_sd_config>
<lightsail_sd_config>
<linode_sd_config>
<marathon_sd_config>
<nerve_sd_config>
<serverset_sd_config>
<triton_sd_config>
<eureka_sd_config>
<scaleway_sd_config>
<static_config>

十三、配置更新

在更新完Prometheus的配置文件后,我们需要更新我们的配置到程序内存里,这里的更新方式有两种,第一种简单粗暴,就是重启Prometheus,第二种是动态更新的方式。如何实现动态的更新Prometheus配置。

步骤

第一步:首先要保证启动Prometheus的时候带上启动参数:--web.enable-lifecycle。

prometheus --config.file=/usr/local/etc/prometheus.yml --web.enable-lifecycle

第二步:去更新我们的Prometheus配置。

第三步:更新完配置后,我们可以通过POS请求的方式,动态更新配置。

curl -v --request POST 'http://localhost:9090/-/reload'

原理 

Prometheus在web模块中,注册了一个handler。

if o.EnableLifecycle {
   router.Post("/-/quit", h.quit)
   router.Put("/-/quit", h.quit)
   router.Post("/-/reload", h.reload)  // reload配置
   router.Put("/-/reload", h.reload)   
}

通过h.reload这个handler方法实现:这个handler就是往一个channle中发送一个信号。

func (h *Handler) reload(w http.ResponseWriter, r *http.Request) {
   rc := make(chan error)
   h.reloadCh <- rc    // 发送一个信号到channe了中
   if err := <-rc; err != nil {
      http.Error(w, fmt.Sprintf("failed to reload config: %s", err), http.StatusInternalServerError)
   }
}

在main函数中会去监听这个channel,只要有监听到信号,就会做配置的reload,重新将新配置加载到内存中。

case rc := <-webHandler.Reload():
   if err := reloadConfig(cfg.configFile, cfg.enableExpandExternalLabels, cfg.tsdb.EnableExemplarStorage, logger, noStepSubqueryInterval, reloaders...); err != nil {
      level.Error(logger).Log("msg", "Error reloading config", "err", err)
      rc <- err
   } else {
      rc <- nil
   }
Logo

更多推荐