2022年9月

https://github.com/amitsaha/prom-file-sd-config-generator

功能比较单一,就是从url使用http GET请求获取一个资源列表,然后自动把他解析成json写进文件,需要提前配置好prometheus基于文件的自动发现功能

GET返回的格式类似于

<a href="http://127.0.0.1:9100/metrics/testitem1">target1</a>
<a href="http://127.0.0.1:9200/metrics/testitem2">target2</a>
<a href="http://127.0.0.1:9300/metrics/testitem3">target3</a>

使用示例

准备一个响应请求的程序

package main

import (
    "fmt"
    "net/http"
    "os"

    "github.com/gin-gonic/gin"
)

type targetlist []string

func port() string {
    port := os.Getenv("PORT")
    if len(port) == 0 {
        port = "8088"
    }
    return ":" + port
}

var list1 = targetlist{`<a href="http://127.0.0.1:9090/metrics">localhost</a>`,
    `<a href="http://172.29.36.125:9100/metrics">ser2</a>`}

func main() {
    engine := gin.Default()
    engine.GET("/list", func(c *gin.Context) {
        str := ""
        for _, item := range list1 {
            str = str + "\n" + item

        }
        fmt.Println(str)
        c.String(http.StatusOK, str)
    })

    engine.Run(port())
}

运行程序

./prom-file-sd-config-generator --config-path /var/file-sd.json --target-source "http://127.0.0.1:8088/list"

#一共就三个参数
#--config-path json文件地址
#--target-source  响应url
#--scrape-interval int  采集间隔,默认5s

有docker 镜像,使用方法和上面一样,挂参数就行
image.png
没看到有更改标签相关的功能,而且还得自己开发响应程序,感觉不实用

本文主要是对官方手册的解读,加上了一点基于实际压测后对方案的感受
https://yunlzheng.gitbook.io/prometheus-book/part-ii-prometheus-jin-jie/readmd/prometheus-local-storage

存储

架构

prometheus 2.x版本以两小时为一个周期,每个周期落盘记录为一个block,block下面有chunk样本数据、metadata元数据、index索引数据
未落盘的数据保存在内存中,如果发生意外导致应用崩溃,恢复的时候会从写入日志(WAL)中读取并重播以恢复数据,在此期间如果发生过删除数据的操作,也会被记录在逻辑文件tombstones
这种以时间段来分段的方式有利于数据的查询以及简化删除过期数据的逻辑
普罗米修斯中单个指标样本约占1-3字节,当然,在其可靠的压缩算法之下能变得更小(按fb的算法能压缩到 1.37 bytes 每个点,我们测在3左右),2.x版本甚至专门对ssd的读写性能和次数进行了优化,感动人心。存储大小的计算公式为

needed_disk_space = retention_time_seconds * ingested_samples_per_second * bytes_per_sample

如果保留时间和指标本身不变动的话,从ingested_samples_per_second(每秒采样总数)想要压缩存储成本就两个方法:
1.延长采样间隔
2.减少指标
prometheus压缩算法参考了fb的Gorilla tsdb,有兴趣可以研究一下

关于WAL机制更详细的介绍

data/
├── 01GCDV01N8T74K4HE9JRD7PNQP #block,命名采用ULID:全局字典可排序ID
│   ├── chunks #样本,单块最大512M
│   │   └── 000001
│   ├── index #索引
│   ├── meta.json #元数据
│   └── tombstones #逻辑
├── 01GCDYC64PDTMA62ZMT73GEX8S
│   ├── chunks
│   │   └── 000001
│   ├── index
│   ├── meta.json
│   └── tombstones
├── chunks_head
│   └── 000002
├── lock
├── queries.active
└── wal #写入日志
    ├── 00000000
    ├── 00000001
    ├── 00000002
    └── 00000003

