跳至主要內容

Prometheus

大约 56 分钟约 16669 字

Prometheus

一,简介

1.1 监控目标:

​ 白盒监控:通过白盒监控了解其内部的运行状态,通过对监控目标的观察能够预判可能出现的问题;从而对潜在的不确定因素进行优化;

​ 黑盒监控:可以在系统或服务发生故障能够快速的通知相关人员;

目的:

  • 趋势数据

  • 对照分析

  • 告警

  • 故障分析与定位

  • 数据可视化

1.2 prometheus的优势:

  1. ​ 易于管理,监控服务的内部运行状态,强大的数据模型,PromQL,高效,可扩展,易于集成,可视化,开放性;

  2. ​ 监控服务的内部运行状态, 基于Prometheus丰富的Client库,用户可以轻松的在应用程序中添加对Prometheus的支持,从而让用户可以获取服务和应用内部真正的运行状态 ;

  3. ​ 强大的数据模型, 所有采集的监控数据均以指标(metric)的形式保存在内置的时间序列数据库当中(TSDB) ;

  4. http_request_status{code='200',content_path='/api/path', environment='produment'} => [value1@timestamp1,value2@timestamp2...]
    
  5. ​ 强大的查询语言promQL

  6. ​ 高效, 每秒处理数十万的数据点;

  7. ​ 可扩展

  8. ​ 易于集成

  9. ​ 可视化,

  10. ​ 开放性

1.3 安装promethuse server

https://prometheus.io/download/ ,下载文件,解压
[root@prometheus02 local]# systemctl cat promethues.service
# /usr/lib/systemd/system/promethues.service
[Unit]
Description=prometheus
After=network.target
[Service]
ExecStart=/usr/local/prometheus/prometheus --config.file=/usr/local/prometheus/prome
Restart=on-failure
[Install]
WantedBy=multi-user.target
###启动服务
# systemctl enable --nwo promethues.service
# ls -io:9090
[Unit]
Description=prometheus
After=network.target
[Service]
ExecStart=/usr/local/prometheus/prometheus --config.file=/usr/local/prometheus/prometheus.yml --web.listen-address=:9090
Restart=on-failure
[Install]
WantedBy=multi-user.target

默认配置文件四个部份

# 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"]

1.4node_exporter安装:

[root@test01 ~]# wget https://github.com/prometheus/node_exporter/releases/download/v1.3.1/node_exporter-1.3.1.linux-amd64.tar.gz
tar -xf node_exporter-1.3.1.linux-amd64.tar.gz
mv node_exporter-1.3.1.linux-amd64 /usr/local/node_exporter
[root@test01 ~]# ls /usr/local/node_exporter/
LICENSE  NOTICE  node_exporter
###添加到服务
[root@test01 ~]# systemctl cat exporter.service 
# /usr/lib/systemd/system/exporter.service
[Unit]
Description=prometheus
After=network.target
[Service]
ExecStart=/usr/bin/nohup /usr/local/node_exporter/node_exporter
Restart=on-failure
[Install]
WantedBy=multi-user.target

[root@test01 ~]# systemctl enable --now exporter.service

1.5 修改promethues server 文件

​ 添加如下文件:

- job_name: "CentOS-TEST01"
    static_configs:
      - targets: ["10.30.162.63:9100"]
  - job_name: "promethues-node-exporter"
    static_configs:
      - targets: ["10.30.162.192:9100"]
  - job_name: "nodes"
    static_configs:
      - targets: ["10.30.162.194:9100","10.30.162.198:9100","10.30.162.195:9100"]

登录网页,输入up,查看添加的主机状态;

image-20230331163021379

1.6 prometheus组件

Prometheus架构 Prometheus架构

二 PromQL

2.1 理解时间序列

2.1.1样本

​ Prometheus采集到的样本数据以时间序列(time-series)的方式保存在内存数据库存中,并且定时存在硬盘上。(TSDB)

​ time-series是按照时间戳和值的序列顺序存放的,称之为向量(vector).

 ^. . . . . . . . . . . . . . . . .   . .  node_cpu{cpu="cpu0",mode="idle"}. . . . . . . . . . . . . . . . . . .  node_cpu{cpu="cpu0",mode="system"}. . . . . . . . . .   . . . . . . . .  node_load1{}. . . . . . . . . . . . . . . .   . .  
  v
    <------------------ 时间 ---------------->

​ 在time-series中每一个点称为一个样本(sample),样本由下面三个部分组成 :

  • ​ 指标(metric):metirc name+labelsets
  • ​ 时间戳(timestamp):可以精确到毫秒;
  • ​ 样本值(Value):

2.2 指标(metric)

2.2.1 基本介绍

格式如下:

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

​ 指标名称只能由ASCII字符、数字、下划线以及冒号组成并必须符合正则表达式[a-zA-Z_:][a-zA-Z0-9_:]*。 反映样本的含义;

​ 标签(label)反映当前样本的特征维度, 以对样本数据进行过滤,聚合等 , 名称只能由ASCII字符、数字以及下划线组成并满足正则表达式[a-zA-Z_][a-zA-Z0-9_]*

​ 其中_作为前缀的标签,是系统保留的关键字,只能在系统内部使用,

api_http_requests_total{method="POST", handler="/messages"}
{__name__="api_http_requests_total",method="POST", handler="/messages"}

Prometheus源码中,metirc的数据结构如下:

type Metric LabelSet

type LabelSet map[LabelName]LabelValue

type LabelName string

type LabelValue string

​ Prometheus定义了4中不同的指标类型(metric type):Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)。

2.2.2 metric类型-Counter(计数器)

​ 特点:只增不减,除非系统发生重置;可以通过一些函数获取变化速率;

如:通过rate()获取HTTP请求的增长率:

rate(http_requests_total[5m])

访问前10的http地址:

topk(10, http_requests_total)

2.2.3 metric类型-Gauge(仪表盘)

​ Gauge类型的指标侧重于反应系统的当前状态 , 样本数据可增可减 。

如下:

node_memory_MemFree_bytes

通过delta()来查看变化情况

delta(node_memory_MemFree_bytes[2h])
idelta(node_memory_MemFree_bytes[2h])

可以使用deriv()计算样本的线性回归,

deriv(node_memory_MemFree_bytes[2h])

使用predict_linear()对数据的变化趋势进行预测

predict_linear(node_memory_MemFree_bytes[2h],20*3600)

2.2.4 metric类型- Histogram和Summary的指标类型

​ Histogram和Summary主用用于统计和分析样本的分布情况,解决长尾问题;

​ 为了区分是平均的慢还是长尾的慢,最简单的方式就是按照请求延迟的范围进行分组。

如下:quantile为分位数0-1

Summary

# HELP prometheus_rule_group_duration_seconds The duration of rule group evaluations.
# TYPE prometheus_rule_group_duration_seconds summary
prometheus_rule_group_duration_seconds{quantile="0.01"} 0.003513586
prometheus_rule_group_duration_seconds{quantile="0.05"} 0.003740832
prometheus_rule_group_duration_seconds{quantile="0.5"} 0.005341571
prometheus_rule_group_duration_seconds{quantile="0.9"} 0.009430996
prometheus_rule_group_duration_seconds{quantile="0.99"} 0.010494519
prometheus_rule_group_duration_seconds_sum 1772.5477663010008
prometheus_rule_group_duration_seconds_count 299810

Histogram

# HELP prometheus_tsdb_compaction_chunk_range_seconds Final time range of chunks on their first compaction
# TYPE prometheus_tsdb_compaction_chunk_range_seconds histogram
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="100"} 22
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="400"} 22
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="1600"} 22
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="6400"} 22
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="25600"} 102
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="102400"} 659
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="409600"} 827
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="1.6384e+06"} 2141
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="6.5536e+06"} 5.785815e+06
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="2.62144e+07"} 5.785815e+06
prometheus_tsdb_compaction_chunk_range_seconds_bucket{le="+Inf"} 5.785815e+06
prometheus_tsdb_compaction_chunk_range_seconds_sum 1.0331562126854e+13
prometheus_tsdb_compaction_chunk_range_seconds_count 5.785815e+06

​ 与Summary类型的指标相似之处在于Histogram类型的样本同样会反应当前指标的记录的总数(以_count作为后缀)以及其值的总量(以_sum作为后缀)。不同在于Histogram指标直接反应了在不同区间内样本的个数,区间通过标签len进行定义。

​ 同时对于Histogram的指标,我们还可以通过histogram_quantile()函数计算出其值的分位数。不同在于Histogram通过histogram_quantile函数是在服务器端计算的分位数。 而Sumamry的分位数则是直接在客户端计算完成。因此对于分位数的计算而言,Summary在通过PromQL进行查询时有更好的性能表现,而Histogram则会消耗更多的资源。反之对于客户端而言Histogram消耗的资源更少。

2.3 初识PromQL

2.3.1 查询时间序列

​ 瞬时向量

PromQL支持使用`=`和`!=`两种完全匹配模式 
node_memory_MemAvailable_bytes{instance="10.30.162.194:9100"}
node_memory_MemAvailable_bytes{instance!="10.30.162.194:9100"}
  • 使用label=~regx表示选择那些标签符合正则表达式定义的时间序列;
  • 反之使用label!~regx进行排除;
node_memory_MemAvailable_bytes{job=~"nodes|Graylog"}
node_memory_MemAvailable_bytes{job!~"nodes|Graylog"}

2.3.2 查询区间(区间向量)

node_memory_MemAvailable_bytes{job!~"nodes|Graylog"}[5m]
  • s-秒
  • m-分
  • h-小时
  • d-天
  • w-周
  • y-年

2.3.3 时间位移操作

5分钟前的瞬时样本数据,或昨天一天的区间内的样本数据 :

node_memory_MemAvailable_bytes{job!~"nodes|Graylog"} offset 5m
node_memory_MemAvailable_bytes{job!~"nodes|Graylog"}[1h] offset 1h

2.3.4 使用聚合操作

# 查询系统所有http请求的总量
sum(http_request_total)

# 按照mode计算主机CPU的平均使用时间
avg(node_cpu) by (mode)

# 按照主机查询各个主机的CPU使用率
sum(sum(irate(node_cpu{mode!='idle'}[5m]))  / sum(irate(node_cpu[5m]))) by (instance)

2.3.5 标量(scalar)和字符串(string)

注意: 当使用表达式count(http_requests_total),返回的数据类型,依然是瞬时向量。用户可以通过内置函数scalar()将单个瞬时向量转换为标量。

2.3.6 合法的PromQL表达式

​ PromQL表达式都必须至少包含一个指标名称(例如http_request_total),或者一个不会匹配到空字符串的标签过滤器(例如{code="200"})。

​ 还可以使用 name 标签来指定监控指标名称;

2.4 操作符

2.4.1 数学运算符,布尔运算符,逻辑运算符等等。

​ 瞬时向量与标量之间进行数学运算时,数学运算符会依次作用域瞬时向量中的每一个样本值,从而得到一组新的时间序列。

node_memory_MemFree_bytes /(1024*1024*1024)

​ 瞬时向量与瞬时向量之间进行数学运算时 , 新的时间序列将不会包含指标名称

node_disk_read_time_seconds_total+node_disk_write_time_seconds_total

​ 使用bool修改符后,布尔运算不会对时间序列进行过滤,而是直接依次瞬时向量中的各个样本数据与标量的比较结果0或者1。从而形成一条新的时间序列

node_memory_MemFree_bytes /(1024*1024*1024) >bool 6

​ 同时需要注意的是,如果是在两个标量之间使用布尔运算,则必须使用bool修饰符

2==bool 2

2.4.2 集合运算符:

​ and or unless

2.4.3 操作符的优先级

  1. ^
  2. *, /, %
  3. +, -
  4. ==, !=, <=, <, >=, >
  5. and, unless
  6. or

2.4.4 匹配模式

​ 向量与向量之间进行运算操作时会基于默认的匹配规则:依次找到与左边向量元素匹配(标签完全一致)的右边向量元素进行运算,如果没找到匹配元素,则直接丢弃。

​ 一对一, 从操作符两边表达式获取的瞬时向量依次比较并找到唯一匹配(标签完全一致)的样本值。 两边不一致的情况下,可用on(label list)或ignoring(lable list)来修改标签的匹配行为。

有如下样本值:

method_code:http_errors:rate5m{method="get", code="500"}  24
method_code:http_errors:rate5m{method="get", code="404"}  30
method_code:http_errors:rate5m{method="put", code="501"}  3
method_code:http_errors:rate5m{method="post", code="500"} 6
method_code:http_errors:rate5m{method="post", code="404"} 21

method:http_requests:rate5m{method="get"}  600
method:http_requests:rate5m{method="del"}  34
method:http_requests:rate5m{method="post"} 120

​ 使用表达式

method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
{method="get"}  0.04            //  24 / 600
{method="post"} 0.05            //   6 / 120

