美文网首页
Prometheus笔记

Prometheus笔记

作者: winlinvip | 来源:发表于2022-08-16 20:53 被阅读0次

    GitHub:prometheus

    架构图:时序数据存储,抓取数据,推送告警,提供PromQL查询数据,对接UI仪表盘,和K8s对接。

    直接本机Docker启动,然后访问本机后台:http://localhost:9090/

    docker run --name prometheus -d -p 127.0.0.1:9090:9090 prom/prometheus
    

    可以docker inspect看到它的信息:

    • 配置文件:--config.file=/etc/prometheus/prometheus.yml
    • 存储路径:--storage.tsdb.path=/prometheus

    数据模型:

    • 所有数据都是时序数据,time series
    • 时序数据可以有name和label来分类过滤,比如:
    <metric name>{<label name>=<label value>, ...}
    api_http_requests_total{method="POST", handler="/messages"}
    

    度量类型:

    • Counter:单调递增的类型,比如总人数。
    • Gauge:可增加可减少的数字,比如CPU使用率。
    • 还有Histogram和Summary,和时长以及窗口相关,没仔细看。

    任务和实例:

    • 抓取endpoint是一个实例,一般就是一个进程。
    • 多个进程组成一个任务,主要是为了扩容和可靠性。

    Docker

    配置文件规则:Configuration

    • 先启动一个node exporter:
    docker run --rm -it -p 9100:9100 prom/node-exporter
    
    • 编写Prometheus的配置文件,抓取这个配置:
    scrape_configs: 
      - job_name: "node0"
        metrics_path: "/metrics"
        scrape_interval: 5s
        static_configs:
          - targets: ["host.docker.internal:9100"] 
    
    • 以本机配置启动:
    docker run --rm -v `pwd`/prometheus.yml:/etc/prometheus/prometheus.yml \
      -p 9090:9090 prom/prometheus
    
    • 进入9090可以看到正常启动了。

    Exporter

    Exporter是无缝将现有系统接入Prometheus:链接

    Prometheus有相当广泛的exporter,其实就是各个平台和软件的插件,比如几个关键的:

    这个exporter的机制,是能广泛应用和接入的基础能力。

    Node Exporter

    主机监控的Exporter:Node/system metrics exporter

    下载二进制后直接运行:链接

    使用Docker运行,测试在Linux可以,在Mac不行:

    docker run --rm --net=host --pid=host -v "/:/host:ro,rslave" \
      prom/node-exporter --path.rootfs=/host
    

    在Darwin下,还是直接运行二进制比较好,注意还是需要允许运行会提示是恶意软件:

    ./node_exporter-1.3.1.darwin-amd64/node_exporter
    

    Darwin下测试用,也可以直接非host方式运行:

    docker run --rm -p 9100:9100 \
      ccr.ccs.tencentyun.com/ossrs/node-exporter
    

    编译执行:

    make
    ./node_exporter
    

    Prometheus配置文件prometheus.yml

    scrape_configs:
      - job_name: "node"
        metrics_path: "/metrics"
        scrape_interval: 5s
        static_configs:
          - targets: ["host.docker.internal:9100"]
    

    启动服务:

    docker run --rm -it -v `pwd`/prometheus.yml:/etc/prometheus/prometheus.yml \
      -p 9090:9090 prom/prometheus
    

    Textfile Collector

    Node Exporter可以采集文件,比如/etc/node-exporter/node-meta.prom,或者指定路径:

    mkdir node0 && echo 'machine_role{role="apache"} 1' > node0/roles.prom
    

    启动时指定采集这个目录:

    docker run --rm -it -p 9100:9100 -v $(pwd):/data -w /data \
        prom/node-exporter --collector.textfile.directory node0
    

    可以看到这个采集的数据:

    machine_role
    machine_role{instance="9100", job="node0", role="apache"} 1
    

    Lighthouse

    在LightHouse上运行Prometheus:

    docker run --rm --add-host=mgmt.srs.local:10.0.24.2 \
      -v `pwd`/prometheus.yml:/etc/prometheus/prometheus.yml \
      -p 9090:9090 ccr.ccs.tencentyun.com/ossrs/prometheus
    

    运行Node Exporter:

    docker run --rm --net=host --pid=host -v "/:/host:ro,rslave" \
      ccr.ccs.tencentyun.com/ossrs/node-exporter --path.rootfs=/host
    

    注意,若启动Prometheus时,指定了data目录,需要使用root启动docker,即--user root,否则访问失败,因为它使用特定的用户运行:

    docker run --user root --rm --add-host=mgmt.srs.local:10.0.24.2 \
      -p 9090:9090/tcp -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
      -v $(pwd)containers/data/prometheus:/prometheus \
      ccr.ccs.tencentyun.com/ossrs/prometheus
    

    BaseUrl

    可以指定Prometheus的baseUrl:链接

    启动时指定参数:

    prometheus --web.external-url http://localhost:19090/prometheus/
    

    Selectors

    Prometheus有几种数据类型,参考链接

    • Instant vector - 实时的向量,时序数据的集合,时间戳相同。只有这种类型的数据,才能被图形化。
    • Range vector - 范围向量,时序数据的集合,一定时间范围。
    • Scalar - 标量,浮点数据类型的标量。

    先看Instant vector,直接输入node_load1就是一个Instance vector,如下所示:

    node_load1
    node_load1{instance="host.docker.internal:9100", job="node0"} 2.474609375
    node_load1{instance="host.docker.internal:9102", job="node2"} 0.13
    

    Note: 所谓实时(instant),就是指定的某个时间戳;所谓时序time series,就是不同时间有不同的值;所谓向量vector,就是time series的集合。

    再看Range vector,输入时间范围,采样是5s输入30s,如下所示:

    node_load1[10s]
    node_load1{job="node0"} 1.95361328125 @1660643735.965 1.876953125 @1660643740.968
    node_load1{job="node2"} 0.46 @1660643736.352 0.42 @1660643741.351
    

    Note: 可以看到,每个time series的值是一个时间范围的数据,比如上面包含了两个采样点,采样的时间戳并不相同。这就是按时间聚合时,我们会使用的数据类型,使用不同的函数处理它。

    Operators

    操作符Operators,是针对Instant vector和Scalar之间的运算,不能用于Range vector:

    node_load1 * 100
    {instance="host.docker.internal:9100", job="node0"} 221.09375
    {instance="host.docker.internal:9102", job="node2"} 28.000
    

    对两个Instant vector相除时,他们的label要相同,比如计算网络包所占的字节数:

    node_network_receive_bytes_total{device="en0"}/node_network_receive_packets_total
    {device="en0", instance=":9100", job="node0"} 17.207300663986636
    

    Note:如果label不同就没有结果。计算结果会丢弃metric的名称,只保留匹配的label。

    也支持集合的操作,比如or将两个vector合并了,比如把load和cpu展示在一个图:

    node_load1 or node_cpu_seconds_total{cpu="0",mode="user"}
    node_load1{job="node0"} 3.33447265625
    node_load1{job="node2"} 0.66
    node_cpu_seconds_total{cpu="0", job="node0", mode="user"} 48824.2
    node_cpu_seconds_total{cpu="0", job="node2", mode="user"} 1115.41
    

    Note: 这样可以把两个指标展示在一个图中了,同时对不同的指标进行处理。是完全按label匹配,而不是按值匹配,因为两个指标的值几乎是不会相等。

    Vector maching

    Vector matching向量匹配,针对两个可能不完全相等label的向量,比如node比cpu_seconds就少了cpu和mode标签:

    node_load1{job="node0"} 3.33447265625
    node_load1{job="node2"} 0.66
    node_cpu_seconds_total{cpu="0", job="node0", mode="user"} 48824.2
    node_cpu_seconds_total{cpu="0", job="node2", mode="user"} 1115.41
    

    如果直接把两个相除,则是空,因为标签并不匹配,无法相除,这时候可以忽略掉cpu和mode,这就是一对一的匹配:

    node_cpu_seconds_total{cpu="0",mode="user"} / ignoring(cpu,mode) node_load1
    {instance="host.docker.internal:9100", job="node0"} 17082.595555555556
    {instance="host.docker.internal:9102", job="node2"} 19009.5
    

    如果我们选择两个cpu,即cpu0和1,这时候就是多对一的关系:

    node_load1 or node_cpu_seconds_total{cpu=~"0|1",mode="user"}
    node_load1{instance="host.docker.internal:9100", job="node0"} 2.92138671875
    node_load1{instance="host.docker.internal:9102", job="node2"} 0.13
    node_cpu_seconds_total{cpu="0", instance="host.docker.internal:9100", job="node0", mode="user"} 48954.11
    node_cpu_seconds_total{cpu="0", instance="host.docker.internal:9102", job="node2", mode="user"} 1141.35
    node_cpu_seconds_total{cpu="1", instance="host.docker.internal:9100", job="node0", mode="user"} 8483.03
    node_cpu_seconds_total{cpu="1", instance="host.docker.internal:9102", job="node2", mode="user"} 1148.34
    

    针对多对一的匹配运算,就不能直接相除了,而是需要加上group_left,即以左边的为基数:

    node_cpu_seconds_total{cpu=~"0|1",mode="user"} / ignoring(cpu,mode) group_left node_load1
    {cpu="0", instance=":9100", job="node0", mode="user"} 19395.831582205028
    {cpu="0", instance=":9102", job="node2", mode="user"} 12694.333333333334
    {cpu="1", instance=":9100", job="node0", mode="user"} 3360.5223984526115
    {cpu="1", instance=":9102", job="node2", mode="user"} 12772.555555555557
    

    使用的是ignore某些标签让剩下的标签相等,也可以on直接指定匹配的标签,结果也是一样的:

    node_cpu_seconds_total{cpu=~"0|1",mode="user"} / on(instance) group_left node_load1
    

    Aggregate

    Aggregatable operators聚合操作,针对Instant vector,按照某些标签聚合,比如cpu有很多标签:

    node_cpu_seconds_total{cpu=~"0|1",job="node0"}
    node_cpu_seconds_total{cpu="0", instance="host.docker.internal:9100", job="node0", mode="idle"} 250784.34
    node_cpu_seconds_total{cpu="0", instance="host.docker.internal:9100", job="node0", mode="nice"} 0
    node_cpu_seconds_total{cpu="0", instance="host.docker.internal:9100", job="node0", mode="system"} 84181.76
    node_cpu_seconds_total{cpu="0", instance="host.docker.internal:9100", job="node0", mode="user"} 49026.15
    node_cpu_seconds_total{cpu="1", instance="host.docker.internal:9100", job="node0", mode="idle"} 361174.34
    node_cpu_seconds_total{cpu="1", instance="host.docker.internal:9100", job="node0", mode="nice"} 0
    node_cpu_seconds_total{cpu="1", instance="host.docker.internal:9100", job="node0", mode="system"} 13072.18
    node_cpu_seconds_total{cpu="1", instance="host.docker.internal:9100", job="node0", mode="user" 8485.57
    

    我们可以按照mode聚合,这样就可以看到整体不同mode的数据:

    sum by(mode) (node_cpu_seconds_total{cpu=~"0|1",job="node0"})
    {mode="idle"} 612159.87
    {mode="nice"} 0
    {mode="system"}97277.25
    {mode="user"} 57527.03
    

    Functions

    Functions函数,可以对Instant vector或Range vector进行变换,比如求差值按时间的变化:

    rate(node_cpu_seconds_total{cpu="0",job="node0",mode="user"}[10s])
    {} 0.18210926555857848
    
    node_cpu_seconds_total{cpu="0",job="node0",mode="user"}[10s]
    node_cpu_seconds_total{} 49198.42@1660650581.185 49199.33@1660650586.166
    
    increase(node_cpu_seconds_total{cpu="0",job="node0",mode="user"}[10s])/10
    {} 0.18210926555857848
    

    rate的输入是Range vector,输出是Instant vector,可以对结果再进行Aggregate操作:

    sum by(instance) (rate(node_cpu_seconds_total{cpu="0",mode=~"user|system"}[10s]))
    {instance="host.docker.internal:9100"} 0.3072289156609558
    {instance="host.docker.internal:9102"} 0.02811809600318792
    

    Note: 不同函数的输入和输出参数都不同,需要看手册。

    由于Range vector每个time series也是一个集合,比如10秒的负载,包含两个采样:

    node_load1[10s]
    node_load1{job="node0"} 2.734375@1660650915.931 2.67529296875@1660650920.93
    node_load1{job="node2"} 0.29@1660650916.317 0.26@1660650921.316
    

    那么也可以对这些采样进行聚合操作,比如最大值:

    max_over_time(node_load1[10s])
    {instance="host.docker.internal:9100", job="node0"} 2.734375
    {instance="host.docker.internal:9102", job="node2"} 0.29
    

    然后再按标签进行聚合,求得系统最大的负载:

    max(max_over_time(node_load1[10s]))
    {} 2.734375
    

    Label

    关于如何打Label,相关资料如下:

    Grafana也列出了一些Exporter,可以看到示例数据:

    The USE Method

    参考The Use Method.

    For every resource, check utilization, saturation, and errors.
    

    摘要:

    • resource: 系统的资源。
    • utilization: 资源的使用率。比如CPU使用率70%。
    • saturation: 资源的饱和度,排队和过载情况。比如load,就是CPU任务排队的情况。
    • errors: 错误事件和次数。

    按照USE制作的Node Exporter大盘,参考链接

    • CPU Utilization
    • CPU Saturation (Load per CPU)
    • Memory Utilisation
    • Memory Saturation (Major Page Faults)
    • Net Utilization (Bytes Receive/Transmit)
    • Net Saturation (Drops Receive/Transmit)
    • Disk I/O Utilization
    • Disk I/O Saturation

    Metrics

    哪些指标可以作为Metric,可以根据不同系统做分类:

    • Online-serving systems在线服务器,比如SRS或API服务器,需要立刻对请求做响应的服务器。关键指标是请求数目、错误数目、请求耗时、服务器并发。应该在客户端和服务器同时采集,当两边的数据不同时会有助于分析问题;当然如果并发太高,就只能靠自己的统计系统了。一般是在请求结束时采集数据,比较方便采集错误和耗时。
    • Offline processing离线处理。离线处理就不会在线等响应,离线处理一般是批处理完成的,而且会分成很多阶段处理。关键指标是每个阶段的输入输出,多少在处理中,上次处理完的时间;对于批处理,还需要跟踪分支。当任务挂起时,知道最后任务的完成时间很重要,更好的是任务的心跳。
    • Batch jobs批处理。批处理和离线处理有时候有点混淆,因为离线处理有时候用批处理实现。批处理的关键特点是非连续性,所以很难抓取有效的指标。关键指标是最后成功的时间和结果(错误码),采集每个主要阶段的耗时也很重要。应该推送给PushGateway。任务级别的统计数据也很重要,比如处理的记录数。对于长时间运行的任务,基于pull的监控也很重要,可以度量系统的资源变化。对于频繁运行的批处理任务,比如每15分钟执行一次,转成离线处理服务会更好。

    除了这几种类型的系统,还有一些系统的部分可以采集Metric:

    • Libraries 库的指标采集,应该不需要用户配置。
    • Logging 日志的指标,应该有个总的日志数,对于某个特别的日志应该看它的频率和耗时,对于函数的某些分支也可以采集,统计不同级别的日志数量也挺有用的。
    • Failures 错误,和日志类似应该采集总数。以及总请求数,这样比较容易计算错误率。
    • Threadpools 线程池,关键指标是排队的请求数,活跃的线程数,总线程数,处理的任务和耗时,队列的等待耗时也很有用。
    • Cache 缓存,关键指标是总查询数,命中数目,延迟,错误数。
    • Collectors Prometheus的Collector,采集的耗时和错误次数。这里建议用gauge而不是histogram,另外一个用gauge的例子是批处理的耗时,这是因为它们度量的是每次的推送或抓取,而不是分散的多个耗时。

    到底该用哪种类型的指标:

    • Counter vs Gauge:能变小的是Gauge,比如占用内存大小。
    • Counter是递增的,直到进程重启会被Reset,比如处理的总请求数、总错误数、发送的总字节数。一般Counter很少能直接使用,是需要函数处理比如rate或做其他处理。
    • Gauge的值可以被设置,可以变大变小,一般是状态的快照,比如处理中的请求数,可用的内存大小,温度等,对于gauge永远不要用rate函数。
    • Summary和Histogram比较难,用得也比较少,大概是统计分布,比如耗时的分布,暂时没仔细看。

    PromQL: Counter

    Prometheus有自己的查询语句,对于Counter的例子。

    比如节点的CPU执行时间,就是Counter单增的量。可以看到,这些数据就是CPU的时间片统计,会不断递增。输入下面的语句:

    node_cpu_seconds_total
    

    可以看到各个CPU,以及不同的mode的数据,我们过滤选择第0个CPU,以及mode为user。这时候过滤出来的是CPU0的user的累计时间片:

    node_cpu_seconds_total{cpu="0",mode="user"}
    

    我们可以用rate函数计算增量的变化率,也就是user的增量的随时间的变化:

    rate(node_cpu_seconds_total{cpu="0",mode="user"}[10s])
    
    • rate(node_cpu_seconds_total{cpu="0",mode="user"}[10s]) 返回 0.162
    • increase(node_cpu_seconds_total{cpu="0",mode="user"}[10s]) 返回 1.62

    可以看到1.62 / 10s = 0.162,也就是rate=increase/duration,取的是增量和时间的比。

    Note: 注意如果采样是1m,那么时间范围就不能小于1m,否则会出现Empty query result

    PromQL: CPU percent

    计算CPU的百分比,原始数据是CPU时间,可以先计算idle时间比例:

    rate(node_cpu_seconds_total{mode="idle"}[30s])
    

    然后将多个CPU的取最小值,注意rate要再加个括号:

    min by(mode) (rate(node_cpu_seconds_total{mode="idle"}[30s]))
    

    然后将idle换成usage,也就是:

    1 - min by(mode) (rate(node_cpu_seconds_total{mode="idle"}[30s]))
    

    再乘以100,就是100%了:

    (1 - min by(mode) (rate(node_cpu_seconds_total{mode="idle"}[30s]))) * 100
    

    PromQL: min by

    取最小值时,取的是每个样本的最小值,比如两个CPU,如果取idle最小的,那是取每个样本最小的,相当于取最繁忙的那个值。

    可以写个bash的死循环:

    cat << END > min_by.sh
    for ((;;)); do echo "" >/dev/null; done
    END
    

    启动这个程序:

    bash min_by.sh
    

    然后用绑定CPU方式测试,先绑定到0,然后切到1:

    taskset -pc 0 $(ps aux|grep min_by.sh|grep bash|awk '{print $2}')
    

    看两个CPU的图,明显发现有交换:

    而用min by(mode)后,总是取idle最小的值了,这也就是系统忙的CPU图了:

    若是min by(cpu),则是按cpu分组。

    node_load1 // vector A
        * // 操作符 A.value * B.value,由于 B.value=1,我们保持A的值不变,所以用的乘
        on(instance) // JOIN on 用instance来join两个vector,A.instance==B.instance
        group_left(sysname) // 保留B的字段, 相当于 SELECT A.*, B. sysname
        node_uname_info // vector B
    

    PromQL: Regex Match

    可以选择两个CPU,用cpu=~"[01]"

    (1-rate(node_cpu_seconds_total{cpu=~"[01]",mode="idle"}[30s]))*100
    

    这就是正则表达式匹配了。

    PromQL: on

    一对一的vector匹配,将vector变换成一组,参考:One-to-one vector matches

    启动两个node:

    docker run --rm -it -p 9101:9100 prom/node-exporter
    docker run --rm -it -p 9102:9100 prom/node-exporter
    

    然后,配置Prometheus,抓取配置:

    scrape_configs: 
      - job_name: "node1"
        metrics_path: "/metrics"
        scrape_interval: 5s
        static_configs:
          - targets: ["host.docker.internal:9101"] 
      - job_name: "node2"
        metrics_path: "/metrics"
        scrape_interval: 5s
        static_configs:
          - targets: ["host.docker.internal:9102"]
    

    启动Prometheus:

    docker run --rm -v `pwd`/prometheus.yml:/etc/prometheus/prometheus.yml \
      -p 9090:9090 prom/prometheus
    

    查看CPU的user数据:

    node_cpu_seconds_total{cpu="0",mode="user"}
    node_cpu_seconds_total{instance="host.docker.internal:9101"} 503.27
    node_cpu_seconds_total{instance="host.docker.internal:9102"} 503.27
    

    查看CPU的system的数据:

    node_cpu_seconds_total{cpu="0",mode="system"} 
    node_cpu_seconds_total{instance="host.docker.internal:9101"} 336.28
    node_cpu_seconds_total{instance="host.docker.internal:9102"} 336.28
    

    我们可以按instance来直接匹配两个vector,让他们相除,得到system/user的比例:

    node_cpu_seconds_total{cpu="0",mode="system"} / on(instance) node_cpu_seconds_total{cpu="0",mode="user"}
    {instance="host.docker.internal:9101"} 0.6681900371569932
    {instance="host.docker.internal:9102"} 0.6681900371569932
    

    如果不指定on,由于这两个数据集有很多不同的标签,所以不知道如何一对一的匹配数据,也当然不知道如何操作。

    PromQL: group_left

    多对一的vector匹配,参考:Many-to-one and one-to-many vector matches

    首先,需要启动多个node_exporter,一个Darwin,两个Linux,可以用docker启动:

    ./node_exporter-1.3.1.darwin-amd64/node_exporter
    docker run --rm -it -p 9101:9100 prom/node-exporter
    docker run --rm -it -p 9102:9100 prom/node-exporter
    

    然后,配置Prometheus,抓取配置:

    scrape_configs: 
      - job_name: "node0"
        metrics_path: "/metrics"
        scrape_interval: 5s
        static_configs:
          - targets: ["host.docker.internal:9100"] 
      - job_name: "node1"
        metrics_path: "/metrics"
        scrape_interval: 5s
        static_configs:
          - targets: ["host.docker.internal:9101"] 
      - job_name: "node2"
        metrics_path: "/metrics"
        scrape_interval: 5s
        static_configs:
          - targets: ["host.docker.internal:9102"]
    

    启动Prometheus:

    docker run --rm -v `pwd`/prometheus.yml:/etc/prometheus/prometheus.yml \
      -p 9090:9090 prom/prometheus
    

    查看负载数据:

    node_load1
    node_load1{instance="host.docker.internal:9100"} 3.15283203125
    node_load1{instance="host.docker.internal:9101"} 0.7
    node_load1{instance="host.docker.internal:9102"} 0.64
    

    查看节点的信息数据:

    node_uname_info
    node_uname_info{instance="host.docker.internal:9100", sysname="Darwin"} 1
    node_uname_info{instance="host.docker.internal:9101", sysname="Linux"} 1
    node_uname_info{instance="host.docker.internal:9102", sysname="Linux"} 1
    

    如果我们要按Linux和Darwin分组数据,就需要Join这两个数据集了。可以用instance来关联,达到根据sysname来分组数据的目的:

    node_load1 * on(instance) group_left(sysname) node_uname_info
    {instance="host.docker.internal:9100", sysname="Darwin"} 3.15283203125
    {instance="host.docker.internal:9101", sysname="Linux"} 0.7
    {instance="host.docker.internal:9102", sysname="Linux"} 0.64
    

    分析这个语句:

    node_load1 // vector A
        * // 操作符 A.value * B.value,由于 B.value=1,我们保持A的值不变,所以用的乘
        on(instance) // JOIN on 用instance来join两个vector,A.instance==B.instance
        group_left(sysname) // 保留B的字段, 相当于 SELECT A.*, B. sysname
        node_uname_info // vector B
    

    如果更熟悉SQL,等价于SQL:

    SELECT A.*, B.sysname, A.value*B.value FROM node_load1 as A 
        join node_name_info B on A.instance=B.instance
    

    Note: 不同于SQL的是,由于Prometheus的数据集是时序的vector而不是table,而且肯定是对两个数据集的数据进行操作,所以Prometheus定义的操作符用来操作两个vector。

    最后,我们按照sysname分组Join之后的数据:

    sum by(sysname) (node_load1 * on(instance) group_left(sysname) node_uname_info)
    {sysname="Darwin"} 2.5068359375
    {sysname="Linux"} 0.29000000000000004
    

    如果需要对结果算rate,不应该对最终结果算rate,应该先算rate后,再做group_left和sum。因为rate实际上是一个expr表达式,是可以对两个expr做group_left的。

    PromQL: Join Custom Metrics

    参考How to join Prometheus metrics by label with PromQL

    参考How to have labels for machine roles

    首先,我们先生成两个目录,放两个文件,给node_exporter抓取:

    mkdir node1 node2
    echo 'machine_role{role="apache"} 1' > node1/roles.prom
    echo 'machine_role{role="postfix"} 1' > node2/roles.prom
    

    接着,需要启动两个node_exporter,这样有两个不同的机器,可以用docker启动:

    docker run --rm -it -p 9101:9100 -v $(pwd):/data -w /data \
        prom/node-exporter --collector.textfile.directory node1
    docker run --rm -it -p 9102:9100 -v $(pwd):/data -w /data \
        prom/node-exporter --collector.textfile.directory node2
    

    然后,配置Prometheus,抓取配置:

    scrape_configs: 
      - job_name: "node1"
        metrics_path: "/metrics"
        scrape_interval: 5s
        static_configs:
          - targets: ["host.docker.internal:9101"] 
      - job_name: "node2"
        metrics_path: "/metrics"
        scrape_interval: 5s
        static_configs:
          - targets: ["host.docker.internal:9102"]
    

    启动Prometheus:

    docker run --rm -v `pwd`/prometheus.yml:/etc/prometheus/prometheus.yml \
      -p 9090:9090 prom/prometheus
    

    查看负载:

    node_network_receive_bytes_total{device="eth0"}
    node_network_transmit_bytes_total{instance="host.docker.internal:9101"} 15375606
    node_network_transmit_bytes_total{instance="host.docker.internal:9102"} 723864
    

    查看我们打的role的标签:

    machine_role
    machine_role{job="node0", role="apache"} 1
    machine_role{job="node1", role="postfix"} 1
    

    可见我们有了这两组数据,可以用job来关联,达到根据role来筛选数据的目的:

    node_network_transmit_bytes_total{device="eth0"} * on(instance) group_left(role) machine_role
    {instance="host.docker.internal:9101", role="apache"} 15698720
    {instance="host.docker.internal:9102", role="postfix"} 735344
    

    分析这个语句:

    node_network_transmit_bytes_total{device="eth0"} // vector A
        * // 操作符 A.value * B.value,由于 B.value=1,我们保持A的值不变,所以用的乘
        on(instance) // JOIN on 用job来join两个vector,A. instance ==B.instance
        group_left(role) // 保留B的字段, 相当于 SELECT A.*, B.role
        machine_role // vector B
    

    后续就可以按照role聚合了。

    PromQL: Embed group_left

    可以对指标进行多次JOIN,配置参考前一章PromQL: Join Custom Metrics

    我们使用load数据:

    node_load1
    node_load1{instance="internal:9101"} 0.27
    node_load1{instance="internal:9102"} 0.27
    

    先让它和uname联合一次,加上nodename:

    node_load1 * on(instance) group_left(nodename) node_uname_info
    {instance="internal:9101", nodename="84270dfcb37f"} 0.27
    {instance="internal:9102", nodename="0ac4874101bd"} 0.27
    

    然后再和machine_role联合一次,加上role:

    (node_load1 * on(instance) group_left(nodename) node_uname_info) * on(instance) group_left(role) machine_role
    {instance="internal:9101", nodename="84270dfcb37f", role="apache"} 0.51
    {instance="internal:9102", nodename="0ac4874101bd", role="postfix"} 0.51
    

    这样相当于给每个数据点加上了这两个标签了,然后再根据加上的标签,进行分组聚合。

    相关文章

      网友评论

          本文标题:Prometheus笔记

          本文链接:https://www.haomeiwen.com/subject/yledgrtx.html