内存中存放的数据,每满三个小时,会被分成2h和1h的一块,2h的那块落盘,1h的那块继续留在内存,数据在写入内存的同时也会被写入wal以确保持久性
内存中的存储结构我们叫其head_block,当获取到新的数据,会写入其中的head_chunk,chunk也是唯一能够被写入的地方。这个chunk每当样本数达到设定的值或者range达到设定的值的时候就会被剪切,然后新增一个新的chunk,旧的chunk被称为“full”,从2.19开始,一个full的chunk会被写入磁盘并通过内存映射引用在内存中,当需要用到的时候可以动态加载进来,当达到上面说的3h时,其中2h的chunk会被压缩成block落盘,wal中的数据也会形成checkpoint截断旧的数据,这个检查点将会检查这些被截断的数据,看看他们是否满足被删除的条件
新版本的普罗米修斯支持wal压缩,这将大大减少磁盘和内存的开销----旧版本可能会出现因为wal数据过多而导致硬盘和内存占用过大,可以参考这篇https://asktug.com/t/topic/512888/2 最最好的解决方法是升级版本

一篇压测文:https://www.percona.com/blog/2018/09/20/prometheus-2-times-series-storage-performance-analyses/

远程存储

虽然prometheus本身就支持本地存储,但是如果想要数据持久化,可以考虑外接influxdb搞个远程存储,只需要调用(remote_write/remote_read)这两个接口就可以实现远程存储的读写
对于远程读取,prometheus会对数据用promQL进行二次处理,另外,因为promtheus只有数据是放数据库的,规则等都是通过配置文件实现的,所以启用远程读设置后,只在数据查询时有效,对于规则文件的处理,以及Metadata API的处理都只基于Prometheus本地存储完成。
开启这两个功能只需要修改普罗米修斯的配置文件就行

remote_write:
    url: <string>
    [ remote_timeout: <duration> | default = 30s ]
    write_relabel_configs:
    [ - <relabel_config> ... ]
    basic_auth:
    [ username: <string> ]
    [ password: <string> ]
    [ bearer_token: <string> ]
    [ bearer_token_file: /path/to/bearer/token/file ]
    tls_config:
    [ <tls_config> ]
    [ proxy_url: <string> ]

remote_read:
    url: <string>
    required_matchers:
    [ <labelname>: <labelvalue> ... ]
    [ remote_timeout: <duration> | default = 30s ]
    [ read_recent: <boolean> | default = false ]
    basic_auth:
    [ username: <string> ]
    [ password: <string> ]
    [ bearer_token: <string> ]
    [ bearer_token_file: /path/to/bearer/token/file ]
    [ <tls_config> ]
    [ proxy_url: <string> ]

普罗米修斯现在也支持一些第三方的存储,所以上面说能够influxdb是基于这个原因,至于实现方式看上面的手册,这里不再复制粘贴

高可用:套娃方案

官方给出了三套高可用方案,不过其实本质上就是一套,分成了丐中丐版、丐版、完全版而已

对于大量数据的处理,官方给的方案是这套,用nginx负载均衡来保障可用性,两个大P的数据是一样的,挂了一个还有一个,小p们通过relabel设置分功能去收集或者随便咋分,总之采了数据上交给大P,以此来保证应对大量数据时的采集性能。最后再外挂个远程存储来实现数据持久化存储
image.png

image.png
所谓联邦集群,本质其实是部署多套普罗米修斯收集数据,最后再用一个普罗米修斯从这些个小p身上汇总数据

以上三部分可以按需选择,各自解决一部分问题