​ 多对一和一对多, 必须使用group修饰符:group_left或者group_right来确定哪一个向量具有更高的基数(充当“多”的角色)。

​ 表达式和结果如下:

method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
结果如下:
{method="get", code="500"}  0.04            //  24 / 600
{method="get", code="404"}  0.05            //  30 / 600
{method="post", code="500"} 0.05            //   6 / 120
{method="post", code="404"} 0.175           //  21 / 120

提醒:group修饰符只能在比较和数学运算符中使用。在逻辑运算and,unless和or才注意操作中默认与右向量中的所有元素进行匹配。

2.5 PromQL聚合操作

  • sum (求和)

  • min (最小值)

  • max (最大值)

  • avg (平均值)

  • stddev (标准差)

  • stdvar (标准差异)

  • count (计数)

  • count_values (对value进行计数)

  • bottomk (后n条时序)

  • topk (前n条时序)

  • quantile (分布统计)

    聚合语法如下:

<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]

​ 其中只有count_values, quantile, topk, bottomk支持参数(parameter)。

这里面有by,without参数的使用。

​ 得到总量:

sum(prometheus_http_requests_total)
结果 :

{}                            11863
sum(prometheus_http_requests_total) without(instance)
等于
sum(prometheus_http_requests_total) by(code,job,handler)

​ count_values用于时间序列中每一个样本值出现的次数。count_values会为每一个唯一的样本值输出一个时间序列,并且每一个时间序列包含一个额外的标签

count_values("count",prometheus_http_requests_total)

1650435802037

​ topk和bottomk则用于对样本值进行排序,返回当前样本值前n位,或者后n位的时间序列 。

topk(5,prometheus_http_requests_total)

1650435959799

bottomk(5,prometheus_http_requests_total)

1650435997089

​ quantile用于计算当前样本数据值的分布情况quantile(φ, express)其中0 ≤ φ ≤ 1。φ 为分位数。

示例如下:

quantile(0.5, http_requests_total)

2.6 内置函数

样本值:value 指标:metrics instant-vector: instant range-vector: range

**注意:**参数类型,instant,range

instant-vector

https://icloudnative.io/prometheus/3-prometheus/functions.html

2.6.0 函数简介

1,abs(v instant-vector):绝对值;
abs(delta(node_memory_MemFree_bytes[5m]))
{instance="10.30.162.195:9100", job="node-test"}          10533187.368421052
2,absent(v instant-vector),absent_over_time(v rang-vector)

​ 如果v有value,返回空,如果没有value,则返回没有指标名但带有标签的时间序列,值为1;适合用于报警;

absent(node_boot_time_seconds{instance="10.30.162.195:9100", job="node-test"}) ==> no data
##
absent(node_boot_time_seconds{instance="10.30.162.195:9100", job="node"}) 
结果:{instance="10.30.162.195:9100", job="node"}    1
absent_over_time(prometheus_http_requests_total{job="test"}[10m])
{job="test"}     1
3,ceil(v instant-vector)

​ 将样本值四舍五入为整数;

​ **floor(v instant),**向下取整;

changes(v rang-vector)

返回这个区间向量每个value变化的次数;

changes(prometheus_http_requests_total[10m])
4,clamp(v instant,min scalar,max scalar)

clamp_max(v instant,max scalar):value>max,则为max clamp_min(v instant,min scalar): value<min则为min

	max>value>=min    value=min
​	value>max         value=max
​	max < min	 	#输出为空
clamp(changes(prometheus_http_requests_total[10m]),2,50)
5,时间

day_of_month(v=vector(time()),instant) 返回当月的第几天; day_of_week(v=vector(time()),instant) day_of_year(v=vector(time()),instant) days _in_month(v=vector(time()),instant),返回当月有多少天; hour(v=vector(time()),instant),当前第几个小时 minute(v=vector(time()),instant), month(v=vector(time()),instant), year(v=vector(time()),instant),

day_of_month(node_boot_time_seconds )
day_of_week(node_boot_time_seconds )
day_of_week(node_boot_time_seconds )##新增函数,旧版本没有
day_of_week(node_boot_time_seconds )
delta() ,idelta()

​ 返回区间向量中第一个值与j最后一个值之间的差值,及时value为整数,得到的值也可能不是整数;最后一个减第一个值 delta(v range):第一个值与j最后一个值之间的差值 idelta(v range),最新两个value之前的差值,

delta(node_memory_MemFree_bytes[10m])
idelta(node_memory_MemFree_bytes[10m])
6,deriv(v range)

​ 使用简单线性回归计算范围向量 V 中时间序列的每秒导数。范围向量必须至少有两个样本才能执行计算。当在距离矢量中找到 +Inf 或 -Inf 时,计算的斜率和偏移值将为 NaN.一般用于Gauge

deriv(node_memory_MemFree_bytes[20m])  ##y=kx+b,中的k
7,exp(v instant)

​ 返回各个样本值的 e 的指数值 ;

exp(prometheus_http_requests_total)
8,histogram_quantile()

histogram_quantile(φ float, b instant-vector)

9, holt_winters()

holt_winters(v range-vector, sf scalar, tf scalar) 函数基于区间向量 v,生成时间序列数据平滑值。平滑因子 sf 越低, 对旧数据的重视程度越高。趋势因子 tf 越高,对数据的趋势的考虑就越多。其中,0< sf, tf <=1

10,increase(v range)

​ rate( v range),irate(v range)下面有介绍

​ 获取区间中的第一个值 和最后一个值,返回其示增长量,只用于count类型;

11,label_join()

​ label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...)

​ 增加标签des_label, des_label的值为src_label_1的值+separator+src_label_2的值。。。

label_join(up{instance="localhost:9090", job="prometheus"},"test",",","instance","job")
#结果:
up{instance="localhost:9090", job="prometheus", test="localhost:9090,prometheus"}
12,label_replace()

label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)

label_replace(up,"host_port","$2","instance","(.*):(.*)")
#结果:##增加host_port标签名,标签值为instance以":"做为分割符的第二个值;
up{host_port="9100", instance="10.30.162.195:9100", job="node-test"} 		1
up{host_port="9090", instance="localhost:9090", job="prometheus"}  			1
13,predict_linear()
表达式:predict_linear(v range-vector, t time-scalar)
根据range-vector,估测t秒后的样本值;
#根2h的样本值,预测4个小时后磁盘剩余空间;
predict_linear(node_filesystem_free_bytes[2h],4*3600)
14,restets(v range)

count被重置的次数, 两个连续样本之间的值的减少被认为是一次计数器重置 ;使用数据类型:count

例:resets(node_filesystem_free_bytes[2h])
15,round(v instant,to_near scalar)

​ 返回向量中所有样本值的最接近to_near整数倍的整数 ;

round(node_filesystem_files,1024*1024) /(1024*1024)

16,scalar(node_filesystem_files_free)

​ 函数的参数是一个单元素的瞬时向量,它返回其唯一的时间序列的值作为一个标量。如果度量指标的样本数量大于 1 或者等于 0, 则返回 NaN

scalar(node_filesystem_files)
17,sort()
sort(v vector-instant):value升序;
sort_desc(v vector-instant):value降序;
例:
sort(node_filesystem_files)

18,time()

time():返回当前时间;
timestamp(v vector-instant):返回value的时间戳
19,aggregation_over_time()
  • avg_over_time(range-vector) : 区间向量内每个度量指标的平均值。
  • min_over_time(range-vector) : 区间向量内每个度量指标的最小值。
  • max_over_time(range-vector) : 区间向量内每个度量指标的最大值。
  • sum_over_time(range-vector) : 区间向量内每个度量指标的求和。
  • count_over_time(range-vector) : 区间向量内每个度量指标的样本数据个数。
  • quantile_over_time(scalar, range-vector) : 区间向量内每个度量指标的样本数据值分位数,φ-quantile (0 ≤ φ ≤ 1)。
  • stddev_over_time(range-vector) : 区间向量内每个度量指标的总体标准差。
  • stdvar_over_time(range-vector) : 区间向量内每个度量指标的总体标准方差。

2.6.1 示counter增长率

​ increase(v rang-vector):获取区间中第一个,最后一个的的值,计算增长率;

increase(prometheus_http_requests_total[2m])/120

​ rate (v range-vector)计算方法同样 ,更简单一些

rate(prometheus_http_requests_total[2m])

​ irate(v range-vector):取区间的最后两个值,来计算增长率,更准确的瞬时增长率;

irate(prometheus_http_requests_total[2m])

2.6.2 预测Gauge指标变化趋势

​ predict_linear(v range-vector,t scalar): predict_linear函数可以预测时间序列v在t秒后的值

predict_linear(node_filesystem_free_bytes[2h],4000*3600)/(1024*1024*1024)<0

2.6.3 Histogram指标分位数

​ histogram_quantile(φ float, b instant-vector) (0<φ<1)

histogram_quantile(0.5,prometheus_http_request_duration_seconds_bucket)

2.6.4 动态标签替换

格式如下:

label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)
label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...)

​ 实例:

label_replace(up, "host", "$1", "instance",  "(.*):.*")

2.6.5 其他内置函数

​ 官网文档;

2.7 在HTTP API中使用PromQL

2.7.1 瞬时数据查询

 ```bash

GET /api/v1/query ```

  • query=:PromQL表达式。
  • time=:用于指定用于计算PromQL的时间戳。可选参数,默认情况下使用当前系统时间。
  • timeout=:超时设置。可选参数,默认情况下使用-query,timeout的全局设置
