[toc]
一、k8s部署prometheus
根据prometheus operator中的yaml文件改写DaemonSet控制器的node-exporter
创建prometheus用到的configmap配置文件
创建serviceaccount,和clusterrolebinding,绑定serviceaccount和cluster-admin的角色
创建prometheus的deployment配置文件
创建service,暴露nodeport端口,绑定到prometheus的deployment的pod
- 监控pod信息,使用cadvisor,使用DaemonSet控制器部署,默认监听端口8080
- 更改uri路径为/metrics,显示pod指标数据
二、二进制安装
1.1 部署prometheus-server
- 下载prometheus-server二进制包
wget https://github.com/prometheus/prometheus/releases/download/v2.33.4/prometheus-2.33.4.linux-amd64.tar.gz
# 解压
tar xvf prometheus-2.33.4.linux-amd64.tar.gz
# 软链接 去掉版本号
ln -sv /apps/prometheus-2.33.4.linux-amd64 /apps/prometheus
# 进入链接目录
cd prometheus
# 检查prometheus.yml配置文件是否正确
./promtool check config prometheus.yml
# 直接启动 默认加载当前目录下的配置文件
./prometheus
直接启动的方式是在当前控制台输出日志,并且会在当前目录下产生一个data的目录,存储prometheus的数据(不能删除),默认监听端口9090
- 创建prometheus.service文件
cat > /etc/systemd/system/prometheus.service <<EOF
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview
After=network.target
[Service]
Restart=on-failure
WorkingDirectory=/apps/prometheus
ExecStart=/apps/prometheus/prometheus --config.file=/apps/prometheus/prometheus.yml
[Install]
WantedBy=multi-user.target
EOF
注意--config.file文件中间是".",不是"-",启动参数可以通过./prometheus --help进行查看
- 启动prometheus
# 设置为开机自启动
systemctl enable prometheus.service
# 重新加载service文件
systemctl daemon-reload
# 启动prometheus
systemctl start prometheus.service
第一次创建出来prometheus.service文件可以不用执行daemon-reload,如果后续更改service文件,需要执行daemon-reload
1.2 部署node-exporter
- 下载node-expoter二进制包
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
ln -sv node_exporter-1.3.1.linux-amd64 node_exporter
- 创建node_exporter.service文件
cat > /etc/systemd/system/node_exporter.service <<EOF
[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
Restart=on-failure
ExecStart=/apps/node_exporter/node_exporter
[Install]
WantedBy=multi-user.target
EOF
启动选项可以通过./node_exporter --help查看
- 启动node_exporter
# 设置为开机自启动
systemctl enable node-exporter.service
# 重新加载service文件
systemctl daemon-reload
# 启动prometheus
systemctl start node-exporter.service
默认监听端口9100
1.3 prometheus监控node
- 原始prometheus.yaml文件
# 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"]
默认只监听prometheus server自己
- 更改prometheus.yml配置文件
- job_name: "prometheus-node"
static_configs:
- targets: ["IP:9100","IP:9100","IP:9100"]
在配置文件末尾添加要监控的主机的地址和node_exporter监听的端口
- 重启prometheus-server
systemctl restart prometheus.service
- 查看新加入监控的node
在prometheus web页面的Status下拉菜单中的Targets选项,默认没间隔15s收集一次数据,Last Scrape显示的时间是距离上次抓取数据的时间
- 使用promQL查询
- 下载grafana包
wget https://dl.grafana.com/enterprise/release/grafana-enterprise_8.3.7_amd64.deb
dpkg -i grafana-enterprise_8.3.7_amd64.deb
安装的时候会报错缺少依赖libfontconfig1,使用apt install -f 解决
默认监听端口3000
默认账号名密码为amdin/admin,如果不想修改,可以点击Skip按钮跳过
- 添加数据源
点击Add data source
点击Prometheus框
填写名字,是否设置为默认,填写prometheus的地址
连接测试
- 添加模板
官网查找模板地址:https://grafana.com/grafana/dashboards/
点击Import
填写模板id,或者导入json文件
修改模板名字,选择数据源,点击Import导入
- 下载consul包
wget https://releases.hashicorp.com/consul/1.11.4/consul_1.11.4_linux_amd64.zip
三、PromQL语句
官方网址:https://prometheus.io/docs/prometheus/latest/querying/basics/
Prometheus提供一个函数式的表达式语言PromQL(Prometheus Query Language),可以使用户实时查找和聚合时间序列数据,表达式计算结果可以在图标中展示,也可以在Prometheus表达式浏览器中以表格形式展示,或者作为数据源,以HTTP API的方式提供给外部系统使用。
PromQL支持处理两种向量,并内置提供了一组用于数据处理的函数;即时向量:最近一次的时间戳上跟踪的数据指标;时间范围向量:指定时间范围内的所有时间戳上的数据指标
- 数据类型
即时向量(Instant Vector):是一组时间序列,每个时间序列包含单个数据样本,具有相同时间戳的一组样本值,prometheus_http_requests_total
范围向量(Range Vector):在任何一个时间范围内,抓取所有度量指标数据,一段时间内的所有样本值,prometheus_http_requests_total[5m]
标量(Scalar):一个浮点型的数据值,使用node_load1获取到一个即时向量,可以使用内置函数scalar()将瞬时向量转换为标量;例如:scalar(sum(node_load1))
字符串:字符串类型的数据,支持使用单引号、双引号或反引号进行引用,但是反引号中不会对转义字符进行转义
- 指标类型
PromQL有四个指标类型,他们主要由Prometheus的客户端使用
Counter:计数器,单调递增,除非重置(例如服务器或进程重启),如磁盘I/O总数、nginx请求总数、网卡流经的报文总数等
Guage:仪表盘,表示是一个可以任意变化的指标数据,可增可减,如带宽速率、CPU负载、内存利用率、nginx活动连接数等
Histogram:直方图,将事件范围内的数据划分成不同的时间段,并各自评估其样本个数以及样本之和,因而可计算出分数位,如每分钟产生一个当前的活跃连接数,那么一天就会产生1440个数据,查看数据的间隔绘图跨度为2小时,那么2小时位置的柱状图(bucket)会包含0-2两个小时的数据
- 可用于分析因异常值而引起的平均值过大的问题
- 分位数计算要使用专门的histogram_quantile函数
Summary:类似于Histogram,统计的不是区间的个数而是统计分位数,客户端会直接计算并上报分位数,0~100%
- 匹配器
= :选择与提供的字符串完全相同的标签,精确匹配
!=:选择与提供的字符串不相同的标签,取反
=~:选择正则表达式与提供的字符串(或子字符串)相匹配的标签
!~:选择正则表达式与提供的字符串(或子字符串)不匹配的标签
node_load1{instance=~"172.31.7.11.*:9100$"} # 包含正则且匹配
- 时间范围
s - 秒
m - 分钟
h - 小时
d - 天
w - 周
y - 年
node_memory_MemTotal_bytes{instance="172.31.7.111:9100"}[5m]
- 运算符
+ 加法
- 减法
* 乘法
/ 除法
% 模
^ 幂等
node_memory_MemFree_bytes/1024/1024
- 聚合运算
max() # 最大值
计算每个节点的最大流量值
max(node_network_receive_bytes_total) by (instance)
计算每个节点最近五分钟没饿device的最大流量
max(rate(node_network_receive_bytes_total[5m])) by (device)
min() # 最小值
avg() # 平均值
sum()
sum(prometheus_http_requests_total)
count()
count(node_os_version)
abs() # 返回指标数据的值
abs(sum(prometheus_http_requests_total{handler="/metrics"}))
absent() # 如果监控指标有数据就返回空,如果监控项没有数据就返回1
absent(sum(prometheus_http_requests_total{handler="/metrics"}))
stddev() # 标准差
stddev(prometheus_http_requests_total)
stdvar() # 求方差
stdvar(prometheus_http_requests_total)
topk() # 样本值排名最大的N个数据
topk(6,prometheus_http_requests_total)
bottomk() # 样本值排名最小的N个数据
bottomk(6,prometheus_http_requests_total)
rate() # 函数是专门搭配counter数据类型使用函数,功能是取counter数据类型在这个时间段中平均每秒的增量平均数
rate(prometheus_http_requests_total[5m])
rate(node_network_receive_bytes_total[5m])
irate() # 函数是专门搭配counter数据类型使用函数,功能是取counter数据类型在这个时间段平均每秒的峰值
irate(prometheus_http_requests_total[5m])
irate(node_network_receive_bytes_total[5m])
- rate和irate都会用于计算某个指标在一定时间间隔内的变化速率;irate取的是在指定时间范围内的最近两个数据点来算速率,而rate会取指定时间范围内所有数据点,算出一组速率,然后取平均值作为结果;官网文档说:irate适合快速变化的计数器(counter),而rate适合缓慢变化的计数器;快速变化的计数器,如果使用rate,容易把峰值削平
by # 在计算结果中,只保留by指定的标签值,并移除其它所有的
sum(rate(node_network_receive_packages_total{instance=~".*"[10m]})) by (instance)
sum(rate(node_memory_MemFree_bytes[5m])) by (increase)
without # 从计算结果中移除列举的instance,job标签,保留其它标签
四、服务发现及relabel
Prometheus默认是采用pull方式拉取监控数据的,也就是定时去目标主机上抓取metrics数据,每一个抓取的目标需要暴露一个HTTP接口,Prometheus通过这个暴露的接口就可以获取到相应的指标数据,这种方式需要由目标服务决定采集的目标有哪些,通过配置在scrape_configs中的各种job来实现,无法动态感知新服务,如果后面增加了节点或者组件信息,就得手动修改配置文件,并重启Prometheus,很不友好,所以出现了动态服务发现,动态服务发现能够自动发现集群中的新端点,并加入到配置中,通过服务发现,Prometheus能查询到需要监控的Target列表,然后轮询这些Target获取监控数据。
Prometheus获取数据源Targets的方式有很多种,如静态配置和服务发现配置,Prometheus支持多种服务发现,常用的主要有以下几种:
kubernetes_sd_configs:kubernetes服务发现,让prometheus动态发现kubernetes中被监控的目标
static_configs:静态服务发现,基于prometheus配置文件指定监控目标
dns_sd_configs:DNS服务发现监控目标
consul_sd_configs:consul服务发现,基于consul服务动态发现监控目标
file_sd_configs:基于指定的文件实现服务发现
prometheus的静态服务发现static_configs:每当有一个新的目标示例需要监控,都需要手动修改配置文件配置目标target
prometheus的consul服务发现consul_sd_configs:prometheus一直监视consul服务,当发现在consul中注册的服务有变化,prometheus会自动监控到所有注册到consul中的目标资源
prometheus的k8s服务发现kubernetes_sd_configs:promtheus与kubernetes的API进行交互,动态的发现kubernetes中部署的多有可监控的目标资源
4.1 kubernetes_sd_configs
官方网址:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
prometheus的relabeling(重新修改标签)功能很强大,它能够在抓取到目标示例之前把目标示例的元数据标签动态重新修改,动态添加或者覆盖标签
prometheus加载target成功之后,在Target实例中,都包含一些Metadata标签信息,默认的标签有:__addresss__:以<host>:<port>格式显示目标targets的地址
__scheme__:采集的目标服务地址的Scheme形式,HTTP或者HTTPS
__metrics_path__:采集的目标服务的访问路径
- 重新标记目的
为了更好的识别监控指标,便于后期调用数据绘图、告警等需求,prometheus支持对发现的目标进行label修改,在两个阶段可以重新标记:
relabel_configs:在采集之前(比如在采集数据之前重新定义元标签),可以使用relabel_configs添加一些标签、也可以只采集特定目标或过滤目标
metric_relabel_configs:如果是已经抓取都指标数据时,可以使用metric_relabel_configs做最后的重新标记和过滤
配置-->重新标签(relabel_configs)-->抓取-->重新标签(metric_relabel_configs)-->TSDB
- job_name: 'kubernetes-apiserver' # job名称
kubernetes_sd_configs: # 基于kubernetes_sd_configs实现服务发现
- role: endpoints # 发现endpoints
scheme: https # 当前job使用的发现协议
tls_config: # 证书配置
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt # 容器里的token路径
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs: # 重新re修改标签lebel配置configs
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] # 源标签
action: keep # action定义了relabel的具体动作,action支持多种
regex: default;kubernetes;https # 发现default命名空间的kubernetes服务是https协议
- label详解
source_labels:源标签,没有经过relabel处理之前的标签名字
target_label:通过action处理之后的新标签名字
regex:正则表达式,匹配源标签
replacement:通过分组替换后标签(target_label)对应的值
- action详解
replace:替换标签值,根据regex正则匹配到源标签的值,使用replacement来引用表达式匹配的分组
keep:满足regex正则条件的实例进行采集,把source_labels中没有匹配到regex正则内容的Target实例丢掉
drop:满足regex正则条件的实例不采集,把source_labels中匹配到regex正则内容的Target实例丢掉
hashmod:使用hashmod计算source_labels的Hash值并进行对比,基于自定义的模数取模,以实现对目标进行分类、重新赋值等功能
scrape_configs:
- job_name: ip_job
relabel_configs:
- source_labels: [__address__]
modulus: 4
target_label: __ip_hash
action: hashmod
- source_labels: [__ip_hahs]
regex: ^1$
action: keep
labelmap:匹配regex所有标签名称,然后赋值匹配标签的值进行分组,通过replacement分组引用({2}...)
labelkeep:匹配regex所有标签名称,其它不匹配的标签豆浆从标签集中删除
labeldrop:匹配regex所有标签名称,其它匹配的标签都将从标签集中删除
- 测试label功能
注释如下行内容
# relabel_configs:
# - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
# action: keep
# regex: default;kubernetes;https
先在default的namespace下创建svc和pod,然后重新apply下prometheus的configmap配置文件,先delete掉prometheus的deployment应用,再apply下,就会发现有好多down状态的,是因为做服务发现的时候没有过滤,pod也被匹配成功并进行监控,但是pod并没有提供metrics指标数据,所以不通
- 支持发现的目标类型
node
service
pod
endpoints
Endpointslice # 对endpoint进行切片
ingress
- kube-dns服务发现
在kube-dns的注解位置一定要包含如下内容
annotations:
prometheus.io/port: "9153" # 注解标签,用于prometheus服务发现端口
prometheus.io/scrape: "true" # 是否允许prometheus抓取数据
prometheus的configmap配置文件中添加如下内容
- job_name: 'kubernetes-service-endpoints' kubernetes_sd_configs: - role: endpoints # 角色 relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] action: keep # 匹配正则就抓取 regex: true # 匹配注解中的prometheus.io/scrape - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] action: replace # 替换 target_label: __scheme__ # 把__meta_kubernetes_service_annotation_prometheus_io_scheme 替换为 __scheme__ regex: (https?) # http或https ?表示可以有或者没有 - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) # 表示任意字符的一个或多个,(.*)表示任意字符的0个或多个 - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] action: replace target_label: __address__ regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] action: replace target_label: kubernetes_name
- prometheus部署在k8s集群外部实现服务发现
首先创建用户,角色,绑定用户和角色,拿到用户的token,存到prometheus主机的/apps/prometheus/k8s.token文件中(文件路径和名字可以自己指定),然后在prometheus的配置文件(prometheus.yaml)中添加job,以监控k8s的api-server为例
- job_name: 'kubernetes-apiserver-monitor'
kubernetes_sd_configs:
- role: endpoints
api_server: https:IP:PORT # 指定自己的apiserver的ip和端口
scheme: https
tls_config:
insecure_skip_verify: true # 跳过证书验证
bearer_token_file: /apps/prometheus/k8s.token # 保存在主机上的token文件
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- target_label: __address__
replacement: IP:PORT # 替换为自己apiserver的ip和端口
4.2 static_configs
- 主机上安装prometheus的配置文件(prometheus.yml),手动添加静态发现列表
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"]
- job_name: "prometheus-node"
static_configs:
- targets: ["IP:9100"]
4.3 consul_sd_configs
consul是分布式k/v数据存储集群,目前常用于服务的注册和发现
- 部署consul集群
安装包下载:https://releases.hashicorp.com/consul/1.11.4/
wget https://releases.hashicorp.com/consul/1.11.4/consul_1.11.4_linux_amd64.zip
unzip consul_1.11.4_linux_amd64.zip
cp consul /usr/local/bin
consul -h # 验证是否可执行
# 创建数据目录
mkdir -p /data/consul
# 启动服务
# node1
nohup consul agent -server -bootstrap -bind=NODE1_IP -client=NODE1_IP -data-dir=/data/consul -ui -node=NODE1_IP &
# node2
nohup consul agent -bind=NODE2_IP -client=NODE2_IP -data-dir=/data/consul -node=NODE2_IP -join=NODE1_IP &
# node3
nohup consul agent -bind=NODE3_IP -client=NODE3_IP -data-dir=/data/consul -node=NODE3_IP -join=NODE1_IP &
默认监听端口8500
查看启动日志nohup.out
查看界面
- 写入数据
curl -X PUT -d '{"id":"node-exporteXXX","name":"node-exporterXXX","address":"IP","port":9100,"tags":"node-exporter","checks":[{"http":"http://IP:PORT","interval":"5s"}]}' http://CONSUL_IP:8500/v1/agent/service/register
不返回值,http code返回200即为成功
- 配置prometheus到consul服务发现
k8s prometheus configmap配置文件
- job_name: 'consul'
honor_labels: true
metrics_path: /metrics
scheme: http
consul_sd_configs:
- server: CONSUL_IP1:8500
services: [] # 发现的目标服务名称,空为所有服务,可以写servicea,serviceb,servicec
- server: CONSUL_IP2:8500
services: []
- server: CONSUL_IP3:8500
services: []
relabel_configs:
- source_labels: ['__meta_consul_tags']
target_label: 'product'
- source_labels: ['__meta_consul_dc']
target_label: 'idc'
- source_labels: ['__meta_consul_service']
regex: "consul"
action: drop
主机prometheus.yml配置文件
- job_name: 'consul'
honor_labels: true
metrics_path: /metrics
scheme: http
consul_sd_configs:
- server: CONSUL_IP1:8500
services: [] # 发现的目标服务名称,空为所有服务,可以写servicea,serviceb,servicec
- server: CONSUL_IP2:8500
services: []
- server: CONSUL_IP3:8500
services: []
relabel_configs:
- source_labels: ['__meta_consul_tags']
target_label: 'product'
- source_labels: ['__meta_consul_dc']
target_label: 'idc'
- source_labels: ['__meta_consul_service']
regex: "consul"
action: drop
页面验证
- 添加cadvisor
curl -X PUT -d '{"id":"cadvisor-XXX","name":"cadvisor-XXX","address":"IP","port":8080,"tags":["cadvisor"],"checks":[{"http":"http://IP:8080","interval":"5s"}]}' http://CONSUL_IP:8500/v1/agent/service/register
- 删除数据
curl --request PUT http://CONSUL_IP:8500/v1/agent/service/deregister/node-exporterXXX
删掉一个node-expoter
4.4 file_sd_configs
- 在prometheus主机上创建/apps/prometheus/file_sd/file_sd_server.json文件
[
{
"targets": ["192.168.204.101:9100","192.168.204.102:9100","192.168.204.103:9100"]
}
]
- prometheus调用json文件
- job_name: 'file_sd_server'
file_sd_configs:
- files:
- /apps/file_sd/file_sd_server.json
refresh_interval: 10s # 读取json文件间隔时间
json配置文件中添加或删除主机,不需要重启prometheus
发现添加的主机
添加完成
4.5 dns_file_configs
基于dns的服务发现允许配置指定一组dns域名,这些域名会定期查询以发现目标列表,域名需要可以被配置的dns服务器解析为ip
此方法仅支持DNS A、AAAA、SRV记录查询
A记录: 将域名指向一个IPv4地址
AAAA记录:将域名指向一个IPv6地址
SRV记录:SRV记录了哪台计算机提供了具体哪个服务,格式为:自定义的服务名字.协议的类型.域名(例如:_example-server._tcp.www.mydns.com)
prometheus会对收集的指标数据进行重新达标,重新标记期间,可以使用一下元标签:
__meta_dns_name:产生发现目标的记录名称
__meta_dns_srv_record_target:SRV记录的目标字段
__meta_dns_srvrecord_port:SRV记录的端口字段
如果没有dns服务器,手动修改/etc/hosts配置文件,添加解析
IP DOMAIN_NAME
修改prometheus.yml配置文件
- job_name: 'dns-server-name-monitor'
metrics_path: "/metrics"
dns_sd_configs:
- names: ["node1.example.com","node2.example.com"]
type: A
port: 9100
refresh_interval: 10s
修改域名解析指向的主机ip,不需要重启prometheus,添加新的域名如添加node3.example.com需要重启prometheus