(方案挺不错的,不过我选择prometheus+thanos
https://github.com/thanos-io/thanos/tree/main/

官方的这套联邦方案,看起来很美好,但是实际测试下来性能很差,数据量大不推荐使用,毕竟他下面小弟汇总,再去拉取,这个数据量大了必卡(测下来别说亿级,百万级、大几十万级都会翻白眼直接超时),而且普罗米修斯本身的性能瓶颈也导致了即便是提高机器配置也很难提升多少性能

这就不得不提到另外一个著名的社区方案:thanos。比如布两套一样的普罗米修斯去采集事务再用thanos去查。这个方案和联邦方案的区别在于,单个pod采集上来的数据量本身是比较小的,虽然汇总起来很大,但是对于普罗米修斯来说就等于是在并行处理许多的小任务,这个普罗米修斯完全是可以做到的。而联邦集群的方案会导致大P去拉取小p的数据时,一次性的把小p获取到的所有数据打包拉了上来,等于在并行处理几个超巨大的任务,饭一口一口吃多吃几碗没问题,一口吃一碗会把人给噎死

Thanos

https://github.com/thanos-io/thanos/tree/main/

灭霸,可靠的开源高可用方案(笑

因为买的服务器过期了,所以这里安装就不演示了
avatar

thanos能无缝兼容promtheus,并且易于水平横向扩容,翻译成人话就是,要是一对prometheus拉不了所有的数据,可以把数据分组,用多组prometheus分别去拉
avatar
简单架构说明:

sidecar和prometheus布一个pod里面,他将prometheus的已落盘的数据上传到对象存储,将grpc的调用转换为http,请求prometheus查询并返回数据,可以像上面一样布两个promtheus去拉一样的数据,起到高可用的作用

query提供查询接口,当在prometheus数据保存期内就从sidecar查,如果超过保质期就去对象存储查,拿到结果后去重返回

object store对象存储,数据在结果compact组件(图上没画)压缩后存入对象存储,提供了数据持久化功能

storegateway提供查询语句转换功能,把promQL转换成对象存储能够理解的语句再发给他

虽然已落盘的数据在pod和obj里面都有,但是除非超过保质期,不然都是从pod里面查而非obj,对象存储的查询性能很差
thanos还有些其他的组件,像rule之类的,这里就不讲了

docker pull prom/node-exporter

node-exporter.yaml

apiVersion: apps/v1 
kind: DaemonSet #daemonset会保证每个node都有这个pod
metadata:
  name: node-exporter
  namespace: promtest
spec:
  selector: 
    matchLabels: 
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostPID: true
      hostIPC: true
      hostNetwork: true
      containers:
      - name: node-exporter
        image: prom/node-exporter
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9100
          hostPort: 9100
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 2000m
            memory: 2Gi        
        securityContext:
          privileged: true
        args:
        - --path.procfs
        - /host/proc
        - --path.sysfs
        - /host/sys
        - --path.rootfs
        - /host/root
        - --collector.filesystem.ignored-mount-points
        - '"^/(sys|proc|dev|host|etc)($|/)"'
        - "--collector.processes"
        volumeMounts:
        - name: dev
          mountPath: /host/dev
        - name: proc
          mountPath: /host/proc
        - name: sys
          mountPath: /host/sys
        - name: rootfs
          mountPath: /host/root
      tolerations: #污点容忍
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"
      volumes:
        - name: proc
          hostPath:
            path: /proc
        - name: dev
          hostPath:
            path: /dev
        - name: sys
          hostPath:
            path: /sys
        - name: rootfs
          hostPath:
            path: /
#如果要在容器环境中部署node-exporter,需要将主机的根节点绑定到容器环境,不然在查询磁盘等参数时,数据是不准确的

node-ser.yaml

kind: Service
apiVersion: v1
metadata:
  name: node-ser
  namespace: promtest
  labels:
    app: node-exporter
spec:
  ports:
  - name: metricsa
    port: 9100
    protocol: TCP
    targetPort: 9100
  selector:
    app: node-exporter

helm是k8s的包管理工具

安装

https://github.com/helm/helm/releases

  1. 解压(tar -zxvf helm-v3.0.0-linux-amd64.tar.gz)
  2. 在解压目中找到helm程序,移动到需要的目录中(mv linux-amd64/helm /usr/local/bin/helm)

入门

chart的结构一般如下

mychart/
  Chart.yaml
  values.yaml
  charts/
  templates/
  ...

templates/ 目录包括了模板文件。当Helm评估chart时,会通过模板渲染引擎将所有文件发送到templates/目录中。 然后收集模板的结果并发送给Kubernetes。
values.yaml 文件也导入到了模板。这个文件包含了chart的 默认值 。这些值会在用户执行helm install 或 helm upgrade时被覆盖。
Chart.yaml 文件包含了该chart的描述。你可以从模板中访问它。charts/目录 可以 包含其他的chart(称之为 _子chart_)。(描述性的,一般这个文件不用怎么管

你可以使用helm create chartname来快速创建一个项目文件夹,里面包含了一个完整的结构,甚至包含了一些预生成的模版,如下

[root@master linux-amd64]# helm create testlist
[root@master testlist]# ll
total 16
drwxr-xr-x 2 root root 4096 Sep  1 14:34 charts
-rw-r--r-- 1 root root 1144 Sep  1 14:34 Chart.yaml
drwxr-xr-x 3 root root 4096 Sep  1 14:34 templates
-rw-r--r-- 1 root root 1875 Sep  1 14:34 values.yaml

[root@master testlist]# ll templates/
total 32
-rw-r--r-- 1 root root 1841 Sep  1 14:34 deployment.yaml
-rw-r--r-- 1 root root 1792 Sep  1 14:34 _helpers.tpl
-rw-r--r-- 1 root root  919 Sep  1 14:34 hpa.yaml
-rw-r--r-- 1 root root 2081 Sep  1 14:34 ingress.yaml
-rw-r--r-- 1 root root 1751 Sep  1 14:34 NOTES.txt
-rw-r--r-- 1 root root  322 Sep  1 14:34 serviceaccount.yaml
-rw-r--r-- 1 root root  364 Sep  1 14:34 service.yaml
drwxr-xr-x 2 root root 4096 Sep  1 14:34 tests
[root@master testlist]# ll templates/tests/
total 4
-rw-r--r-- 1 root root 382 Sep  1 14:34 test-connection.yaml

你可以把他们全部删除然后写你自己的,你也可以在这些文件的基础上进行修改,helm官方有一些别人已经写好的helm,你可以helm pull把他们拉下来,但是一般实际环境还是得要根据自己的需求去写

常用指令

helm create chartname 创建一个helm工程文件夹
helm package path 打包一个helm版本包
helm lint path 验证chart
helm uninstall release_name 卸载一个已经安装的包
helm test 测试模拟安装
helm template 渲染模版,可以看看各个值映射的对不对

编写示例:普罗米修斯容器化方案

prometheus+grafana,并实现以文件的方式自动发现
当然,这里只是简单演示,具体请按自己情况来添加其他需要的功能
deployment:

prometheus.yaml

#/bin/prometheus --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/prometheus --web.console.libraries=/usr/share/prometheus/console_libraries --web.console.templates=/usr/share/prometheus/consoles

apiVersion: apps/v1
kind: StatefulSet
metadata: 
  name: prometheus
  namespace: {{.Values.namespace}}
spec: 
  serviceName: prometheus
  replicas: {{.Values.prom.replicaCount}}
  selector: 
    matchLabels: 
      app: prometheus
  template: 
    metadata: 
      labels: 
        app: prometheus
    spec: 
      containers: 
      - name: prometheus
        image: prom/prometheus:latest
        imagePullPolicy: IfNotPresent
        args:
        - "--config.file=/etc/prometheus/conf/prometheus.yml"
        # user: root
        # command:  ["chmod", "-R", "777", "/prometheus"]
        volumeMounts: 
          - mountPath: /etc/prometheus/conf/
            name: prometheusconf
          - name: storage 
            mountPath: /prometheus
          - name: static-sd
            mountPath: /var/
      volumes: 
      - name: prometheusconf
        hostPath:
          path: /prom/conf/ #配置文件存放地址
      - name: storage
        hostPath: 
          path: /data01/ #node上的挂载点,记得权限放高点,不然pod里面的用户没有修改这个目录的权限就会导致失败
          type: DirectoryOrCreate
      - name: static-sd
        configMap:
          name: prometheus-file-sd #节点自动发现

grafana.yaml

apiVersion: apps/v1 
kind: Deployment
metadata: 
  name: grafana
  namespace: {{.Values.namespace}}
spec: 
  replicas: 1 
  selector: 
    matchLabels: 
      app: grafana
  template: 
    metadata: 
      labels: 
        app: grafana 
    spec:
      containers: 
      - name: grafana
        image: grafana/grafana:latest
        imagePullPolicy: IfNotPresent

configuremap:

file-sd.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-file-sd
  namespace: {{ .Values.namespace }}
  labels:
    app: promtest
data:
  file-sd.json: |
    [
    ]

service

prom-ser.yaml

kind: Service
apiVersion: v1
metadata:
  name: prometheus
  namespace: {{ .Values.namespace }}
  labels:
    app: prometheus
spec:
  type: NodePort
  ports:
  - name: http
    port: 9090
    protocol: TCP
    targetPort: 9090
    nodePort: 30001
  selector:
    app: prometheus

gra-ser.yaml

kind: Service
apiVersion: v1
metadata:
  name: grafana
  namespace: {{ .Values.namespace }}
  labels:
    app: grafana
spec:
  type: NodePort
  ports:
  - name: grafana
    port: 3000
    targetPort: 3000
    nodePort: 30002
  selector:
    app: grafana

values.yaml

namespace: promtest

prom: 
  replicaCount: 1
  image:
  - name: prometheus
    image: prometheus:latest
    pullPolicy: IfNotPresent

用了几个月普罗米修斯了,回头再来补一篇博客(笑
参考:https://blog.csdn.net/cp3_zyh/article/details/124019043

简介

谷歌出品,基于Go编写,容器时代版本的答案!

特点:

  • 由指标名+键值对的标签标识的时序数据和转为监控而生的时序数据库TSDB
  • promQL
  • 自动发现
  • 成熟的容器化支持
  • 独立部署,无需agent,但是想要获得一些针对性的监控需要对应的exporter
  • 基于HTTP采集数据
  • 秒级采集精度
  • 基于数学模型计算,能够实现复杂的监控逻辑(如计算QPS相关的指标等)
  • 数据恢复机制


prometheus server可以独立部署,采集目标的数据并存储在tsdb中,自身对外提供promQL,计算告警规则并把触发告警的推送给altermanager
exporter可以帮助普罗米修斯采集数据,目前市面上常见的软件均已有现成的exporter,如mysql\nginx等
pushgateway主要用于针对一些短期存在的job,这些job可以直接向其push metrics,prometheus server周期性过去取数据就行
altermanager从server获取到alter之后,对其进行去重分组后路由至正确的告警方式,支持多种告警格式
serverdiscovery负责动态发现监控对象

普罗米修斯的TS数据库以每两小时为间隔来分block存储,每一个块又分chunk存储,chunk用于存储采集过来的ts数据、index、metadata,index是对metrics和labels进行索引后对存储。后台还会把小block合并成大block以减少内存里block的数量

普罗米修斯使用WAL机制来保护未落盘的数据不会因为突然宕机而丢失,WAL被分割成默认大小为128M的文件段(segment)文件段以数字命名,长度为8位的整形。WAL的写入单位是页(page),每页的大小为32KB,所以每个段大小必须是页的大小的整数倍。如果WAL一次性写入的页数超过一个段的空闲页数,就会创建一个新的文件段来保存这些页,从而确保一次性写入的页不会跨段存储。当出现宕机,等到机器恢复之后,普罗米修斯会把这些数据恢复进内存

Prometheus的数据由指标名称metric、一组键值对、时间戳、指标值组成,键值对可以在配置文件里面自定义,方便后面根据其来用promQL进行数据的分组、筛选等工作。
指标表达方式

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

四种数据类型

Counter
Counter是计数器类型

  • Counter 用于累计值,例如记录请求次数、任务完成数、错误发生次数。
  • 一直增加,不会减少。
  • 重启进程后,会被重置。

Gague
Gauge是测量器类型

  • Gauge是常规数值,例如温度变化、内存使用变化。
  • 可变大,可变小。
  • 重启进程后,会被重置

Histogram
histogram是直方图,在Prometheus系统的查询语言中,有三种作用:
1)在一段时间范围内对数据进行采样(通常是请求持续时间或响应大小等),并将其计入可配置的存储桶(bucket)中. 后续可通过指定区间筛选样本,也可以统计样本总数,最后一般将数据展示为直方图。
2)对每个采样点值累计和(sum)
3)对采样点的次数累计和(count)
度量指标名称: [basename]_上面三类的作用度量指标名称_
举例:
对一批访问,分别列出响应时间在0~0.5,0.5~1,1+的数量

[basename]bucket{le="上边界"}, 这个值为小于等于上边界的所有采样点数量
[basename]_sum_
[basename]_count

Summary
Summary即概率图,类似于Histogram,常用于跟踪与时间相关的数据。典型的应用包括请求持续时
间、响应大小等。Summary同样提供样本的count和sum功能;还提供quantiles功能,可以按百分比划
分跟踪结果,例如,quantile取值0.95,表示取样本里的95%数据。Histogram需要计算,summary直接存储

安装与入门示例

https://prometheus.io/download/ 挑版本下载
解压
cp -rf prometheus-2.38.0.linux-amd64 /usr/local/prometheus
./prometheus &运行,默认运行在9090端口
但是注意这种方式启动会使得你丢失普罗米修斯的日志!!你可以配置个systemd或者用nohup来指定输出日志

[root@master prometheus]# ss -tnlp | grep 9090
LISTEN     0      128       [::]:9090                  [::]:*                   users:(("prometheus",pid=373,fd=8))

nohup ./prometheus > /var/log/prom.log 2>&1  & #nohup方式,把输出重定向到了我指定的日志文件里面

普罗米修斯本身还带有一些启动的参数

--config.file=”prometheus.yml” 指定配置文件
-–storage.tsdb.path=”data/”    指标存储的基本路径。
--storage.tsdb.retention=15d 指定保存的数据的时间

当然,因为这里只是演示,我就不加参数了,实际生产环境按需设置

访问端口就可以访问了,阿里云的服务器如果发现访问不了的话,先去安全组里面放行9090端口

关于普罗米修斯的访问控制可以看

https://blog.csdn.net/qq_31725371/article/details/114978760


image.png

prometheus的配置文件是prometheus.yml,当然你也可以用--yml来指定配置文件

# 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"] #监控对象

这里我们把targets改成targets: ["localhost:9090", "node1:9100"]试试看(node1是另外一台服务器,已经配置了hosts,9100一般是node_exporter的端口
当然,这里得提前在机器上装好node_exporter并启动,安装方式同上,官网下载运行就行,当然,记得放行9100端口
image.png
以cpu使用率为例子

image.png

查询node_cpu_seconds_total,我们得到了各项cpu使用时间数据,counter类型的
image.png
通过cpu占用率的原理可以得知,cpu的使用率=cpu除空闲时间以外的总时间/总时间
所以这里应该这么写
(1-((sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by (instance)) / (sum(increase(node_cpu_seconds_total[1m])) by (instance)))) * 100
image.png
image.png
这个指标是个counter类型,累计的,{}取了带标签为mode="idle"的数据,increase()可以取一段时间内的增长量,因为一台云服务器一般不止1核,会查出多条cpu数据,单核单核看没多少意义,所以用sum进行总和。by instance是按实例拆分数据,如果是集群多机器的时候可以根据主机来区分数据分开展示。[1m]是就取一分钟内的数据,对于cpu这种实时性很强的指标取太长意义不大
((sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by (instance)) 分解⬇️
node_cpu_seconds_total{mode="idle"}[1m]
increase(node_cpu_seconds_total{mode="idle"}[1m])
sum(increase(node_cpu_seconds_total{mode="idle"}[1m]))
(sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by (instance)

promQL

https://blog.csdn.net/fu_huo_1993/article/details/114482586
这篇比较全,以下是部分

匹配器

使用{}可以通过标签来筛选数据

=: 精确的匹配给定的标签值
!=: 不匹配给定的标签值
=~: 正则表达式匹配给定的标签值
!~: 不匹配正则表格式给定的标签值
=~和!= 必须要指定一个标签名字或者匹配的标签必须要有值

例子:

查询出指标名称up中标签job等于prometheus的时间序列数据
up{job=“prometheus”}
查询出指标名称up中标签job以pro开头的的时间序列数据
up{job=~“pro.*”}
查询出指标名称up中不存在标签env的时间序列数据

时间区间

up[5m] 表示查询5分钟时间内各实例的状态
ms(毫秒)、s(秒)、m(分钟)、h(小时)、d(天)、w(周)、y(年)

d 表示一天总是24小时
w 表示一周总是7天
y 表示一年总是365天
可以将多个不同的时间单位串联起来使用,但是大的时间单位必须在前面,小的时间单位在后面,且不同的时间单位只能出现一次。且不能是小数。
eg: 1h30m可以,但是1.5h则不才可以。

偏移量

表示获取指标名称prometheus_http_requests_total的所有时间序列在距离此刻1分钟之前的5分钟之内的样本。

prometheus_http_requests_total[5m] offset 1m

运算符

+(加)、-(减)、*(乘)、/(除)、%(取模)、^(幂等)
== (等于)、!=(不等于)、>(大于)、<(小于)、>=(大于或等于)、<=(小于或等于)
and(并且-交集)、or(或者-并集)、unless(除非-补集)

如果存在bool修饰符,则结果只返回0,1.如果不使用bool修饰符,那么返回满足结果的个数
image.png
image.png

匹配

两个即时向量之间进行计算,需要拥有一样的标签才能计算,使用匹配关键字可以帮助我们达成计算目的
向量之间的运算尝试为左侧的每个条目在右侧向量中找到匹配的元素

ignoring:允许在匹配时忽略某些标签。

on:允许在匹配时只匹配指定的标签。

例:
method_code:http_errors:rate5m{method="get", code="500"}  24   和
method:http_requests:rate5m{method="get"}  600

这两个拥有共同的标签method,但是前者多一个code,正常来讲是无法计算的

method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
这种写法让我们忽视前者的code标签,这样两者拥有的标签就一样了
一对多和多对一:“一”的一侧的每个向量元素可以与“多”侧的多个元素进行匹配。必须使用group_left或group_right修饰符显式请求,其中left/right确定哪个向量具有更高的基数

例
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m

内置函数

by 从计算结果从保留该标签、移除其他标签来分组,具体见上面的入门例子
without:与by类似,移除该标签保留其他标签
abs():绝对值
floor():粘贴并匹配样式
increase():返回区间范围内值的增长量,counter
rate():平均增长速率,区间内counter增长量/时间
irate():取最后两个值计算瞬间增长率
sum():合计
topk(n,metric):选出最高的几个值,counter,gague
cout():统计结果的条数

常用组件

https://prometheus.io/download/ 官方组件的下载地址

node_exporter

主机监控

push_gateway

因为pushgateway是被动获取数据,运行起来后取普罗米修斯里面单独给他加一个

  - job_name: "pushgateway"
    static_configs:
      - targets: ["localhost:9091"]

pushgateway可以自己写一些小脚本跑在机器上,定期给普罗米修斯推送

blackbox

端口监测,只能检活

grafana

https://grafana.com/grafana/download/9.1.2
service grafana-server start
以这种方式启动的grafana会使用默认的配置文件和日志文件
/etc/grafana/grafana.ini
/var/log/grafana/grafana.log

访问3000端口
image.png
配置数据源,然后建立dashboard或者先建立folder再建立dashboard,建议先建文件夹,grafana有完善的权限控制,后续可以把一个应用的监控面板放在一个文件夹里面,然后把相关的人员放进一个team里面,赋权的时候直接给team赋予权利就行了

容器化方案+自动发现+dashboard

prometheus有docker镜像,可以直接拉取
除此以外还有另外一套通过yaml来部署的项目,或者自己自定义文件来安装(如通过helm等
https://github.com/prometheus-operator/kube-prometheus

这里介绍通过helm编排容器,以及基于文件的自动发现,以下三篇为参考教程
https://yunlzheng.gitbook.io/prometheus-book/part-ii-prometheus-jin-jie/sd/service-discovery-with-file
https://cloud.tencent.com/developer/article/1885193
https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247495887&idx=1&sn=beddcaebaf6738a2d9f69bf5c35a348c&chksm=fdbaffd2cacd76c41e796065bc11ed608b404587c371281c3f3e3df4b65b81fc26178cbcf310&scene=21#wechat_redirect
docker pull prom/prometheus
docker pull grafana/grafana
在node机器上准备好prometheus.yaml,挂载目录建议提前创建好然后赋权赋高点,不然会出现权限问题导致应用创建失败

global:
  scrape_interval: 15s
  scrape_timeout: 10s
  evaluation_interval: 15s
scrape_configs:
- job_name: file_ds
  honor_timestamps: true
  scrape_interval: 15s
  scrape_timeout: 10s
  metrics_path: /metrics
  scheme: http
  follow_redirects: true
  file_sd_configs:
  - files:
    - /var/file-sd.json
    refresh_interval: 1m

helm编写,具体请见http://shangxizhuan.site/archives/411/例子部分

配置完后,尝试访问服务,成功,如果是阿里云之类的记得先放行端口
image.png

现在我们来测试一下自动发现功能正不正常,在一台机子上运行期node_exporter,然后去cm里面修改

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-file-sd
  namespace: {{ .Values.namespace }}
  labels:
    app: promtest
data:
  file-sd.json: |
    [
      {
      "targets": [ "localhost:9090" ],
      "labels": {
        "env": "prod",
        "job": "local"
      }
    },
    {
      "targets": [ "server2:9100"],
      "labels": {
        "env": "ser2",
        "job": "node"
      }
    }
    ]

等个一分钟左右就看到新的节点已经被自动加载上来了
image.png
这里节点挂了的原因并不是node_exporter,而是这个exporter是单点的,不是集群里的pod,没做路由连接不上

dashboard部分,先拉取官方的recommand.yaml,按需修改
https://github.com/kubernetes/dashboard

http://www.live-in.org/archives/3320.html
如果发现pod起不来,试试安装在master节点,修改下面两处

    spec:
      nodeName: master节点的名字
      containers:
        - name: kubernetes-dashboard
          image: kubernetesui/dashboard:v2.0.4
          imagePullPolicy: Always


    spec:
      nodeName: master节点的名字
      containers:
        - name: dashboard-metrics-scraper
          image: kubernetesui/metrics-scraper:v1.0.4

443端口相关报错,删除yaml里面检活部分

如果进去发现列不出pod,试试添加角色

https://stackoverflow.com/questions/58719006/kubernetes-dashboard-error-using-service-account-token
https://stackoverflow.com/questions/46664104/how-to-sign-in-kubernetes-dashboard
kubectl delete clusterrolebinding kubernetes-dashboard kubectl create clusterrolebinding kubernetes-dashboard --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard
kubectl create clusterrolebinding deployment-controller --clusterrole=cluster-admin --serviceaccount=kube-system:deployment-controller
获取token
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | awk '/^deployment-controller-token-/{print $1}') | awk '$1=="token:"{print $2}'

访问url,如果发现打不开,使用https再试试看,出现报错按照上面的方案处理

image.png

其他及缺陷

上面给的只是基础的容器化方案,大集群肯定会涉及到高可用的问题,对于这个,比起官方的联邦方案,我更推荐thanos

对存储机制和联邦集群方案的分析在这

普罗米修斯毋庸置疑是容器化环境下监控方案的旗帜,falcon虽好,但是不太支持容器,至于zabbix......什么年代了,还在用传统监控(笑

prometheus本身也是有点点缺陷的,当数据量很大的时候,启动会比较慢,因为其WAL机制,虽然保障了数据恢复机制,但是也使得其在启动的时候必须把还没落盘的数据都加载到内存里面,而且还是一块一块加载(虽然这边给官方提过意见,但是官方表示改不了,就这样)

关于数据采集,除了官方的和社区的那些exporter,一般公司肯定有自己开发的业务,这种一般得自己开发exporter,或者,java应用可以用micrometer打点,毕竟普罗米修斯他跟别的监控不太一样,采集哪些指标、指标怎么进行计算,除了通用的一些,这些只有开发者自己最清楚

https://github.com/micrometer-metrics/micrometer