# curl 'http://localhost:9090/api/v1/query?query=up'
{"status":"success","data":{"resultType":"vector","result":[{"metric":{"__name__":"up","instance":"10.30.162.192:9100","job":"promethues-node-exporter"},"value":[1650525415.782,"1"].....}
{"status":"success","data":
 {"resultType":"vector",
  "result":[{"metric":{"__name__":"up","instance":"10.30.162.192:9100","job":"promethues-node-exporter"},"
             value":[1650525415.782,"1"].....}

​ 根返回的数据类型不同,返回的result也有所不同:

​ 瞬时向量:vetor

[
  {
    "metric": { "<label_name>": "<label_value>", ... },
    "value": [ <unix_time>, "<sample_value>" ]
  },
  ...
]

​ 区间向量:matrix

[
  {
    "metric": { "<label_name>": "<label_value>", ... },
    "values": [ [ <unix_time>, "<sample_value>" ], ... ]
  },
  ...
]

​ 标量:scalar

[ <unix_time>, "<scalar_value>" ]

​ 字符串:string

[ <unix_time>, "<string_value>" ]

2.7.2 区间数据查询

格式:

GET /api/v1/query_range
  • query=: PromQL表达式。
  • start=: 起始时间。
  • end=: 结束时间。
  • step=: 查询步长。
  • timeout=: 超时设置。可选参数,默认情况下使用-query,timeout的全局设置。

结果格式如下:

{
  "resultType": "matrix",
  "result": <value>
}

up在30秒内,以15秒为间隔

# curl 'http://localhost:9090/api/v1/query_range?query=up&start=2022-04-20T20:10:30.781Z&end=2022-04-20T20:11:00.781Z&step=15s'

结果如下:

{"status":"success","data":{"resultType":"matrix","result":[{"metric":{"__name__":"up","instance":"10.30.162.192:9100","job":"promethues-node-exporter"},"values":[[1650485430.781,"1"],[1650485445.781,"1"],[1650485460.781,"1"]]},{"metric":{"__name__":"up","instance":"10.30.162.194:9100","job":"nodes"},"values":[[1650485430.781,"1"],[1650485445.781,"1"],[1650485460.781,"1"]]},{"metric":{"__name__":"up","instance":"10.30.162.195:9100","job":"nodes"},"values":[[1650485430.781,"1"],[1650485445.781,"1"],[1650485460.781,"1"]]},{"metric":{"__name__":"up","instance":"10.30.162.198:9100","job":"nodes"},"values":[[1650485430.781,"1"],[1650485445.781,"1"],[1650485460.781,"1"]]},{"metric":{"__name__":"up","instance":"10.30.162.60:9100","job":"Graylog"},"values":[[1650485430.781,"1"],[1650485445.781,"1"],[1650485460.781,"1"]]},{"metric":{"__name__":"up","instance":"10.30.162.63:9100","job":"CentOS-TEST01"},"values":[[1650485430.781,"1"],[1650485445.781,"1"],[1650485460.781,"1"]]},{"metric":{"__name__":"up","instance":"localhost:9090","job":"prometheus"},"values":[[1650485430.781,"1"],[1650485445.781,"1"],[1650485460.781,"1"]]}]}}

2,8 ,最佳实践

2.8.1监控所有

级别监控什么Exporter
网络网络协议:http、dns、tcp、icmp;网络硬件:路由器,交换机等BlockBox Exporter;SNMP Exporter
主机资源用量node exporter
容器资源用量cAdvisor
应用(包括Library)延迟,错误,QPS,内部状态等代码中集成Prmometheus Client
中间件状态资源用量,以及服务状态代码中集成Prmometheus Client
编排工具集群资源用量,调度等Kubernetes Component

2.8.2 四个黄金指标

  • 延迟:服务请求所需时间。

  • 通讯量:监控当前系统的流量,用于衡量服务的容量需求。

  • 错误:监控当前系统所有发生的错误请求,衡量当前系统错误发生的速率。

  • 饱和度:衡量当前服务的饱和度。

2.8.3 RED方法

​ RED方法是Weave Cloud在基于Google的“4个黄金指标”的原则下结合Prometheus以及Kubernetes容器实践,细化和总结的方法论,特别适合于云原生应用以及微服务架构应用的监控和度量。

  • (请求)速率:服务每秒接收的请求数。
  • (请求)错误:每秒失败的请求数。
  • (请求)耗时:每个请求的耗时。

2.8.4 USE方法

​ USE方法全称"Utilization Saturation and Errors Method"

  • 使用率:关注系统资源的使用情况。 这里的资源主要包括但不限于:CPU,内存,网络,磁盘等等。100%的使用率通常是系统性能瓶颈的标志。
  • 饱和度:例如CPU的平均运行排队长度,这里主要是针对资源的饱和度(注意,不同于4大黄金信号)。任何资源在某种程度上的饱和都可能导致系统性能的下降。
  • 错误:错误计数。例如:“网卡在数据包传输过程中检测到的以太网网络冲突了14次”。

2.9 prometheus数据模型和存储机制

2.9.1 数据模型DataModel

​ Prometheus 的监控数据以指标(metric)的形式保存在内置的时间序列数据库(TSDB)当中 .

指标名称和标签(metrics name+labels)

​ 每一条时间序列由指标名称以及一组标签唯一标识

样本(Sample)

三个组成部分:

指标(metric):指标名称Metric Name和标签Labels
时间戳(timestamp):一个精确到毫秒的时间点;
样本值(value):一个float64的浮点型数据;
##后加
Series 由很多相关的samples组成的时间序列;  
# 方便理解,如下三个样本
<-------------------- metric ------------------><-----timestamp-----><--value-->
<--- metric name---><--------labels------------><-----timestamp-----><--value-->
http_request_total{status="200", method="GET"}@1434417560938 => 94355
http_request_total{status="200", method="GET"}@1434417561287 => 94334
http_request_total{status="200", method="POST"}@1434417561287 => 93656

​ 根据时间顺序,把样本数据放在一起,就可以形成一条曲线,如下: 1669789333824

​ 特定的metric、timestamp、value构成的时间序列(TimeSeries) 在Prometheus中被称作==Series==。

2.9.2 Prometheus中Samples和Series的监控

##查看每少收到samples数量;超10万,可以考虑分片拆分;
rate(prometheus_tsdb_head_samples_appended_total[5m])
##Prometheus内存中最新的一次的series数量,也可以理解时间序列的数量 ;
prometheus_tsdb_head_series

查询所有时间序列的方法

#查询所有时间序列Series
{__name__=~".+"}
#统计所有时间序列Series的数量
count({__name__=~".+"})

2.9.3 Prometheus存储机制[^20221130]

​ 为了查询效率,Prometheus将最近的数据保存在内存中,然后通过一个compactor定时将数据打包到磁盘, 数据在内存中最少保留2个小时(storage.tsdb.min-block-duration ), 压缩率在2小时时候达到最大值 。为了防止程序崩溃,实现了WAL(write-ahead-log)机制。

img

​ 如上图, HeadBlock是数据库的内存部分,灰色块是存在磁盘上的不可更改的持久块Block。 我们有一个预写日志(WAL)用于持久写入。 传入的样本(粉红色方框)首先进入HeadBlock并在内存中停留一会儿,然后刷新到磁盘并映射到内存(蓝色的方框)。当这些内存映射 chunks 或内存中的 chunks 变旧到一定程度时,它们将作为持久块Block刷新到磁盘。 ​ 在Prometheus内部,chunk是用来存储压缩后的样本sample数据的最小单位。chunk的大小1KB,每个chunk可以存储最多120个样本,当chunk存满120个样本或超过了chunkRange的时间范围(默认情况为 2h),就会写到新的chunk里。 chunk写满以后,Prometheus会存入到磁盘,并使用MMAP做映射关系,来节省内存的消耗。如下。

img

Prometheus磁盘存储结构如下:

img

每个block又分为:

chunk dir:里面的chunk文件(最大512M)存储了具体的监控数据;
index:索引
meta.json:元数据文件,标识了一些基本信息
tombstones:标识了一些删除文件;

​ Prometheus默认会对旧的Block数据进行合并和压缩,以减少文件的数量 ,应该把监控数据备份到其他地方,重启Prometheus实例会加载历史数据,如果历史数据量很大,将会耗时长;

磁盘容量规划

通过对Prometheus使用磁盘目录的分析,每个Block占用磁盘空间主要有三部分:

Chunk数据 :241M
index数据:87M
WAL数据:3913M(历史数据)
index数据量比chunk总数据量比例是: 35:100 

​ 每2个小时生成一个block,先计算2小时内新增sample数量,

# 先计算2小时内新增sample数量13733662
$ increase(prometheus_tsdb_head_samples_appended_total[2h])

{container="prometheus", endpoint="web", instance="10.244.145.39:9090", job="prometheus-k8s", namespace="monitoring", pod="prometheus-k8s-1", service="prometheus-k8s"}
13733662.594142258
{container="prometheus", endpoint="web", instance="10.244.145.44:9090", job="prometheus-k8s", namespace="monitoring", pod="prometheus-k8s-0", service="prometheus-k8s"}
13733463.765690375
# sample平均大小,约1Btyes
$ rate(prometheus_tsdb_compaction_chunk_size_bytes_sum[1d])
/
  rate(prometheus_tsdb_compaction_chunk_samples_sum[1d])

{container="prometheus", endpoint="web", instance="10.244.145.39:9090", job="prometheus-k8s", namespace="monitoring", pod="prometheus-k8s-1", service="prometheus-k8s"}
0.9777944440923069
{container="prometheus", endpoint="web", instance="10.244.145.44:9090", job="prometheus-k8s", namespace="monitoring", pod="prometheus-k8s-0", service="prometheus-k8s"}
1.0713163056751385  

​ chunk数据占用存储空间=两小时内新增sample数量 * 每个sample平均大小 = 14M ​ index数据存储空间 = chunk数据占用存储空间* 35% =5M ​ 总磁盘占用量= (chunk数据占用存储空间 + index数据存储空间)*Block数量 + WAL磁盘存储空间(历史数据)

三,Prometheus告警处理

结构图:

Prometheus告警处理

​ Prometheus中,还可以通过Group(告警组)对一组相关的告警进行统一定义。当然这些定义都是通过YAML文件来统一管理的。 AlertManager还提供了静默和告警抑制机制来对告警通知行为进行优化。

3.1 Alertmanager特性

Alertmanager特性

3.1.1 分组

​ 如由于系统宕机导致大量的告警被同时触发,在这种情况下分组机制可以将这些被触发的告警合并为一个告警通知,避免一次性接受大量的告警通知,而无法对问题进行快速定位

​ 告警分组,告警时间,以及告警的接受方式可以通过Alertmanager的配置文件进行配置。

3.1.2 抑制

​ 当集群不可访问时触发了一次告警,通过配置Alertmanager可以忽略与该集群有关的其它所有告警。这样可以避免接收到大量与实际问题无关的告警通知。

​ 抑制机制同样通过Alertmanager的配置文件进行设置。

3.1.3 静默

​ 在web界面,让他闭嘴;

3.1.4 alert三种状态

img

Alert的三种状态:

  1. pending:警报被激活,但是低于配置的持续时间。这里的持续时间即rule里的FOR字段设置的时间。改状态下不发送报警。

  2. firing:警报已被激活,而且超出设置的持续时间。该状态下发送报警。

  3. inactive:既不是pending也不是firing的时候状态变为inactive

prometheus触发一条告警的过程:

prometheus--->触发阈值--->超出持续时间--->alertmanager--->分组|抑制|静默--->媒体类型--->邮件|钉钉|微信等

img

3.2 自定义告警规则

3.2.1 定义告警规则

groups:
  - name: node-alert
    rules:
    - alert: NodeDown
      expr: up{job="nodes"} == 0
      for: 5m
      labels:
        severity: critical
        instance: "{{ $labels.instance }}"
      annotations:
        summary: "instance: {{ $labels.instance }} down"
        description: "Instance: {{ $labels.instance }} 已经宕机 5分钟"
        value: "{{ $value }}"

如上图: 一条告警规则主要由以下几部分组成:

  • alert:告警规则的名称。

  • expr:基于PromQL表达式告警触发条件,用于计算是否有时间序列满足该条件。

  • for:评估等待时间,可选参数。用于表示只有当触发条件持续一段时间后才发送告警。在等待期间新产生告警的状态为pending。

  • labels:自定义标签,允许用户指定要附加到告警上的一组附加标签。

  • annotations:用于指定一组附加信息,比如用于描述告警详细信息的文字等,annotations的内容在告警产生时会一同作为参数发送到Alertmanager

    模板化: 通过$labels.变量可以访问当前告警实例中指定标签的值。$value则可以获取当前PromQL表达式计算的样本值。

​ 须要能过promethues server的配置文件到指定rules目录的路径,默认Promethues每分钟会对这些告警计算,两样通过server的配置文件可以修改。如下图:

  • 1650610706523

3.3 部署Alertmanager

​ 下载文件,解压

# wget https://github.com/prometheus/alertmanager/releases/download/v0.24.0/alertmanager-0.24.0.linux-amd64.tar.gz
tar -xf 
mv ... alertmanager

​ 改成服务,添加开机启动项

[root@prometheus02 system]# cat alertmanager.service 
[Unit]
Description=prometheus
After=network.target
[Service]
ExecStart=/usr/bin/nohup /usr/local/alertmanager/alertmanager --config.file=/usr/local/alertmanager/alertmanager.yml --storage.path=/usr/local/alertmanager/data/
Restart=on-failure
[Install]
WantedBy=multi-user.target

​ 访问:http://ip:9093

3.4 Alertmanage 配置概述

3.4.1 配置文件主要分为以下几个部分:

  • 全局配置(global):用于定义一些全局的公共参数,如全局的SMTP配置,Slack配置等内容;
  • 模板(templates):用于定义告警通知时的模板,如HTML模板,邮件模板等;
  • 告警路由(route):根据标签匹配,确定当前告警应该如何处理;
  • 接收人(receivers):接收人是一个抽象的概念,它可以是一个邮箱也可以是微信,Slack或者Webhook等,接收人一般配合告警路由使用;
  • 抑制规则(inhibit_rules):合理设置抑制规则可以减少垃圾告警的产生

3.5 基于标签的告警路由

​ 在Alertmanager的配置中会定义一个基于标签匹配规则的告警路由树;

​ 如下,默认配置文件 中的路由:

route:
 group_by: ['alertname']
 group_wait: 30s
 group_interval: 5m
 repeat_interval: 1h
 receiver: 'web.hook'
receivers:
 - name: 'web.hook'
   webhook_configs:
     - url: 'http://127.0.0.1:5001/'

3.5.1 路由匹配

​ 每一个警告都会经过顶级路由进入路由树,顶级路由必须匹配所有规则(不能有任何的match和match_re个人感觉是空接口), 每一个路由都可以定义自己的接受人以及匹配规则。默认情况下,告警进入到顶级route后会遍历所有的子节点,直到找到最深的匹配route,并将告警发送到该route定义的receiver中。但如果route中设置continue的值为false,那么告警在匹配到第一个子节点之后就直接停止。

​ 匹配有两种方式:

​ 一 ,基于字符串验证,match

​ 二, 基于正则表达式: match_re

​ 设置发送警告通知之前要等待时间,则通过repeat_interval设置

match:
  [ <labelname>: <labelvalue>, ... ]

match_re:
  [ <labelname>: <regex>, ... ]

3.5.2 告警分组

​ 分组规则: 通过group_by, 基于告警中包含的标签 ,group_wait参数设置等待时间,如果在当前的等待时间内,group收到新告警,会合并成一个发送给receiver.

group_interval配置,则用于定义相同的Group之间发送告警通知的时间间隔。

如下例子:

route:
  receiver: 'default-receiver'  ##接收所告警
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  group_by: [cluster, alertname]
  routes:
  - receiver: 'database-pager'
    group_wait: 10s
    match_re:
      service: mysql|cassandra
  - receiver: 'frontend-pager'
    group_by: [product, environment]
    match:
      team: frontend    ## 分组中如果有team,且值为frontend

3.6 receiver

​ 如下:revceiver有多种的通知方式

name: <string>
email_configs:
  [ - <email_config>, ... ]
hipchat_configs:
  [ - <hipchat_config>, ... ]
pagerduty_configs:
  [ - <pagerduty_config>, ... ]
pushover_configs:
  [ - <pushover_config>, ... ]
slack_configs:
  [ - <slack_config>, ... ]
opsgenie_configs:
  [ - <opsgenie_config>, ... ]
webhook_configs:
  [ - <webhook_config>, ... ]
victorops_configs:
  [ - <victorops_config>, ... ]

一配置文件 邮箱

global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.qiye.163.com:25'
  smtp_from: 'zabbix-server@leadchina.cn'
  smtp_auth_username: 'zabbix-server@leadchina.cn'
  smtp_auth_password: 'Leadchina@147258'
  smtp_require_tls: true

templates:
  - './template/*.tmpl'
route:
  group_by: ['alertname','cluster','service']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 10m
  receiver: 'default-receiver'
receivers:
- name: 'default-receiver'
  email_configs:
  - to: 'weijie.wang@leadchina.cn'
    send_resolved: true
#    html: '{{ template "__alertmanager" . }}'
    html: '{{ template "email.default.html" . }}'
    headers: { Subject: "Prometheus 告警邮件" }

企业微信:

例文:

global:
  resolve_timeout: 10m
  wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
  wechat_api_secret: '应用的secret,在应用的配置页面可以看到'
  wechat_api_corp_id: '企业id,在企业的配置页面可以看到'
templates:
- '/etc/alertmanager/config/*.tmpl'
route:
  group_by: ['alertname']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 12h
  routes:
  - receiver: 'wechat'
    continue: true
inhibit_rules:
- source_match:
receivers:
- name: 'wechat'
  wechat_configs:
  - send_resolved: false
    corp_id: '企业id,在企业的配置页面可以看到'
    to_user: '@all'
    to_party: ' PartyID1 | PartyID2 '
    message: '{{ template "wechat.default.message" . }}'
    agent_id: '应用的AgentId,在应用的配置页面可以看到'
    api_secret: '应用的secret,在应用的配置页面可以看到'

配置模板如下:

{{ define "wechat.default.message" }}
{{- if gt (len .Alerts.Firing) 0 -}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index 0 -}}
告警类型: {{ $alert.Labels.alertname }}
告警级别: {{ $alert.Labels.severity }}

=====================
{{- end }}
===告警详情===
告警详情: {{ $alert.Annotations.message }}
故障时间: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
===参考信息===
{{ if gt (len $alert.Labels.instance) 0 -}}故障实例ip: {{ $alert.Labels.instance }};{{- end -}}
{{- if gt (len $alert.Labels.namespace) 0 -}}故障实例所在namespace: {{ $alert.Labels.namespace }};{{- end -}}
{{- if gt (len $alert.Labels.node) 0 -}}故障物理机ip: {{ $alert.Labels.node }};{{- end -}}
{{- if gt (len $alert.Labels.pod_name) 0 -}}故障pod名称: {{ $alert.Labels.pod_name }}{{- end }}
=====================
{{- end }}
{{- end }}

{{- if gt (len .Alerts.Resolved) 0 -}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index 0 -}}
告警类型: {{ $alert.Labels.alertname }}
告警级别: {{ $alert.Labels.severity }}

=====================
{{- end }}
===告警详情===
告警详情: {{ $alert.Annotations.message }}
故障时间: {{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
恢复时间: {{ $alert.EndsAt.Format "2006-01-02 15:04:05" }}
===参考信息===
{{ if gt (len $alert.Labels.instance) 0 -}}故障实例ip: {{ $alert.Labels.instance }};{{- end -}}
{{- if gt (len $alert.Labels.namespace) 0 -}}故障实例所在namespace: {{ $alert.Labels.namespace }};{{- end -}}
{{- if gt (len $alert.Labels.node) 0 -}}故障物理机ip: {{ $alert.Labels.node }};{{- end -}}
{{- if gt (len $alert.Labels.pod_name) 0 -}}故障pod名称: {{ $alert.Labels.pod_name }};{{- end }}
=====================
{{- end }}
{{- end }}
{{- end }}

​ Prometheus通过Recoding Rule规则支持这种后台计算的方式,可以实现对复杂查询的性能优化,提高查询效率。

Recording Rule其中的一个

groups:
  - name: node-record
    rules:
    #system
    - record: node:up
      expr: up{job="nodes"}
      labels:
        job: "nodes"
        unit: 
        desc: "节点是否在线,在线1,不在线0"

Alert Rule

groups:
  - name: node-alert
    rules:
    - alert: NodeDown
      expr: up{job="nodes"} == 0
      for: 1m
      labels:
        severity: critical
        instance: "{{ $labels.instance }}"
      annotations:

3.7 Alertmanager高可用搭建

日期:230222

$ groupadd alertmanager
$ useradd -g alertmanager -s /sbin/nologin alertmanager
$ mkdir -p /data/alertmanager_data
$ vim /usr/lib/systemd/system/alertmanager.service
[Unit]
Description=alertmanager
Documentation=https://github.com/prometheus/alertmanager
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/alertmanager/alertmanager \
--config.file="/usr/local/alertmanager/alertmanager.yml" \
--web.listen-address=":9093" \
--data.retention=48h \
--storage.path="/data/alertmanager" \
--cluster.listen-address="0.0.0.0:9083" \
--log.level=debug \
> logs/alertmanager.out 2>&1 &

Restart=on-failure
[Install]
WantedBy=multi-user.target


--config.file="/usr/local/alertmanager/alertmanager.yml" \
--web.listen-address=":9093" \
--data.retention=48h \
--storage.path="/data/alertmanager" \
--cluster.listen-address="0.0.0.0:9083" \
--log.level=debug \
> logs/alertmanager.out 2>&1 &
[Unit]
Description=alertmanager
Documentation=https://github.com/prometheus/alertmanager
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/alertmanager/alertmanager \
--config.file=/usr/local/alertmanager/alertmanager.yml \
--web.listen-address=:9093 \
--data.retention=48h \
--storage.path=/usr/local/alertmanager/data/ \
--cluster.listen-address=10.30.162.48:9083 \
--log.level=debug >> /var/log/alertmanager.out 2>&1

Restart=on-failure

[Install]
WantedBy=multi-user.target

/usr/local/alertmanager/alertmanager \
--config.file=/usr/local/alertmanager/alertmanager.yml \
--web.listen-address=:9093 \
--data.retention=48h \
--storage.path=/usr/local/alertmanager/data/ \
--cluster.listen-address=0.0.0.0:9083 \
--cluster.peer=10.30.162.48:9083 \
--log.level=debug >> /var/log/alertmanager.out 2>&1

k8s alertmanager

apiVersion: v1
kind: Service
metadata:
  name: alertmanager-divine-soldier
  namespace: monitoring
spec:
  type: ClusterIP
  ports:
  - port: 9093
    name: alertmanager
    protocol: TCP
    targetPort: 9093

---
apiVersion: v1
kind: Endpoints
metadata:
  name: alertmanager-divine-soldier
subsets:
- addresses:
  - ip: 10.30.162.195
  - ip: 10.30.162.48
  - ip: 10.30.162.198
  ports:
  - port: 9093
    name: alertmanager
    protocol: TCP

3.8 Prometheus联邦

四 Exporter详解

4.1 简介

范围常用Exporter
数据库MySQL Exporter, Redis Exporter, MongoDB Exporter, MSSQL Exporter等
硬件Apcupsd Exporter,IoT Edison Exporter, IPMI Exporter, Node Exporter等
消息队列Beanstalkd Exporter, Kafka Exporter, NSQ Exporter, RabbitMQ Exporter等
存储Ceph Exporter, Gluster Exporter, HDFS Exporter, ScaleIO Exporter等
HTTP服务Apache Exporter, HAProxy Exporter, Nginx Exporter等
API服务AWS ECS Exporter, Docker Cloud Exporter, Docker Hub Exporter, GitHub Exporter等
日志Fluentd Exporter, Grok Exporter等
监控系统Collectd Exporter, Graphite Exporter, InfluxDB Exporter, Nagios Exporter, SNMP Exporter等
其它Blockbox Exporter, JIRA Exporter, Jenkins Exporter, Confluence Exporter等

4.1.2 运行方式

​ 独立运行:手动安装exporter,exporter做中间人的角色;

​ 集成到应用中:提前已经集成到应用中;

4.1.3 Exporter的规范

​ 分成三个部分: HELP(注释) TYPE(类型定义),样本,TYPE一定要在样本之前,

# HELP go_memstats_mallocs_total Total number of mallocs.
# TYPE go_memstats_mallocs_total counter
go_memstats_mallocs_total 55424

对于histogramt和summary:

  • 类型为summary或者histogram的指标x,该指标所有样本的值的总和需要使用一个单独的x_sum指标表示。
  • 类型为summary或者histogram的指标x,该指标所有样本的总数需要使用一个单独的x_count指标表示。
  • 对于类型为summary的指标x,其不同分位数quantile所代表的样本,需要使用单独的x{quantile="y"}表示。
  • 对于类型histogram的指标x为了表示其样本的分布情况,每一个分布需要使用x_bucket{le="y"}表示,其中y为当前分布的上位数。同时必须包含一个样本x_bucket{le="+Inf"},并且其样本值必须和x_count相同。
  • 对于histogram和summary的样本,必须按照分位数quantile和分布le的值的递增顺序排序。

4.1.4 指定样本格式的版本(看不懂)

Exporter响应的HTTP头信息中,可以通过Content-Type指定特定的规范版本

HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Length: 2906
Content-Type: text/plain; version=0.0.4
Date: Sat, 17 Mar 2018 08:47:06 GMT

4.2 常用Exporter

4.2.1 docker---CAdvisor

​ CAdvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具 .

安装如下

docker run \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:rw \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --publish=8080:8080 \
  --detach=true \
  --name=cadvisor \
  google/cadvisor:latest

访问: http://ip:8080

​ CAdvisor默认只保存2分钟的监控数据, CAdvisor已经内置了对Prometheus的支持。

​ 直接访问:http://IP:8080/metrics http://10.30.162.64:8080/metrics

​ 修改promethues.yml文件,添加任务主机

  - job_name: "CAdvisor"
    static_configs:
      - targets: ["10.30.162.64:8080"]

1650961758388

​ 简单几个样本查看,metrics前面都container的标识

可以通过以下表达式计算容器的CPU使用率:

sum(irate(container_cpu_usage_seconds_total{image!=""}[1m])) without (cpu)

查询容器内存使用量(单位:字节):

container_memory_usage_bytes{image!=""}

查询容器网络接收量速率(单位:字节/秒):

sum(rate(container_network_receive_bytes_total{image!=""}[1m])) without (interface)

查询容器网络传输量速率(单位:字节/秒):

sum(rate(container_network_transmit_bytes_total{image!=""}[1m])) without (interface)

查询容器文件系统读取速率(单位:字节/秒):

sum(rate(container_fs_reads_bytes_total{image!=""}[1m])) without (device)

查询容器文件系统写入速率(单位:字节/秒):

sum(rate(container_fs_writes_bytes_total{image!=""}[1m])) without (device)

4.2.2 mysql-exporter

1,下载 安装 :
##添加配置文件并编辑
[root@localhost mysql_exporter]# cat localhost_db.cnf 
[client]
user=mysqld_exporter
password=12345678
编辑文件,添加为服务:
[root@localhost system]# cat mysql_exporter.service
[Unit]
Description=prometheus
After=network.target
[Service]
ExecStart=/data/mysql_exporter/mysqld_exporter --config.my-cnf=/data/mysql_exporter/localhost_db.cnf
Restart=on-failure
[Install]
WantedBy=multi-user.target
2,使用方面:
mysql_global_status_questions反映当前Questions计数器的大小 

1651728596452

查看当前MySQL实例写操作速率的变化情况:

sum(rate(mysql_global_status_commands_total{command=~"insert|update|delete"}[2m])) without (command)

1651728714203

3,连接数

下面列举了与MySQL连接相关的监控指标:

  • mysql_global_variables_max_connections: 允许的最大连接数;
  • mysql_global_status_threads_connected: 当前开放的连接;
  • mysql_global_status_threads_running:当前开放的连接;
  • mysql_global_status_aborted_connects:当前开放的连接;
  • mysql_global_status_connection_errors_total{error="max_connections"}:由于超出最大连接数导致的错误;
  • mysql_global_status_connection_errors_total{error="internal"}:由于系统内部导致的错误;
4,监控缓冲澉使用情况

​ 查看buffer_pool_read的使用数量

# HELP mysql_global_status_innodb_buffer_pool_read_requests Generic metric from SHOW GLOBAL STATUS.
# TYPE mysql_global_status_innodb_buffer_pool_read_requests untyped
mysql_global_status_innodb_buffer_pool_read_requests 1.821222609e+09

计算2分钟内磁盘读取请求次数的增长率的变化情况

rate(mysql_global_status_innodb_buffer_pool_reads[2m])

1651728993514

5,查询性能

Slow_queries的计数器

# HELP mysql_global_status_slow_queries Generic metric from SHOW GLOBAL STATUS.
# TYPE mysql_global_status_slow_queries untyped
mysql_global_status_slow_queries 0

增长率:

irate(mysql_global_status_slow_queries[2m])

4.2.3 网络探测:Black_Exporter

​ 1,相对白盒监控,黑盒监控即以用户身份测试服务的外部可见性,常见的黑盒监控包括HTTP探针,TCP探针等用于检测站点或者服务的可以访问性,以及访问效率等。

黑盒监控和白盒监控

2,配置文件

​ Blackbox Exporter每一个探针的配置称为一个module,module包含:探针类型:prober,timeout,,以及当前探针的具体配置选项;格式如下:

 # 探针类型:http、 tcp、 dns、 icmp.
  prober: <prober_string>

  # 超时时间
  [ timeout: <duration> ]

  # 探针的详细配置,最多只能配置其中的一个
  [ http: <http_probe> ]
  [ tcp: <tcp_probe> ]
  [ dns: <dns_probe> ]
  [ icmp: <icmp_probe> ]

官方提供一个简单配置文件 如下:,默认配置文件在压缩包里有:

modules:
  http_2xx:
    prober: http
    http:
      method: GET
  http_post_2xx:
    prober: http
    http:
      method: POST

​ 启动 blackbax_exporter

访问: http://10.30.162.192:9115/probe?module=http_2xx&target=baidu.com ,可以看到dns响应等metrics

3,与Prometheus集成

​ 修改Prometheus配置文件 ,添加如下内容:

  - job_name: baidu_http2xx_probe
    params:
      module:
      - http_2xx
      target:
      - baidu.com
    metrics_path: /probe
    static_configs:
    - targets:
      - 10.30.162.192:9115
  - job_name: prometheus_http2xx_probe
    params:
      module:
      - http_2xx
      target:
      - prometheus.io
    metrics_path: /probe
    static_configs:
    - targets:
      - 10.30.162.192:9115

​ 以下 是官方提供,N个站点,M种探测方式,如下配置的话,须要N*M个采集任务;采用 Prometheus的Relabeling能力,这里我们也可以采用Relabling的方式对这些配置进行简化 ;如下:

scrape_configs:
  - job_name: 'blackbox'    #只有一个任务
    metrics_path: /probe
    params:
      module: [http_2xx]     #探针
    static_configs:
      - targets:
        - http://prometheus.io    # Target to probe with http.
        - https://prometheus.io   # Target to probe with https.
        - http://example.com:8080 # Target to probe with http on port 8080.
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: 127.0.0.1:9115

​ 在采集样本数据之前通过relabel_configs对采集任务进行动态设置 ,一个采集任务

  • 第1步,根据Target实例的地址,写入__param_target标签中。__param_形式的标签表示,在采集任务时会在请求目标地址中添加``参数,等同于params的设置;

  • 第2步,获取__param_target的值,并覆写到instance标签中;

  • 第3步,覆写Target实例的__address__标签值为BlockBox Exporter实例的访问地址。

4,HTTP探针

​ 如下:

modules:
  http_2xx_example:
    prober: http
    http:

​ 如上,http配置选项中没有添加任何配置,表示完全使用HTTP探针的默认配置,使用GET的方式对目标服务进行探测,并验证返回状态吗是否为2XX,是则表示成功,否则失败;

5,自定义HTTP探针 请求方法(看不太懂)

​ 如下:用method定义了探测时使用的方法,通过header定义相关的请求头信息,使用body定义请求内容:

http_post_2xx:
    prober: http
    timeout: 5s
    http:
      method: POST
      headers:
        Content-Type: application/json
      body: '{}'

​ 如果HTTP采用了安全认证,如下:basic_auth:username,password

http_basic_auth_example:
    prober: http
    timeout: 5s
    http:
      method: POST
      headers:
        Host: "login.example.com"
      basic_auth:
        username: "username"
        password: "mysecret"

​ HTTPS,须要自定义证书服务,如下,通过tls_config指定相关的证书信息:

 http_custom_ca_example:
    prober: http
    http:
      method: GET
      tls_config:
        ca_file: "/certs/my_cert.crt"
6 ,自定义探针行为
用户需要指定HTTP返回状态码,或者对HTTP版本有特殊要求,如下所示,可以使用valid_http_versions和valid_status_codes进行定义 
  http_2xx_example:
    prober: http
    timeout: 5s
    http:
      valid_http_versions: ["HTTP/1.1", "HTTP/2"]
      valid_status_codes: []

​ 如果用户对于HTTP服务是否启用SSL有强制的标准,则使用fail_if_ssl和fail_if_not_ssl进行配置, fail_if_ssl为true时,表示如果站点启用了SSL则探针失败,反之成功 ,fail_if_not_ssl刚好相反。如下:

  http_2xx_example:
    prober: http
    timeout: 5s
    http:
      valid_status_codes: []
      method: GET
      no_follow_redirects: false
      fail_if_ssl: false
      fail_if_not_ssl: false

​ 还可以定义正则表达式来,fail_if_matches_regexp和fail_if_not_matches_regexp

http_2xx_example:
    prober: http
    timeout: 5s
    http:
      method: GET
      fail_if_matches_regexp:
        - "Could not connect to database"
      fail_if_not_matches_regexp:
        - "Download the latest version here"

​ 默认情况 下,HTTP探针为走IPV6协议,可以通过 preferred_ip_protocol=ip4强制通过IPV4的方式进行探测 ,

​ 除了支持对HTTP协议进行网络探测以外,Blackbox还支持对TCP、DNS、ICMP等其他网络协议

4.3 监控Redis

下载,运行文件 ,Redis有没有设置密码,有密码在程序运行时要加上密码,两个参数下:

-redis.addr -redis.password

cat redis_exporter.service
[Unit]
Description=redis_exporter
After=network.target

[Service]
Type=simple
User=prometheus
ExecStart=/data/redis_exporter/redis_exporter -redis.addr 172.26.42.229:6379  -redis.password 123456
Restart=on-failure

[Install]
WantedBy=multi-user.target

Promethues配置文件的修改

  - job_name: redis
  static_configs:
    - targets: ["10.30.xx.xx:9121"]
      labels:
        instance: redis120

4.3 监控域名和证书过期 (没有实践)

# 下载安装
wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.16.0/blackbox_exporter-0.16.0.linux-amd64.tar.gz
tar -xvf  blackbox_exporter-0.16.0.linux-amd64.tar.gz
mv blackbox_exporter-0.16.0.linux-amd64/ /data/redis_exporter

# 创建配置文件
cat > /data/black_exporter/black_exporter.yml << EOF
modules:
  http_2xx:
    prober: http
    timeout: 20s
    http:
      preferred_ip_protocol: "ip4"
  http_post_2xx_query:
    prober: http
    timeout: 20s
    http:
      preferred_ip_protocol: "ip4" ##使用ipv4
      method: POST
      headers:
        Content-Type: application/json ##header头
      body: '{"hmac":"","params":{"publicFundsKeyWords":"xxx"}}' ##传参
  tls_connect_tls:
    prober: tcp
    timeout: 5s
    tcp:
      tls: true
  tcp_connect:
    prober: tcp
    timeout: 5s
 #
  pop3s_banner:
    prober: tcp
    tcp:
      query_response:
      - expect: "^+OK"
      tls: true
      tls_config:
        insecure_skip_verify: false
  ssh_banner:
    prober: tcp
    tcp:
      query_response:
      - expect: "^SSH-2.0-"
  irc_banner:
    prober: tcp
    tcp:
      query_response:
      - send: "NICK prober"
      - send: "USER prober prober prober :prober"
      - expect: "PING :([^ ]+)"
        send: "PONG ${1}"
      - expect: "^:[^ ]+ 001"
  icmp:
    prober: icmp
    timeout: 20s
EOF

# 配置systemd
cat > /etc/systemd/system/blackbox_exporter.service <<EOF
[Unit]
Description=blackbox_exporter
Documentation=https://prometheus.io/
After=network.target

[Service]
Type=simple
User=prometheus
ExecStart=/data/blackbox_exporter/blackbox_exporter  --config.file=/data/blackbox_exporter/blackbox.yml
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

# 启动服务
systemctl enable blackbox_exporter.service 
systemctl start blackbox_exporter.service 
systemctl status blackbox_exporter.service 

# 配置Consul自动发现
cat > /data/consul/server1/config/blackbox-exporter.json <<EOF
{
    "service":{
        "name":"blackbox-exporter",
        "tags":[
            "prod",
            "blackbox-exporter"
        ],
        "address": "172.26.42.229",
        "port":9115,
        "check":{
            "http":"http://172.26.42.229:9115",
            "interval":"10s"
        },
        "token":"your_token"
    }
}
EOF
# 热加载Consul配置
consul reload
# Grafana导入Dashboard-ID:7587

五 Grafana(跳过)

六,集群和高可能

6.1 数据存储

6.1.1 本地存储

​ 时间单元为两个小时,每两个小时的数据打包成一块,存储到硬盘上,如块下面的目录结构:

[root@prometheus02 01G1KD1K826GEYCQPKJXPB88DE]# tree
.
|-- chunks      ##所有样本数据
|   `-- 000001
|-- index       ##索引文件
|-- meta.json   ##元数据文件
`-- tombstones  ##相当于回收站

1 directory, 4 files

​ 如果 在获取样本数据是出现问题,promethues启动时会从预写日志WAL(Write Ahead Log)进行重播,回复数据。通过API删除时间时间序列,删除的记录也会保存在单独的逻辑文件tombstones中。

image-20230331163615536

​ 提高查询数据的效率,删除历史数据时,给个时间界限,只要块在这个时间界限外,直接丢弃就好了。过期块的清理是在后台,删除块最多可能需要两个小时,块必须完全过期。

6.1.2 本地存储配置

用户可以通过命令行启动参数的方式修改本地存储的配置。

启动参数默认值含义
--storage.tsdb.pathdata/Base path for metrics storage
--storage.tsdb.retention15dHow long to retain samples in the storage
--storage.tsdb.min-block-duration2hThe timestamp range of head blocks after which they get persisted
--storage.tsdb.max-block-duration36hThe maximum timestamp range of compacted blocks,It's the minimum duration of any persisted block.
--storage.tsdb.no-lockfilefalseDo not create lockfile in data directory

服务器磁盘空间规划,可以用以下公式简单计算:

needed_disk_space = retention_time_seconds * ingested_samples_per_second * bytes_per_sample

6.1.3 从失败中恢复

​ 如果本地存储损坏,解决问题的最佳策略就是关闭proemthues,删除整个存储目录,也可以尝试删除单独的块或WAL目录来解决问题。

6.2 远程存储

​ 本地存储也意味着Prometheus无法持久化数据,无法存储大量历史数据,同时也无法灵活扩展和迁移。

​ remote_write和remote_write具体配置如下所示: (复制)

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> ]

​ 目前,第三方数据库支持Remote Storage的有:

6.2.2 实例 集成influxDB (测试)

​ influxDB官网提供:

cat <<EOF | sudo tee /etc/yum.repos.d/influxdb.repo
[influxdb]
name = InfluxDB Repository - RHEL \$releasever
baseurl = https://repos.influxdata.com/rhel/\$releasever/\$basearch/stable
enabled = 1
gpgcheck = 1
gpgkey = https://repos.influxdata.com/influxdb.key
EOF

sudo yum install influxdb2

​ 这里我用的influxdb,面不是用的influxdb2

下载rpm包,利用yun localinstall xxx.rpm

https://repos.influxdata.com/rhel/7Server/x86_64/stable/

# influx
>create database prometheus;
>show databases;

​ 修改prometheus配置文件

# 添加如下两行
remote_write:
  - url: "http://10.30.162.64:8086/api/v1/prom/write?db=prometheus"
remote_read:
  - url: "http://10.30.162.64:8086/api/v1/prom/read?db=prometheus"

重启prometheus服务,查看数据库中有没有数据

influx
>use prometheus
>show MEASUREMENTS;
# 可以看到相关的数据,简单实现远程存储数据

6.3 联邦集群

​ 如下图

联邦集群

​ 联邦集群的核心在于每一个Promethues Server都包含额一个用于获取当前实例中监控样本的接口(federate),对于Promethues Sever来说,无论是从其他的Prometheus实例还是Exporter实例中获取数据实际并没有差异。

​ 接口配置如下:官网,自己并未测试

scrape_configs:
  - job_name: 'federate'
    scrape_interval: 15s
    honor_labels: true
    metrics_path: '/federate'
    params:
      'match[]':
        - '{job="prometheus"}'
        - '{__name__=~"job:.*"}'
        - '{__name__=~"node.*"}'
    static_configs:
      - targets:
        - '192.168.77.11:9090'
        - '192.168.77.12:9090'

​ 可以对Prometheus进行功能分区,不再集群分区,扩展性。

  - job_name: 'federate'
    scrape_interval: 15s
    honor_labels: true
    metrics_path: '/federate'
    params:
      'match[]':
        - '{job="serviceMonitor/monitoring/node-exporter/0"}'
        - '{__name__=~"job:.*"}'
        - '{__name__=~"node.*"}'
    static_configs:
      - targets:
        - '10.30.162.64:30004'
    

6.4 Prometheus高可用

6.4.1基本HA

基本HA

6.4.2基本HA+远程存储

HA + Remote Storage

6.4.3基本HA+远程存储+联邦集群

基本HA + 远程存储 + 联邦集群 6.4.4 功能分区实例

Prometheus Server 配置

global:
  external_labels:
    slave: 1  # This is the 2nd slave. This prevents clashes between slaves.
scrape_configs:
  - job_name: some_job
    relabel_configs:
    - source_labels: [__address__]
      modulus:       4
      target_label:  __tmp_hash
      action:        hashmod
    - source_labels: [__tmp_hash]
      regex:         ^1$
      action:        keep

中心Prometheus Sever聚合任务配置

- scrape_config:
  - job_name: slaves
    honor_labels: true
    metrics_path: /federate
    params:
      match[]:
        - '{__name__=~"^slave:.*"}'   # Request all slave-level time series
    static_configs:
      - targets:
        - slave0:9090
        - slave1:9090
        - slave3:9090
        - slave4:9090

6.4.5 高可用方案

选项\需求服务可用性数据持久化水平扩展
主备HAvxx
远程存储xvx
联邦集群xxv

七、 kube-operator

​ Prometheus operator的本职就是一组用户自定义的CRD资源以及Controller的实现,Prometheus Operator负责监听这些自定义资源的变化,并且根据这些资源的定义自动化的完成如Prometheus Server自身以及配置的自动化管理工作。

自定义4类资源 :

  • Prometheus:声明式创建和管理Prometheus Server实例;
  • ServiceMonitor:负责声明式的管理监控配置;
  • PrometheusRule:负责声明式的管理告警配置;
  • Alertmanager:声明式的创建和管理Alertmanager实例。

img

上图是Prometheus-Operator官方提供的架构图,从下向上看,Operator可以部署并且管理Prometheus Server,并且Operator可以观察Prometheus,那么这个观察是什么意思呢,上图中Service1 - Service5其实就是kubernetes的service,kubernetes的资源分为Service、Deployment、ServiceMonitor、ConfigMap等等,所以上图中的Service和ServiceMonitor都是kubernetes资源,一个ServiceMonitor可以通过labelSelector的方式去匹配一类Service(一般来说,一个ServiceMonitor对应一个Service),Prometheus也可以通过labelSelector去匹配多个ServiceMonitor。

  • Operator : Operator是整个系统的主要控制器,会以Deployment的方式运行于Kubernetes集群上,并根据自定义资源(Custom Resources Definition)CRD 来负责管理与部署Prometheus,Operator会通过监听这些CRD的变化来做出相对应的处理。
  • Prometheus : Operator会观察集群内的Prometheus CRD(Prometheus 也是一种CRD)来创建一个合适的statefulset在monitoring(.metadata.namespace指定)命名空间,并且挂载了一个名为prometheus-k8s的Secret为Volume到/etc/prometheus/config目录,Secret的data包含了以下内容
    • configmaps.json指定了rule-files在configmap的名字
    • prometheus.yaml为主配置文件
  • ServiceMonitor : ServiceMonitor就是一种kubernetes自定义资源(CRD),Operator会通过监听ServiceMonitor的变化来动态生成Prometheus的配置文件中的Scrape targets,并让这些配置实时生效,operator通过将生成的job更新到上面的prometheus-k8s这个Secret的Data的prometheus.yaml字段里,然后prometheus这个pod里的sidecar容器prometheus-config-reloader当检测到挂载路径的文件发生改变后自动去执行HTTP Post请求到/api/-reload-路径去reload配置。该自定义资源(CRD)通过labels选取对应的Service,并让prometheus server通过选取的Service拉取对应的监控信息(metric)
  • Service :Service其实就是指kubernetes的service资源,这里特指Prometheus exporter的service,比如部署在kubernetes上的mysql-exporter的service

​ 想象一下,我们以传统的方式去监控一个mysql服务,首先需要安装mysql-exporter,获取mysql metrics,并且暴露一个端口,等待prometheus服务来拉取监控信息,然后去Prometheus Server的prometheus.yaml文件中在scarpe_config中添加mysql-exporter的job,配置mysql-exporter的地址和端口等信息,再然后,需要重启Prometheus服务,就完成添加一个mysql监控的任务

​ 现在我们以Prometheus-Operator的方式来部署Prometheus,当我们需要添加一个mysql监控我们会怎么做,首先第一步和传统方式一样,部署一个mysql-exporter来获取mysql监控项,然后编写一个ServiceMonitor通过labelSelector选择刚才部署的mysql-exporter,由于Operator在部署Prometheus的时候默认指定了Prometheus选择label为:prometheus: kube-prometheus的ServiceMonitor,所以只需要在ServiceMonitor上打上prometheus: kube-prometheus标签就可以被Prometheus选择了,完成以上两步就完成了对mysql的监控,不需要改Prometheus配置文件,也不需要重启Prometheus服务,是不是很方便,Operator观察到ServiceMonitor发生变化,会动态生成Prometheus配置文件,并保证配置文件实时生效

十二,k8s-Prometheus

Kerbenetes storageclass搭建

7.0 nfs server搭建

$ yum install nfs-utils rpcbind
$ cat /etc/exports
/data/nfs 10.30.162.0/24(rw,sync)
$ systemctl enable --now rpcbind ##有先后顺序
$ systemctl enable --now nfs
$ cat /var/lib/nfs/etab 
/data/nfs	10.30.162.0/24(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,no_pnfs,anonuid=65534,anongid=65534,sec=sys,rw,secure,root_squash,no_all_squash)
##测试:
$ showmount -e
Export list for localhost.localdomain:
/data/nfs 10.30.162.0/24

## 客户端操作:
$ yum install nfs-utils rpcbind
$ mount -t nfs 10.30.162.49:/data/nfs /share
#卸载
$ umount /share

7.2 使用RBAC进行授权:

修改两处为:apiVersion: rbac.authorization.k8s.io/v1
原文件为:  apiVersion: rbac.authorization.k8s.io/v1beta1
$ kubectl apply -f prometheus-rbac.yaml

7.3 Storage Class

下载相关文件:

$ git clone https://github.com/kubernetes-incubator/external-storage.git ##或者
$ git clone https://github.com/kubernetes-retired/external-storage.git

$ ls /root/external-storage-master/nfs-client/deploy
class.yaml           deployment.yaml      objects    test-claim.yaml
deployment-arm.yaml  deployment.yaml.bak  rbac.yaml  test-pod.yaml

部署权限

$ kubectl apply -f rbac.yaml  #默认文件,没有修改

rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch", "update"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["events"]
    verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-client-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["endpoints"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: leader-locking-nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
subjects:
  - kind: ServiceAccount
    name: nfs-client-provisioner
    # replace with namespace where provisioner is deployed
    namespace: default
roleRef:
  kind: Role
  name: leader-locking-nfs-client-provisioner
  apiGroup: rbac.authorization.k8s.io

部署插件:

$ kubectl apply -f deployment.yaml

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  labels:
    app: nfs-client-provisioner
  # replace with namespace where provisioner is deployed
  namespace: default
spec:
  replicas: 3
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: nfs-client-provisioner
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          #image: quay.io/external_storage/nfs-client-provisioner:latest
          #image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner:latest
          #坑
          image: registry.cn-hangzhou.aliyuncs.com/xzjs/nfs-subdir-external-provisioner:v4.0.0
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
            #要和部署class中的yaml文件中的一致;
              value: fuseim.pri/ifs
            - name: NFS_SERVER
            #见7.0中的nfs部署,中的地址,还有nfs目录
              value: 10.30.162.49
            - name: NFS_PATH
              value: /data/nfs
      volumes:
        - name: nfs-client-root
          nfs:
            server: 10.30.162.49
            path: /data/nfs

部署storageclass

$ kubectl apply -f class.yaml

$ kubectl get storageclasses.storage.k8s.io 
NAME                  PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage   fuseim.pri/ifs   Delete          Immediate           false                  12d

class.yaml,没有做修改

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-nfs-storage
provisioner: fuseim.pri/ifs # or choose another name, must match deployment's env PROVISIONER_NAME'
parameters:
  archiveOnDelete: "false"

测试

$ kubectl apply -f test-claim.yaml

$ [root@docker-k8s01 deploy]# kubectl get pvc
NAME         STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
test-claim   Bound    pvc-6351255f-c88e-4670-903d-ed65a60b2483   1Mi        RWX            managed-nfs-storage   36m

#pvc测试
$ kubectl apply -f test-pod.yaml
#可以去nfs服务器去查看nfs目录;

Prometheus部署

1,Prometheus-server部署

1.1 下载相关文件

$ git clone https://github.com/zhangdongdong7/k8s-prometheus.git
$ cd k8s-prometheus
$ ls
alertmanager-configmap.yaml         kube-state-metrics-rbac.yaml               prometheus-rbac.yaml
alertmanager-configmap.yaml.bak     kube-state-metrics-service.yaml            prometheus-rules.yaml
alertmanager-deployment.yaml        node_exporter-0.17.0.linux-amd64.tar.gz    prometheus-service.yaml
alertmanager-pvc.yaml               node_exporter-0.17.0.linux-amd64.tar.gz.1  prometheus-statefulset-static-pv.yaml
alertmanager-service.yaml           node_exporter.sh                           prometheus-statefulset.yaml
grafana.yaml                        OWNERS                                     prometheus-statefulset.yamlbak
kube-state-metrics-deployment.yaml  prometheus-configmap.yaml                  README.md

1.2 使用RBAC进行授权

[root@docker-k8s01 k8s-prometheus]# kubectl apply -f prometheus-rbac.yaml 
serviceaccount/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
# 没有修改任何内容;prometheus-server的配置文件;

1.3 配置管理

[root@docker-k8s01 k8s-prometheus]# kubectl apply -f prometheus-configmap.yaml

[root@docker-k8s01 k8s-prometheus]# kubectl get configmaps prometheus-config -n kube-system 
NAME                DATA   AGE
prometheus-config   1      14d
[root@docker-k8s01 k8s-prometheus]# vim prometheus-configmap.yaml
##修改主机IP地址:
…………
    - job_name: kubernetes-nodes
      scrape_interval: 30s
      static_configs:
      - targets:
        - 10.30.162.64:9100
        - 10.30.162.65:9100
        - 10.30.162.66:9100
…………

1.4 添加rules

#由于有状态部署Prometheus时,要用到rules,没有这个目录为直接报错;
[root@docker-k8s01 k8s-prometheus]# kubectl  apply -f prometheus-rules.yaml 

1.5 有状态部署prometheus

[root@docker-k8s01 k8s-prometheus]# kubectl  apply -f prometheus-statefulset.yaml
# 这里用到持久存储,之前搭建好的storageclass
[root@docker-k8s01 k8s-prometheus]# kubectl get storageclasses.storage.k8s.io 
NAME                  PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage   fuseim.pri/ifs   Delete          Immediate           false                  12d

[root@docker-k8s01 k8s-prometheus]# cat prometheus-statefulset.yaml
…………
  volumeClaimTemplates:
  - metadata:
      name: prometheus-data
    spec:
      storageClassName: managed-nfs-storage
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: "16Gi"
[root@docker-k8s01 k8s-prometheus]# kubectl get pods -n kube-system | grep prometheus
prometheus-0                               2/2     Running     0          19h

1.6 创建Service暴露端口访问

[root@docker-k8s01 k8s-prometheus]# kubectl  apply -f prometheus-service.yaml
[root@docker-k8s01 k8s-prometheus]# cat prometheus-service.yaml 
kind: Service
apiVersion: v1
metadata: 
  name: prometheus
  namespace: kube-system
  labels: 
    kubernetes.io/name: "Prometheus"
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: Reconcile
spec: 
  type: NodePort
  ports: 
    - name: http 
      port: 9090
      protocol: TCP
      targetPort: 9090
      nodePort: 30090  ##对外端口
  selector: 
    k8s-app: prometheus

2, 在k8s平台创建Grafana

##直接使用文件
[root@docker-k8s01 k8s-prometheus]# kubectl  apply -f grafana.yaml

3,监控K8S中的Pod,Node,资源对象的数据方法:

1)Pod kubelet的节点使用cAdvisor提供的metrics接口获取该节点所有Pod和容器相关的性能指标数据,安装kubelet默认就开启了 暴露接口地址:

https://NodeIP:10255/metrics/cadvisorhttps://NodeIP:10250/metrics/cadvisor

2)Node 需要使用node_exporter收集器采集节点资源利用率。

3)资源对象

使用metric-server

[root@docker-k8s01 k8s-prometheus]# cat node_exporter.sh 
#!/bin/bash
##这边文件已经下载好了,所以注释掉了
#wget https://github.com/prometheus/node_exporter/releases/download/v0.17.0/node_exporter-0.17.0.linux-amd64.tar.gz

tar zxf node_exporter-0.17.0.linux-amd64.tar.gz
mv node_exporter-0.17.0.linux-amd64 /usr/local/node_exporter

cat <<EOF >/usr/lib/systemd/system/node_exporter.service
[Unit]
Description=https://prometheus.io

[Service]
Restart=on-failure
ExecStart=/usr/local/node_exporter/node_exporter --collector.systemd --collector.systemd.unit-whitelist=(docker|kubelet|kube-proxy|flanneld).service

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable node_exporter
systemctl restart node_exporter
##在所有Node上安装node_exporter
$ ./node_exporter.sh
[root@docker-k8s02 ~]# systemctl status node_exporter.servic  ##查看服务状态;

3.2 部署metircs server

[root@docker-k8s01 k8s-prometheus]# ls | grep metric
kube-state-metrics-deployment.yaml
kube-state-metrics-rbac.yaml
kube-state-metrics-service.yaml
#创建rbac的yaml对metrics进行授权;
[root@docker-k8s01 k8s-prometheus]# kubectl apply -f kube-state-metrics-rbac.yaml
#对metric pod进行部署;
[root@docker-k8s01 k8s-prometheus]# kubectl apply -f kube-state-metrics-deployment.yaml
# service对外暴露端口
[root@docker-k8s01 k8s-prometheus]# kubectl apply -f kube-state-metrics-service.yaml
[root@docker-k8s01 k8s-prometheus]# kubectl get pod,svc -n kube-system
NAME                                           READY   STATUS             RESTARTS   AGE
pod/alertmanager-7cf4d5d7b8-p7lx7              2/2     Running            0          16h
pod/calico-kube-controllers-6949477b58-xqr7c   1/1     Running            0          74d
pod/calico-node-d9m27                          1/1     Running            0          74d
pod/calico-node-swxtv                          1/1     Running            0          74d
pod/calico-node-v5vp8                          1/1     Running            0          74d
pod/coredns-7f89b7bc75-2kf7q                   1/1     Running            0          74d
pod/coredns-7f89b7bc75-6trkg                   1/1     Running            0          74d
pod/etcd-docker-k8s01                          1/1     Running            0          74d
pod/fluentd-logging-test-hzlzd                 0/1     CrashLoopBackOff   8573       31d
pod/grafana-0                                  1/1     Running            0          19h
pod/kube-apiserver-docker-k8s01                1/1     Running            0          74d
pod/kube-controller-manager-docker-k8s01       1/1     Running            0          74d
pod/kube-proxy-dbtxh                           1/1     Running            0          74d
pod/kube-proxy-fklzd                           1/1     Running            0          74d
pod/kube-proxy-jbk6v                           1/1     Running            0          74d
pod/kube-scheduler-docker-k8s01                1/1     Running            0          74d
pod/kube-state-metrics-5dd5dc67fc-tp29m        2/2     Running            0          18h
pod/prometheus-0                               2/2     Running            0          19h

NAME                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
service/alertmanager         ClusterIP   10.10.227.79    <none>        80/TCP                   16h
service/grafana              NodePort    10.10.102.113   <none>        80:30091/TCP             19h
service/kube-dns             ClusterIP   10.10.0.10      <none>        53/UDP,53/TCP,9153/TCP   74d
service/kube-state-metrics   ClusterIP   10.10.254.80    <none>        8080/TCP,8081/TCP        18h
service/prometheus           NodePort    10.10.46.163    <none>        9090:30090/TCP           19h

4,在K8S中部署Alertmanager

4.1 configmap,增加alertmanager告警配置

[root@docker-k8s01 k8s-prometheus]# cat alertmanager-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: alertmanager-config
  namespace: kube-system
  labels:
    kubernetes.io/cluster-service: "true"
    addonmanager.kubernetes.io/mode: EnsureExists
data:
  alertmanager.yml: |
    global: 
      resolve_timeout: 5m
      smtp_smarthost: 'smtp.qiye.163.com:25'
      smtp_from: 'zabbix-server@leadchina.cn'
      smtp_auth_username: 'zabbix-server@leadchina.cn'
      smtp_auth_password: 'xxx'

    receivers:
    - name: default-receiver
      email_configs:
      - to: "xxx"

    route:
      group_interval: 1m
      group_wait: 10s
      receiver: default-receiver
      repeat_interval: 60m
[root@docker-k8s01 k8s-prometheus]# kubectl apply -f alertmanager-configmap.yaml

4.2 创建PVC,进行数据持久化,

[root@docker-k8s01 k8s-prometheus]# kubectl apply -f alertmanager-pvc.yaml

4.3部署alertmanager的Pod

#没做修改
[root@docker-k8s01 k8s-prometheus]# kubectl apply -f alertmanager-deployment.yaml

4.4 创建service对暴露端口

[root@docker-k8s01 k8s-prometheus]# kubectl apply -f alertmanager-service.yaml
[root@docker-k8s01 k8s-prometheus]# kubectl get pod,svc -n kube-system
NAME                                           READY   STATUS             RESTARTS   AGE
pod/alertmanager-7cf4d5d7b8-p7lx7              2/2     Running            0          16h
pod/calico-kube-controllers-6949477b58-xqr7c   1/1     Running            0          74d
pod/calico-node-d9m27                          1/1     Running            0          74d
pod/calico-node-swxtv                          1/1     Running            0          74d
pod/calico-node-v5vp8                          1/1     Running            0          74d
pod/coredns-7f89b7bc75-2kf7q                   1/1     Running            0          74d
pod/coredns-7f89b7bc75-6trkg                   1/1     Running            0          74d
pod/etcd-docker-k8s01                          1/1     Running            0          74d
pod/fluentd-logging-test-hzlzd                 0/1     CrashLoopBackOff   8573       31d
pod/grafana-0                                  1/1     Running            0          19h
pod/kube-apiserver-docker-k8s01                1/1     Running            0          74d
pod/kube-controller-manager-docker-k8s01       1/1     Running            0          74d
pod/kube-proxy-dbtxh                           1/1     Running            0          74d
pod/kube-proxy-fklzd                           1/1     Running            0          74d
pod/kube-proxy-jbk6v                           1/1     Running            0          74d
pod/kube-scheduler-docker-k8s01                1/1     Running            0          74d
pod/kube-state-metrics-5dd5dc67fc-tp29m        2/2     Running            0          18h
pod/prometheus-0                               2/2     Running            0          19h

NAME                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
service/alertmanager         ClusterIP   10.10.227.79    <none>        80/TCP                   16h
service/grafana              NodePort    10.10.102.113   <none>        80:30091/TCP             19h
service/kube-dns             ClusterIP   10.10.0.10      <none>        53/UDP,53/TCP,9153/TCP   74d
service/kube-state-metrics   ClusterIP   10.10.254.80    <none>        8080/TCP,8081/TCP        18h
service/prometheus           NodePort    10.10.46.163    <none>        9090:30090/TCP           19h

4.4邮件告警测试

+++

Prometheus operator部署

下载相关文件:

https://github.com/prometheus-operator/kube-prometheus/releases
#找到指定版本

a,部署operator

[root@docker-k8s01 ~]# kubectl apply -f kube-prometheus-0.8.0/manifests/setup/
namespace/monitoring created
customresourcedefinition.apiextensions.k8s.io/alertmanagerconfigs.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/alertmanagers.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/podmonitors.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/probes.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/prometheuses.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/prometheusrules.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/servicemonitors.monitoring.coreos.com created
customresourcedefinition.apiextensions.k8s.io/thanosrulers.monitoring.coreos.com created
clusterrole.rbac.authorization.k8s.io/prometheus-operator created
clusterrolebinding.rbac.authorization.k8s.io/prometheus-operator created
deployment.apps/prometheus-operator created
service/prometheus-operator created
serviceaccount/prometheus-operator created
[root@docker-k8s01 ~]# kubectl  get customresourcedefinitions.apiextensions.k8s.io | grep monitor
alertmanagerconfigs.monitoring.coreos.com             2022-11-23T07:41:30Z
alertmanagers.monitoring.coreos.com                   2022-11-23T07:41:30Z
podmonitors.monitoring.coreos.com                     2022-11-23T07:41:30Z
probes.monitoring.coreos.com                          2022-11-23T07:41:30Z
prometheuses.monitoring.coreos.com                    2022-11-23T07:41:30Z
prometheusrules.monitoring.coreos.com                 2022-11-23T07:41:30Z
servicemonitors.monitoring.coreos.com                 2022-11-23T07:41:30Z
thanosrulers.monitoring.coreos.com                    2022-11-23T07:41:30Z
[root@docker-k8s01 ~]# kubectl get deployments.apps -n monitoring 
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
prometheus-operator   1/1     1            1           80s
[root@docker-k8s01 ~]# kubectl get services -n monitoring 
NAME                  TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
prometheus-operator   ClusterIP   None         <none>        8443/TCP   92s
[root@docker-k8s01 ~]# 

b, 部署prometheus其他组件

  • prometheus prometheus核心组件
  • prometheus-adapter prometheus适配器,做数据转换
  • kube-state-metrics kubernetes指标转换器,转换为apiserver能识别的指标
  • alertmanager 告警管理器,用于指标阀值告警实现
  • node-exporter exporters,客户端监控上报agent,用于实现数据上报
  • grafana 数据显示展板
  • configmaps grafana数据展板配置模版,封装在configmap中
  • clusterrole,clusterrolebinding prometheus访问kubernetes的RBAC授权
$ kubectl apply -f kube-prometheus-0.8.0/manifests/
##检查资源对象状态
##node exporter通过daemonset部署;
[root@docker-k8s01 ~]# kubectl get daemonsets.apps -n monitoring 
NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
node-exporter   3         3         3       3            3           kubernetes.io/os=linux   17h
[root@docker-k8s01 ~]# kubectl get pods -n monitoring  | grep node-exporter
node-exporter-bglkr                    2/2     Running   0          18h
node-exporter-kxt4z                    2/2     Running   0          18h
node-exporter-vsfx4                    2/2     Running   0          18h

c,检查资源对象状态

##node exporter通过daemonset部署;
[root@docker-k8s01 ~]# kubectl get daemonsets.apps -n monitoring 
NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
node-exporter   3         3         3       3            3           kubernetes.io/os=linux   17h
[root@docker-k8s01 ~]# kubectl get pods -n monitoring  | grep node-exporter
node-exporter-bglkr                    2/2     Running   0          18h
node-exporter-kxt4z                    2/2     Running   0          18h
node-exporter-vsfx4                    2/2     Running   0          18h
# prometheus-adapter,grafana,kube-state-metrics以deployments的形式部署;
[root@docker-k8s01 ~]# kubectl get deployments.apps -n monitoring 
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
blackbox-exporter     1/1     1            1           18h
grafana               1/1     1            1           18h
kube-state-metrics    1/1     1            1           16h
prometheus-adapter    2/2     2            2           18h
prometheus-operator   1/1     1            1           18h

kube-state-metrics一开始部署有问题imageBackoff,下载镜像失败,修改如下

$ mv kube-state-metrics-* ./metrics/
标签为:app.kubernetes.io/version: 2.0.0,全部换为:app.kubernetes.io/version: 2.3.0
$ cat kube-state-metrics-deployment.yaml
#修改镜像地址,
…………
        #image: k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.0.0
        image: registry.cn-wulanchabu.aliyuncs.com/moge1/kube-state-metrics:v2.3.0
        #image: quay.io/coreos/kube-state-metrics:v2.0.0
        #image: harbor.od.com/public/kube-state-metrics:v2.0.0
…………
# Prometheus,alertmanager以statefulsets形式部署
[root@docker-k8s01 metrics]# kubectl get statefulsets.apps -n monitoring 
NAME                READY   AGE
alertmanager-main   3/3     18h
prometheus-k8s      2/2     18h
# 暴露服务状态
[root@docker-k8s01 metrics]# kubectl get services  -n monitoring 
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
alertmanager-main       ClusterIP   10.10.117.119   <none>        9093/TCP                     18h
alertmanager-operated   ClusterIP   None            <none>        9093/TCP,9094/TCP,9094/UDP   18h
blackbox-exporter       ClusterIP   10.10.46.163    <none>        9115/TCP,19115/TCP           18h
grafana                 NodePort    10.10.102.113   <none>        3000:30338/TCP               18h
kube-state-metrics      ClusterIP   None            <none>        8443/TCP,9443/TCP            18h
node-exporter           ClusterIP   None            <none>        9100/TCP                     18h
prometheus-adapter      ClusterIP   10.10.254.80    <none>        443/TCP                      18h
prometheus-k8s          NodePort    10.10.227.79    <none>        9090:30004/TCP               18h
prometheus-operated     ClusterIP   None            <none>        9090/TCP                     18h
prometheus-operator     ClusterIP   None            <none>        8443/TCP                     18h
# 查看pods状态
[root@docker-k8s01 ~]# kubectl get pods -n monitoring 
NAME                                   READY   STATUS    RESTARTS   AGE
alertmanager-main-0                    2/2     Running   0          18h
alertmanager-main-1                    2/2     Running   0          18h
alertmanager-main-2                    2/2     Running   0          18h
blackbox-exporter-55c457d5fb-tp29m     3/3     Running   0          18h
grafana-9df57cdc4-r565d                1/1     Running   0          18h
kube-state-metrics-cd7c68998-d2lff     3/3     Running   0          15h
node-exporter-bglkr                    2/2     Running   0          18h
node-exporter-kxt4z                    2/2     Running   0          18h
node-exporter-vsfx4                    2/2     Running   0          18h
prometheus-adapter-59df95d9f5-grtd8    1/1     Running   0          18h
prometheus-adapter-59df95d9f5-nzjnn    1/1     Running   0          18h
prometheus-k8s-0                       2/2     Running   1          18h
prometheus-k8s-1                       2/2     Running   1          18h
prometheus-operator-7775c66ccf-gv4rd   2/2     Running   0          18h

d,Prometheus,grafana使用

# 添加NodePort
# service Prometheus
[root@docker-k8s01 ~]# kubectl patch -p '{"spec":{"type": "NodePort"}}' services -n monitoring prometheus-k8s
service/prometheus-k8s patched

# service grafana
[root@docker-k8s01 ~]# kubectl patch -p '{"spec": {"type": "NodePort"}}' services grafana -n monitoring
service/grafana patched

[root@docker-k8s01 ~]# kubectl get service -n monitoring 
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
alertmanager-main       ClusterIP   10.10.117.119   <none>        9093/TCP                     18h
alertmanager-operated   ClusterIP   None            <none>        9093/TCP,9094/TCP,9094/UDP   18h
blackbox-exporter       ClusterIP   10.10.46.163    <none>        9115/TCP,19115/TCP           18h
grafana                 NodePort    10.10.102.113   <none>        3000:30338/TCP               18h
kube-state-metrics      ClusterIP   None            <none>        8443/TCP,9443/TCP            18h
node-exporter           ClusterIP   None            <none>        9100/TCP                     18h
prometheus-adapter      ClusterIP   10.10.254.80    <none>        443/TCP                      18h
prometheus-k8s          NodePort    10.10.227.79    <none>        9090:30004/TCP               18h
prometheus-operated     ClusterIP   None            <none>        9090/TCP                     18h
prometheus-operator     ClusterIP   None            <none>        8443/TCP                     18h

e,增加持久存储

prometheus-prometheus.yaml

  retention: 30d
  storage:
    volumeClaimTemplate:
      spec:
        storageClassName: managed-nfs-storage
        resources:
          requests:
            storage: 16Gi

grafana-deployment.yaml

...
      serviceAccountName: grafana
      volumes:
#      - emptyDir: {}
#        name: grafana-storage
      - name: grafana-storage
        persistentVolumeClaim:
          claimName: grafana-data

grafana-pvc.yaml

$ vim grafana-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: grafana-data
  namespace: monitoring
  annotations:
    volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

f, KubeControllerManagerDown

$ netstat -lntup | grep kube-control
tcp        0      0 127.0.0.1:10257         0.0.0.0:*               LISTEN      21086/kube-controll 
#修改监听地址
$ netstat -lntup | grep kube-con
tcp6       0      0 :::10257                :::*                    LISTEN      29942/kube-controll

创建service文件kube-controller-manager-svc.yaml,

apiVersion: v1
kind: Service
metadata:
  namespace: kube-system
  name: kube-controller-manager
  labels:
    #k8s-app: kube-controller-manager
    app.kubernetes.io/name: kube-controller-manager
spec:
  ports:
  - name: https-metrics
    port: 10257
  selector:
    component: kube-controller-manager

查看kubernetes-serviceMonitorKubeControllerManager.yaml

 $ tail -3 kubernetes-serviceMonitorKubeControllerManager.yaml
 selector:
    matchLabels:
      app.kubernetes.io/name: kube-controller-manager

g,KubeSchedulerDown

apiVersion: v1
kind: Service
metadata:
  namespace: kube-system
  name: kube-scheduler
  labels:
    #k8s-app: kube-scheduler
    app.kubernetes.io/name: kube-scheduler
spec:
  ports:
  - name: https-metrics
    port: 10259
  selector:
    component: kube-scheduler
$ kubectl apply -f kube-controller-manager-svc.yaml -f kube-scheduler-svc.yaml

h,添加邮件报警

修改alertmanager-secret.yaml文件:

stringData:
  alertmanager.yaml: |- ##保留每行的换行符,删除结尾的换行符
    "global":
      "resolve_timeout": "5m"
      "smtp_smarthost": "smtp.qiye.163.com:25"  ##添加相关配置
      "smtp_from": "zabbix-server@leadchina.cn"
      "smtp_auth_username": "zabbix-server@leadchina.cn"
      "smtp_auth_password": "xxxxx"
    "inhibit_rules":
 …………
    "receivers":
    - "name": "Default"  ##指定用户
      "email_configs":
      - "to": "xxx"
    - "name": "Watchdog"
…………

+++

j,添加报警规则

# prometheus 报警规则文件位置:通过prometheus页面-configration中的可以看到
rule_files:
- /etc/prometheus/rules/prometheus-k8s-rulefiles-0/*.yaml
$ kubectl -n monitoring exec -it prometheus-k8s-0 -- /bin/sh
Defaulting container name to prometheus.
Use 'kubectl describe pod/prometheus-k8s-0 -n monitoring' to see all of the containers in this pod.
/prometheus $  cd /etc/prometheus/rules/prometheus-k8s-rulefiles-0/
/etc/prometheus/rules/prometheus-k8s-rulefiles-0 $ ls
monitoring-alertmanager-main-rules.yaml          monitoring-kube-state-metrics-rules.yaml         monitoring-prometheus-k8s-prometheus-rules.yaml
 monitoring-kubernetes-monitoring-rules.yaml      monitoring-prometheus-operator-rules.yaml		monitoring-kube-prometheus-rules.yaml            monitoring-node-exporter-rules.yaml
我们创建的 prometheus 这个资源对象,里面有非常重要的一个属性 ruleSelector,用来匹配 rule 规则的过滤器,要求匹配具有 prometheus=k8s 和 role=alert-rules 标签的 PrometheusRule 资源对象 
#手动添加 报警规则,创建一个具有 prometheus=k8s 和 role=alert-rules 标签的 PrometheusRule 对象
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    prometheus: k8s  
    role: alert-rules
  name: disk-free-rules
  namespace: monitoring
spec:
  groups:
  - name: disk
    rules:
    - alert: diskFree
      annotations:
        summary: "{{ $labels.job }}  项目实例 {{ $labels.instance }} 磁盘使用率大于 80%"
        description: "{{ $labels.instance }}  {{ $labels.mountpoint }}  磁盘使用率大于80%  (当前的值: {{ $value }}%),请及时处理"
      expr: |
        (1-(node_filesystem_free_bytes{fstype=~"ext4|xfs",mountpoint!="/boot"} / node_filesystem_size_bytes{fstype=~"ext4|xfs",mountpoint!="/boot"}) )*100 > 85
      for: 3m
      labels:
        level: disaster

Prometheus热更新

curl -X POST http://IP/-/reload

4,添加企业微信报警

​ alertmanager.yaml模板

global:
  resolve_timeout: 5m
  wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
  wechat_api_secret: 'X82vlGwRUAoauFlK-9jhxNvL_vTayo48oUuxDDWIuBM'
  wechat_api_corp_id: 'ww6ae02f1fb738be91'
  

templates:     ##消息模板
  - '*.tmpl'

route:
  group_by: ['alertname','job']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1m
  receiver: 'wechat'

receivers:

- name: 'wechat'
  wechat_configs:
  - send_resolved: true
    to_party: '2'  #中心ID
    agent_id: '1000002'  #部门ID

默认配置文件

global:
  resolve_timeout: 5m
  wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
  wechat_api_secret: 'X82vlGwRUAoauFlK-9jhxNvL_vTayo48oUuxDDWIuBM'
  wechat_api_corp_id: 'ww6ae02f1fb738be91'
inhibit_rules:
- equal:
  - namespace
  - alertname
  source_matchers:
  - severity = critical
  target_matchers:
  - severity =~ warning|info
- equal:
  - namespace
  - alertname
  source_matchers:
  - severity = warning
  target_matchers:
  - severity = info
- equal:
  - namespace
  source_matchers:
  - alertname = InfoInhibitor
  target_matchers:
  - severity = info
receivers:
- name: "null"
route:
  group_by:
  - namespace
  group_interval: 5m
  group_wait: 30s
  receiver: "null"
  repeat_interval: 12h
  routes:
  - matchers:
    - alertname =~ "InfoInhibitor|Watchdog"
    receiver: "null"
templates:
- /etc/alertmanager/config/*.tmpl

企业微信告警模板:

apiVersion: v1
kind: ConfigMap
metadata:
  name: wechat-tmpl
  namespace: kube-ops
data:
  wechat.tmpl: |
    {{ define "wechat.default.message" }}
    {{ range .Alerts }}
    ========start==========
    告警程序: prometheus_alert
    告警级别: {{ .Labels.severity }}
    告警类型: {{ .Labels.alertname }}
    故障主机: {{ .Labels.instance }}
    告警主题: {{ .Annotations.summary }}
    告警详情: {{ .Annotations.description }}
    触发时间: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
    ========end==========
    {{ end }}
    {{ end }}
    
#####################################################另一份
[root@prometheus-bpmdev alertmanager]# cat template/wechat.tmpl
{{ define "wechat.default.message" }}
{{- if gt (len .Alerts.Firing) 0 -}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index 0 }}
=========xxx环境监控报警 =========
告警状态:{{   .Status }}
告警级别:{{ .Labels.severity }}
告警类型:{{ $alert.Labels.alertname }}
故障主机: {{ $alert.Labels.instance }} {{ $alert.Labels.pod }}
告警主题: {{ $alert.Annotations.summary }}
告警详情: {{ $alert.Annotations.message }}{{ $alert.Annotations.description}};
触发阀值:{{ .Annotations.value }}
故障时间: {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
========= = end =  =========
{{- end }}
{{- end }}
{{- end }}
{{- if gt (len .Alerts.Resolved) 0 -}}
{{- range $index, $alert := .Alerts -}}
{{- if eq $index 0 }}
=========xxx环境异常恢复 =========
告警类型:{{ .Labels.alertname }}
告警状态:{{   .Status }}
告警主题: {{ $alert.Annotations.summary }}
告警详情: {{ $alert.Annotations.message }}{{ $alert.Annotations.description}};
故障时间: {{ ($alert.StartsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
恢复时间: {{ ($alert.EndsAt.Add 28800e9).Format "2006-01-02 15:04:05" }}
{{- if gt (len $alert.Labels.instance) 0 }}
实例信息: {{ $alert.Labels.instance }}
{{- end }}
========= = end =  =========
{{- end }}
{{- end }}
{{- end }}
{{- end }}

###########################模板3#########
[root@centos74 home]# cat /usr/local/prometheus/alertmanager/wechat.tmpl
{{ define "wechat.default.message" }}
{{- if gt (len .Alerts.Firing) 0 -}}
{{- range $index, $alert := .Alerts -}}
======== 异常告警 ========
告警名称:{{ $alert.Labels.alertname }}
告警级别:{{ $alert.Labels.severity }}
告警机器:{{ $alert.Labels.instance }} {{ $alert.Labels.device }}
告警详情:{{ $alert.Annotations.summary }}
告警时间:{{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
========== END ==========
{{- end }}
{{- end }}
{{- if gt (len .Alerts.Resolved) 0 -}}
{{- range $index, $alert := .Alerts -}}
======== 告警恢复 ========
告警名称:{{ $alert.Labels.alertname }}
告警级别:{{ $alert.Labels.severity }}
告警机器:{{ $alert.Labels.instance }}
告警详情:{{ $alert.Annotations.summary }}
告警时间:{{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
恢复时间:{{ $alert.EndsAt.Format "2006-01-02 15:04:05" }}
========== END ==========
{{- end }}
{{- end }}
{{- end }}