[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