采用kube-prometheus方案,架构图如下
1.1 安装kube-prometheus
Prometheus-operator:https://github.com/prometheus-operator/prometheus-operator.git
Kube-prometheus:https://github.com/prometheus-operator/kube-prometheus.git
1.1.1 下载安装资源文件
git clone -b release-0.8 --single-branch https://github.com/prometheus-operator/kube-prometheus.git
1.1.2 修改为国内镜像
监控容器
需要修改如下镜像地址,镜像需要提前同步到国内或者内网
[root@k8s-master01 ~]# cd kube-prometheus/manifests && grep -r "image:" .
./alertmanager-alertmanager.yaml: #image: quay.io/prometheus/alertmanager:v0.21.0
./alertmanager-alertmanager.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/alertmanager:v0.21.0
./blackbox-exporter-deployment.yaml: #image: quay.io/prometheus/blackbox-exporter:v0.18.0
./blackbox-exporter-deployment.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/blackbox-exporter:v0.18.0
./blackbox-exporter-deployment.yaml: #image: jimmidyson/configmap-reload:v0.5.0
./blackbox-exporter-deployment.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/configmap-reload:v0.5.0
./blackbox-exporter-deployment.yaml: #image: quay.io/brancz/kube-rbac-proxy:v0.8.0
./blackbox-exporter-deployment.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/kube-rbac-proxy:v0.8.0
./grafana-deployment.yaml: #image: grafana/grafana:7.5.4
./grafana-deployment.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/grafana:7.5.4
./kube-state-metrics-deployment.yaml: #image: k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.0.0
./kube-state-metrics-deployment.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/kube-state-metrics:v2.0.0
./kube-state-metrics-deployment.yaml: #image: quay.io/brancz/kube-rbac-proxy:v0.8.0
./kube-state-metrics-deployment.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/kube-rbac-proxy:v0.8.0
./kube-state-metrics-deployment.yaml: #image: quay.io/brancz/kube-rbac-proxy:v0.8.0
./kube-state-metrics-deployment.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/kube-rbac-proxy:v0.8.0
./node-exporter-daemonset.yaml: #image: quay.io/prometheus/node-exporter:v1.1.2
./node-exporter-daemonset.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/node-exporter:v1.1.2
./node-exporter-daemonset.yaml: #image: quay.io/brancz/kube-rbac-proxy:v0.8.0
./node-exporter-daemonset.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/kube-rbac-proxy:v0.8.0
./prometheus-adapter-deployment.yaml: #image: directxman12/k8s-prometheus-adapter:v0.8.4
./prometheus-adapter-deployment.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/k8s-prometheus-adapter:v0.8.4
./prometheus-prometheus.yaml: #image: quay.io/prometheus/prometheus:v2.26.0
./prometheus-prometheus.yaml: image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/prometheus:v2.26.0
Oprator
cd kube-prometheus/manifests/setup
vim prometheus-operator-deployment.yaml
spec:
containers:
- args:
- --kubelet-service=kube-system/kubelet
#- --prometheus-config-reloader=quay.io/prometheus-operator/prometheus-config-reloader:v0.47.0
- --prometheus-config-reloader=registry.cn-qingdao.aliyuncs.com/zz_google_containers/prometheus-config-reloader:v0.47.0
#image: quay.io/prometheus-operator/prometheus-operator:v0.47.0
image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/prometheus-operator:v0.47.0
name: prometheus-operator
....
#image: quay.io/brancz/kube-rbac-proxy:v0.8.0
image: registry.cn-qingdao.aliyuncs.com/zz_google_containers/kube-rbac-proxy:v0.8.0
name: kube-rbac-proxy
......
1.1.3 安装prometheus-operator
cd kube-prometheus/manifests/setup && kubectl create -f .
1.1.4 安装监控资源
cd kube-prometheus/manifests && kubectl create -f .
1.1.5 修改默认serviceMonitor
默认的serviceMonitor资源会有KubeControllerManagerDown 和KubeSchedulerDown 错误,需要单独提前修改kubernetes-serviceMonitorKubeControllerManager.yaml
和kubernetes-serviceMonitorKubeScheduler.yaml
kubernetes-serviceMonitorKubeControllerManager.yaml
sourceLabels: - __name__ port: http-metrics #https-metrics修改为http-metrics scheme: http #https修改为http #tlsConfig: # 注释跳过tls验证,也可不注释 # insecureSkipVerify: true jobLabel: app.kubernetes.io/name namespaceSelector: matchNames: - kube-system selector: matchLabels: app.kubernetes.io/name: kube-controller-manager #不需要修改,但之后创建的service需要是这个label
kubernetes-serviceMonitorKubeScheduler.yaml
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: app.kubernetes.io/name: kube-scheduler name: kube-scheduler namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s port: http-metrics # https-metrics改为http-metrics scheme: http # https改为http #tlsConfig: #可注释 # insecureSkipVerify: true jobLabel: app.kubernetes.io/name namespaceSelector: matchNames: - kube-system selector: matchLabels: app.kubernetes.io/name: kube-scheduler #不需要修改,但之后创建的service需要是这个label
1.1.6 添加Ingress资源
grafana默认的用户名密码都是admin
为alertmanager-main、grafana、prometheus-k8s Service资源建立Ingress资源
k8s集群需要提前安装ingress,并将域名解析到安装了Ingress的节点
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: monitor-ingresses
namespace: monitoring
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: alert.node1.com
http:
paths:
- backend:
service:
name: alertmanager-main
port:
number: 9093
path: /
pathType: Prefix
- host: grafana.node1.com
http:
paths:
- backend:
service:
name: grafana
port:
number: 3000
path: /
pathType: Prefix
- host: prometheus.node1.com
http:
paths:
- backend:
service:
name: prometheus-k8s
port:
number: 9090
path: /
pathType: Prefix
1.2 Metrics类型
Counter:只增不减的计数器
例如:http_requests_total、node_cpu等
Gauge:可增可减
例如:主机的cpu、内存、磁盘使用率、当前并发量等
Histogram和Summary:用于统计和分析样本的分布情况
直方图参考如下文档:https://www.cnblogs.com/ryanyangcs/p/11309373.html
1.3 Metrics字段信息说明
metrics接口返回的格式开头
HELP:说明
TYPE:metrics类型
....
alertmanager_alerts_invalid_total{version="v1"}@139383232 0 #存储在prometheus的格式
1.4 PromQL查询语法
详细文档参考:https://fuckcloudnative.io/prometheus/3-prometheus/basics.html
Prometheus 提供了一种功能表达式语言 PromQL
,允许用户实时选择和汇聚时间序列数据。表达式的结果可以在浏览器中显示为图形,也可以显示为表格数据,或者由外部系统通过 HTTP API 调用。
1.4.1 表达式语言数据类型
在 Prometheus 的表达式语言中,表达式或子表达式包括以下四种类型之一:
- 瞬时向量(Instant vector) : 一组时间序列,每个时间序列包含单个样本,它们共享相同的时间戳。也就是说,表达式的返回值中只会包含该时间序列中的最新的一个样本值。而相应的这样的表达式称之为瞬时向量表达式。
- 区间向量(Range vector) :一组时间序列,每个时间序列包含一段时间范围内的样本数据。
- 标量(Scalar) :一个浮点型的数据值。
- 字符串(String) :一个简单的字符串值。
根用户输入的表达式返回的数据类型是否合法取决于用例的不同,例如:瞬时向量表达式返回的数据类型是唯一可以直接绘制成图表的数据类型。
1.4.2 字面量
(1) 字符串
字符串可以用单引号、双引号或反引号指定为文字常量。
(2) 标量
标量浮点值可以字面上写成 [-](digits)[.(digits)]
的形式。
1.4.3 时间序列过滤器
(1) 瞬时向量过滤器
瞬时向量过滤器允许在指定的时间戳内选择一组时间序列和每个时间序列的单个样本值。在最简单的形式中,近指定指标(metric)名称。这将生成包含此指标名称的所有时间序列的元素的瞬时向量。
例如:选择指标名称为 prometheus_http_requests_total
的所有时间序列:
prometheus_http_requests_total
可以通过向花括号({}
)里附加一组标签来进一步过滤时间序列。
例如:选择指标名称为 prometheus_http_requests_total
,code
值为200,job
标签值为 prometheus-k8s
的时间序列:
prometheus_http_requests_total{code="200", job="prometheus-k8s"}
PromQL 还支持用户根据时间序列的标签匹配模式来对时间序列进行过滤,目前主要支持两种匹配模式:完全匹配和正则匹配。总共有以下几种标签匹配运算符:
=
: 选择与提供的字符串完全相同的标签。!=
: 选择与提供的字符串不相同的标签。=~
: 选择正则表达式与提供的字符串(或子字符串)相匹配的标签。!~
: 选择正则表达式与提供的字符串(或子字符串)不匹配的标签。
例如:
过滤出具有handler="/login"的label的数据
http_request_total{handler=~".*login.*"}
剔除某个label
http_request_total{handler!~".*login.*"}
匹配两个值
http_request_total{handler=~"/login|/password"}
(2) 区间向量过滤器
区间向量与瞬时向量的工作方式类似,唯一的差异在于在区间向量表达式中我们需要定义时间选择的范围,时间范围通过时间范围选择器 []
进行定义,以指定应为每个返回的区间向量样本值中提取多长的时间范围。
时间范围通过数字来表示,单位可以使用以下其中之一的时间单位:
s
- 秒m
- 分钟h
- 小时d
- 天w
- 周y
- 年
例如:选择在过去 5 分钟内指标名称为 http_requests_total
,job
标签值为 prometheus
的所有时间序列:
http_requests_total{job="prometheus"}[5m]
(3) 时间位移操作
在瞬时向量表达式或者区间向量表达式中,都是以当前时间为基准
http_request_total{} # 瞬时向量表达式,选择当前最新的数据
http_request_total{}[5m] # 区间向量表达式,选择以当前时间为基准,5分钟内的数据
而如果我们想查询,5 分钟前的瞬时样本数据,或昨天一天的区间内的样本数据呢? 这个时候我们就可以使用位移操作,位移操作的关键字为 offset
。
例如:查询时间过去 5 分钟的 http_requests_total
值
注意:offset
关键字需要紧跟在选择器({}
)后面。
http_requests_total offset 5m
1.4.4 操作符
(1) 算术二元运算符
在 Prometheus 系统中支持下面的二元算术运算符:
+
加法-
减法*
乘法/
除法%
模^
幂等
例如:查看主机内存总大小(Mi)
node_memory_MemTotal_bytes / 1024 /1024
(2) 布尔运算符
目前,Prometheus 支持以下布尔运算符:
==
(相等)!=
(不相等)>
(大于)<
(小于)>=
(大于等于)<=
(小于等于)
例如:查看主机内存大于3000Mi的
node_memory_MemTotal_bytes / 1024 /1024 < 3000
(3) 集合运算符
使用瞬时向量表达式能够获取到一个包含多个时间序列的集合,我们称为瞬时向量。 通过集合运算,可以在两个瞬时向量与瞬时向量之间进行相应的集合操作。目前,Prometheus 支持以下集合运算符:
and
(并且)or
(或者)unless
(排除)
例如:
查看主机内存小于等于2772Mi 或者 主机内存等于3758.59765625Mi的
node_memory_MemTotal_bytes / 1024 /1024 <= 2772 or node_memory_MemTotal_bytes / 1024 /1024 == 3758.59765625
查看主机内存大于等于2772Mi,排除主机内存等于3758.59765625Mi的
node_memory_MemTotal_bytes / 1024 /1024 >= 2772 unless node_memory_MemTotal_bytes / 1024 /1024 == 3758.59765625
(4) 聚合操作
Prometheus 还提供了下列内置的聚合操作符,这些操作符作用域瞬时向量。可以将瞬时表达式返回的样本数据进行聚合,形成一个具有较少样本值的新的时间序列。
sum
(求和)min
(最小值)max
(最大值)avg
(平均值)stddev
(标准差)stdvar
(标准差异)count
(计数)count_values
(对 value 进行计数)bottomk
(样本值最小的 k 个元素)topk
(样本值最大的k个元素)quantile
(分布统计)
例如:
取总共的主机内存:
sum(node_memory_MemTotal_bytes) / 1024^2
根据某个字段进行统计:
sum(http_request_total) by (statuscode, handler)
取内存最小的主机
min(node_memory_MemTotal_bytes)
取所有主机的内存平均值
avg(node_memory_MemTotal_bytes)
所有http请求计数
count(http_request_total)
对value进行统计计数
count_values("count", node_memory_MemTotal_bytes)
取prometheus请求记录前5条记录,以code和handler分组
topk(5, sum(prometheus_http_requests_total) by (code, handler))
取prometheus请求记录后3条记录,以code和handler分组
bottomk(3, sum(prometheus_http_requests_total) by (code, handler))
取当前数据的中位数
quantile(0.5, prometheus_http_requests_total)
1.4.5 PromQL 常用内置函数
完整的内置函数文档参考:https://fuckcloudnative.io/prometheus/3-prometheus/functions.html
Prometheus 提供了其它大量的内置函数,可以对时序数据进行丰富的处理。某些函数有默认的参数,例如:year(v=vector(time()) instant-vector)
。其中参数 v
是一个瞬时向量,如果不提供该参数,将使用默认值 vector(time())
。instant-vector 表示参数类型。
increase()
increase(v range-vector)
函数获取区间向量中的第一个和最后一个样本并返回其增长量, 它会在单调性发生变化时(如由于采样目标重启引起的计数器复位)自动中断。由于这个值被外推到指定的整个时间范围,所以即使样本值都是整数,你仍然可能会得到一个非整数值。
例如: 查询过去1小时内,prometheus HTTP请求的每秒的增长率
increase(prometheus_http_requests_total{code="200",handler="/alerts",instance="0.0.0.0:9090",job="prometheus"}[1h]) / 3600
rate()
rate(v range-vector)
函数可以直接计算区间向量 v 在时间窗口内平均增长速率,它会在单调性发生变化时(如由于采样目标重启引起的计数器复位)自动中断。该函数的返回结果不带有度量指标,只有标签列表。
例如:查询过去1小时内,prometheus HTTP请求的每秒的增长率
rate(prometheus_http_requests_total{code="200",handler="/alerts",instance="0.0.0.0:9090",job="prometheus"}[1h])
irate()
irate(v range-vector)
函数用于计算区间向量的增长率,但是其反应出的是瞬时增长率。irate 函数是通过区间向量中最后两个两本数据来计算区间向量的增长速率,它会在单调性发生变化时(如由于采样目标重启引起的计数器复位)自动中断。这种方式可以避免在时间窗口范围内的“长尾问题”,并且体现出更好的灵敏度,通过irate函数绘制的图标能够更好的反应样本数据的瞬时变化状态。
不适合做需要分析长期趋势或者告警规则中使用。
predict_linear()
这个函数一般只用在 Gauge 类型的时间序列上。
predict_linear(v range-vector, t scalar)
函数可以预测时间序列 v 在 t 秒后的值。它基于简单线性回归的方式,对时间窗口内的样本数据进行统计,从而可以对时间序列的变化趋势做出预测。该函数的返回结果不带有度量指标,只有标签列表。
例如,基于 1 小时的样本数据,来预测主机可用磁盘空间的是否在 4 个小时候被占满,可以使用如下表达式:
predict_linear(node_filesystem_files_free{mountpoint="/"}[1h], 4*3600)
absent()
如果样本数据不为空则返回no data,如果为空则返回1。一般用于判断数据是否在正常采集。
absent(v instant-vector)
,如果传递给它的向量参数具有样本数据,则返回空向量;如果传递的向量参数没有样本数据,则返回不带度量指标名称且带有标签的时间序列,且样本值为1。
当监控度量指标时,如果获取到的样本数据是空的, 使用 absent 方法对告警是非常有用的。
ceil()
ceil(v instant-vector)
将 v 中所有元素的样本值向上四舍五入到最接近的整数。例如:2.79 -> 3
floor()
floor(v instant-vector)
函数与 ceil() 函数相反,将 v 中所有元素的样本值向下四舍五入到最接近的整数。例如:2.79 -> 2
delta()
delta(v range-vector)
的参数是一个区间向量,返回一个瞬时向量。它计算一个区间向量 v 的第一个元素和最后一个元素之间的差值。由于这个值被外推到指定的整个时间范围,所以即使样本值都是整数,你仍然可能会得到一个非整数值。
例如:取8小时之前和现在的磁盘可用空间的差值
delta(node_filesystem_files_free[8h])
sort()
sort(v instant-vector)
函数对向量按元素的值进行升序排序,返回结果:key: value = 度量指标:样本值[升序排列]。
sort_desc()
sort(v instant-vector)
函数对向量按元素的值进行降序排序,返回结果:key: value = 度量指标:样本值[降序排列]。
label_join()
将数据中的一个或多个label的值赋值给一个新label,参数依次为:目标变量、新的label的名、分隔符、被合并的第一个label、被合并的第二个label
label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...)
函数可以将时间序列 v 中多个标签 src_label
的值,通过 separator
作为连接符写入到一个新的标签 dst_label
中。可以有多个 src_label 标签
例如:
label_join(node_filesystem_files_free, "new_label", "-", "instance", "mountpoint")
返回如下
node_filesystem_files_free{container="kube-rbac-proxy", device="/dev/sda1", endpoint="https", fstype="xfs", instance="k8s-master01", job="node-exporter", mountpoint="/boot", namespace="monitoring", new_label="k8s-master01-/boot", pod="node-exporter-ztmr9", service="node-exporter"}
label_replace()
根据数据中的某个label值,进行正则匹配,然后赋值给新label并添加到数据中,参数依次为:目标变量、新的label名字、匹配取出字符的位置、正则匹配目标label值
为了能够让客户端的图标更具有可读性,可以通过 label_replace
函数为时间序列添加额外的标签。label_replace 的具体参数如下:
例如:把label名为instance的为目标,去除-开头的左边的字符,添加到host label中
label_replace(node_filesystem_files_free, "host", "$1", "instance", "(.*)-(.*)")
返回如下
node_filesystem_files_free{container="kube-rbac-proxy", device="/dev/sda1", endpoint="https", fstype="xfs", host="k8s", instance="k8s-master01", job="node-exporter", mountpoint="/boot", namespace="monitoring", pod="node-exporter-ztmr9", service="node-exporter"}
1.5 解决二进制安装k8s集群prometheus schedule和controller监控问题
1.5.1 报错详细
二进制安装的k8s集群,在安装完kube-prometheus后,prometheus中的alter会有如下几个Firing告警,注意需要解决KubeControllerManagerDown 和KubeSchedulerDown
1.5.2 报错原因
KubeControllerManagerDown的原因:
- 二进制安装的k8s的kube-contrller-manager监听地址为127.0.0.1,prometheus无法直接访问
- monitoring命名空间下的名为kube-controller-manager的servicemonitors资源,selector.matchLabels是
app.kubernetes.io/name: kube-controller-manager
,而kube-system命名空间下没有没有这个label的service
KubeSchedulerDown 的原因和以上相同不再描述,解决方案是相同的。
1.5.3 解决
- 修改kube-controller-manager和kube-schduler的systemd启动脚本,将
--address=127.0.0.1
改为--address=0.0.0.0
,之后重启 创建指定标签的service,这个service没有selector的,需要注意label和serviceMonitor一致,只需指向kube-controller-manager节点ip和端口的endpoint
apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/name: kube-controller-manager name: kube-controller-manager namespace: kube-system spec: ports: - name: https-metrics port: 10257 protocol: TCP targetPort: 10257 type: ClusterIP --- apiVersion: v1 kind: Endpoints metadata: labels: app.kubernetes.io/name: kube-controller-manager namespace: kube-system name: kube-controller-manager subsets: - addresses: - ip: 192.168.2.4 ports: - name: https-metrics port: 10257 protocol: TCP --- apiVersion: v1 kind: Service metadata: labels: app.kubernetes.io/name: kube-scheduler name: kube-scheduler namespace: kube-system spec: ports: - name: https-metrics port: 10259 protocol: TCP targetPort: 10259 type: ClusterIP --- apiVersion: v1 kind: Endpoints metadata: labels: app.kubernetes.io/name: kube-scheduler namespace: kube-system name: kube-scheduler subsets: - addresses: - ip: 192.168.2.4 ports: - name: https-metrics port: 10259 protocol: TCP
1.5.4 查看prometheus web页面
1.6 Prometheus监控etcd集群(云原生应用的监控)
1.6.1 访问etcd metrics接口测试
curl --cacert /etc/etcd/ssl/etcd-ca.pem --cert /etc/etcd/ssl/etcd.pem --key /etc/etcd/ssl/etcd-key.pem https://192.168.2.4:2379/metrics
1.6.2 创建etcd监控service和endpoints
apiVersion: v1
kind: Service
metadata:
labels:
app: etcd-monitor
name: etcd-monitor
namespace: kube-system
spec:
ports:
- name: etcd-port
port: 2379
protocol: TCP
targetPort: 2379
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
labels:
app: etcd-monitor
name: etcd-monitor
namespace: kube-system
subsets:
- addresses: # etcd节点对应的主机ip,有几台就写几台
- ip: 192.168.2.4
ports:
- name: etcd-port
port: 2379 # etcd端口
protocol: TCP
1.6.3 创建secret
将etcd的证书创建为单个secret资源
本例etcd证书位置分别为:
- cacert:/etc/etcd/ssl/etcd-ca.pem
- cert:/etc/etcd/ssl/etcd.pem
- key:/etc/etcd/ssl/etcd-key
kubectl -n monitoring create secret generic etcd-ssl --from-file=/etc/etcd/ssl/etcd-ca.pem --from-file=/etc/etcd/ssl/etcd.pem --from-file=/etc/etcd/ssl/etcd-key.pem
1.6.4 挂载secret到prometheus容器内
直接编辑名为k8s的prometheus资源
kubectl -n monitoring edit prometheus k8s
加入如下字段,是spec子级
secrets:
- etcd-ssl
查看挂载
[root@k8s-master01 ~]# kubectl -n monitoring exec -it prometheus-k8s-0 -c prometheus -- ls /etc/prometheus/secrets/etcd-ssl
etcd-ca.pem etcd-key.pem etcd.pem
1.6.5 创建etcd的ServiceMonitor资源
vim etcd-servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: etcd-monitor
namespace: monitoring
labels:
app: etcd-monitor
spec:
jobLabel: app
endpoints:
- interval: 30s
port: etcd-port # 这个port对应 Service.spec.ports.name
scheme: https
tlsConfig:
caFile: /etc/prometheus/secrets/etcd-ssl/etcd-ca.pem #证书路径 (在prometheus pod里路径)
certFile: /etc/prometheus/secrets/etcd-ssl/etcd.pem
keyFile: /etc/prometheus/secrets/etcd-ssl/etcd-key.pem
insecureSkipVerify: true # 关闭证书校验
selector:
matchLabels:
app: etcd-monitor # 跟svc的lables保持一致
namespaceSelector:
matchNames:
- kube-system # 跟svc所在namespace保持一致
# 匹配Kube-system这个命名空间下面具有app=etcd-k8s这个label标签的Serve,job label用于检索job任务名称的标签。由于证书serverName和etcd中签发的证书可能不匹配,所以添加了insecureSkipVerify=true将不再对服务端的证书进行校验
1.6.6 在promethus中查看target
1.6.7 grafana导入模板
中文版ETCD集群插件:https://grafana.com/grafana/dashboards/9733
指定导入id:9733即可
1.7 kafka集群监控(非云原生应用监控)
非云原生应用的监控需要依赖exporter,采集指定应用的数据然后提供metrics接口,供prometheus采集,以kafka为例,演示监控非原生应用。
kafka_exporter项目地址:https://github.com/danielqsj/kafka_exporter
1.7.1 创建kafka_exporter的deployment和servcice资源
apiVersion: apps/v1
kind: Deployment
metadata:
name: kafka-exporter
namespace: monitoring
labels:
app: kafka-exporter
spec:
replicas: 1
selector:
matchLabels:
app: kafka-exporter
template:
metadata:
name: kafka-exporter
labels:
app: kafka-exporter
spec:
restartPolicy: Always
containers:
- name: kafka-exporter
image: danielqsj/kafka-exporter
imagePullPolicy: IfNotPresent
env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
args: #这里是args而不是command,避免将kafka_exporter启动命令覆盖
- --kafka.server=kafka-0.kafka-headless.public-service:9092 #指定kafka的无头服务域名
ports:
- containerPort: 9308
name: monitor-port
protocol: TCP
volumeMounts:
- mountPath: /usr/share/zoneinfo/Asia/Shanghai
name: tz-config
- mountPath: /etc/timezone
name: timezone
volumes:
- name: tz-config
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
- name: timezone
hostPath:
path: /etc/timezone
---
apiVersion: v1
kind: Service
metadata:
name: kafka-exporter
namespace: monitoring
labels:
app: kafka-exporter
spec:
ports:
- port: 9308
protocol: TCP
targetPort: 9308
name: monitor-port #这个name和ServiceMonitor.spec.endpoints.port相对应
selector:
app: kafka-exporter
type: ClusterIP
1.7.2 创建kafka的servicemonitor资源
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: kafka-monitor
namespace: monitoring
labels:
app: kafka-monitor
spec:
jobLabel: app
endpoints:
- interval: 30s
port: monitor-port # 这个port对应 Service.spec.ports.name
scheme: http
selector:
matchLabels:
app: kafka-exporter # 跟service的lables保持一致
namespaceSelector:
matchNames:
- monitoring
1.7.3 kafka创建测试topic
kubectl -n public-service exec -it kafka-0 -- bash
kafka-topics.sh --create --zookeeper zookeeper:2181 --replication-factor 1 --partitions 1 --topic mytopic
1.7.4 Prometheus查看target
1.7.5 grafana导入模板
导入模板ID为:7589
1.8 黑盒监控
新版本kube-promethus默认已经安装了黑盒监控组件,无需手动安装。
1.8.1 概念
- 白盒监控:监控一些内部的数据,topic的监控数据,Redis key的大小。内部暴露的指标被称为白盒监控。比较关注的是原因。
黑盒监控:站在用户的角度看到的东西。网站不能打开,网站打开的比较慢。比较关注现象,表示正在发生的问题,正在发生的告警。
1.8.2 创建演示监控
传统方式(additional-scrape-config):
Prometheus自定义监控项目:https://github.com/prometheus/blackbox_exporter
kube-prometheus添加额外的抓取配置:https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/additional-scrape-config.md
新版本方式(添加Probe资源):
blackbox_exporter及Probe资源添加:https://github.com/prometheus-operator/kube-prometheus/blob/main/docs/blackbox-exporter.md
确保prometheus target中blackbox-exporter
存在,然后添加如下Probe资源,即可监控指定的网址
kind: Probe
apiVersion: monitoring.coreos.com/v1
metadata:
name: baidu-com-website
namespace: monitoring
spec:
interval: 60s
module: http_2xx
prober:
url: blackbox-exporter.monitoring.svc.cluster.local:19115
targets:
staticConfig:
static:
- http://www.baidu.com
- https://www.qq.com
添加Probe资源完成后,查看Prometheus的Configuration
1.9 Alertmanager
1.9.1 alertmanager主配置文件
# global块配置下的配置选项在本配置文件内的所有配置项下可见
global:
# 在Alertmanager内管理的每一条告警均有两种状态: "resolved"或者"firing". 在altermanager首次发送告警通知后, 该告警会一直处于firing状态,设置resolve_timeout可以指定处于firing状态的告警间隔多长时间会被设置为resolved状态, 在设置为resolved状态的告警后,altermanager不会再发送firing的告警通知.
resolve_timeout: 1h
# 邮件告警配置
smtp_smarthost: 'smtp.exmail.qq.com:25'
smtp_from: 'dukuan@xxx.com'
smtp_auth_username: 'dukuan@xxx.com'
smtp_auth_password: 'DKxxx'
# HipChat告警配置
# hipchat_auth_token: '123456789'
# hipchat_auth_url: 'https://hipchat.foobar.org/'
# wechat
wechat_api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
wechat_api_secret: 'JJ'
wechat_api_corp_id: 'ww'
# 告警通知模板
templates:
- '/etc/alertmanager/config/*.tmpl'
# route: 根路由,该模块用于该根路由下的节点及子路由routes的定义. 子树节点如果不对相关配置进行配置,则默认会从父路由树继承该配置选项。每一条告警都要进入route,即要求配置选项group_by的值能够匹配到每一条告警的至少一个labelkey(即通过POST请求向altermanager服务接口所发送告警的labels项所携带的<labelname>),告警进入到route后,将会根据子路由routes节点中的配置项match_re或者match来确定能进入该子路由节点的告警(由在match_re或者match下配置的labelkey: labelvalue是否为告警labels的子集决定,是的话则会进入该子路由节点,否则不能接收进入该子路由节点).
route:
# 例如所有labelkey:labelvalue含cluster=A及altertname=LatencyHigh labelkey的告警都会被归入单一组中
group_by: ['job', 'altername', 'cluster', 'service','severity']
# 若一组新的告警产生,则会等group_wait后再发送通知,该功能主要用于当告警在很短时间内接连产生时,在group_wait内合并为单一的告警后再发送
group_wait: 30s
# 再次告警时间间隔
group_interval: 5m
# 如果一条告警通知已成功发送,且在间隔repeat_interval后,该告警仍然未被设置为resolved,则会再次发送该告警通知
repeat_interval: 12h
# 默认告警通知接收者,凡未被匹配进入各子路由节点的告警均被发送到此接收者
receiver: 'wechat'
# 上述route的配置会被传递给子路由节点,子路由节点进行重新配置才会被覆盖
# 子路由树
routes:
# 该配置选项使用正则表达式来匹配告警的labels,以确定能否进入该子路由树
# match_re和match均用于匹配labelkey为service,labelvalue分别为指定值的告警,被匹配到的告警会将通知发送到对应的receiver
- match_re:
service: ^(foo1|foo2|baz)$
receiver: 'wechat'
# 在带有service标签的告警同时有severity标签时,他可以有自己的子路由,同时具有severity != critical的告警则被发送给接收者team-ops-mails,对severity == critical的告警则被发送到对应的接收者即team-ops-pager
routes:
- match:
severity: critical
receiver: 'wechat'
# 比如关于数据库服务的告警,如果子路由没有匹配到相应的owner标签,则都默认由team-DB-pager接收
- match:
service: database
receiver: 'wechat'
# 我们也可以先根据标签service:database将数据库服务告警过滤出来,然后进一步将所有同时带labelkey为database
- match:
severity: critical
receiver: 'wechat'
# 抑制规则,当出现critical告警时 忽略warning
inhibit_rules:
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
# Apply inhibition if the alertname is the same.
# equal: ['alertname', 'cluster', 'service']
#
# 收件人配置
receivers:
- name: 'team-ops-mails'
email_configs:
- to: 'dukuan@xxx.com'
- name: 'wechat'
wechat_configs:
- send_resolved: true
corp_id: 'ww'
api_secret: 'JJ'
to_tag: '1'
agent_id: '1000002'
api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
message: '{{ template "wechat.default.message" . }}'
#- name: 'team-X-pager'
# email_configs:
# - to: 'team-X+alerts-critical@example.org'
# pagerduty_configs:
# - service_key: <team-X-key>
#
#- name: 'team-Y-mails'
# email_configs:
# - to: 'team-Y+alerts@example.org'
#
#- name: 'team-Y-pager'
# pagerduty_configs:
# - service_key: <team-Y-key>
#
#- name: 'team-DB-pager'
# pagerduty_configs:
# - service_key: <team-DB-key>
#
#- name: 'team-X-hipchat'
# hipchat_configs:
# - auth_token: <auth_token>
# room_id: 85
# message_format: html
# notify: true
1.9.2 配置邮件告警
kube-prometheus中的alertmanger配置是通过secret挂载到pod中的,修改告警配置信息需要修改指定secret
查看secret
root@k8s-master01:~# kubectl -n monitoring get secrets alertmanager-main
NAME TYPE DATA AGE
alertmanager-main Opaque 1 13h
修改指定secret
通过直接修改源文件的方式添加邮件告警配置信息,路径为kube-prometheus/manifests/alertmanager-secret.yaml
apiVersion: v1
kind: Secret
metadata:
labels:
alertmanager: main
app.kubernetes.io/component: alert-router
app.kubernetes.io/name: alertmanager
app.kubernetes.io/part-of: kube-prometheus
app.kubernetes.io/version: 0.22.2
name: alertmanager-main
namespace: monitoring
stringData:
alertmanager.yaml: |-
"global":
"resolve_timeout": "5m"
"smtp_from": "1532916189@qq.com"
"smtp_smarthost": smtp.qq.com:465
"smtp_hello": "hello from alertmanager"
"smtp_auth_username": "1532916189@qq.com"
"smtp_auth_password": "xxxxxxxx"
"smtp_require_tls": false
"inhibit_rules":
- "equal":
- "namespace"
- "alertname"
"source_match":
"severity": "critical"
"target_match_re":
"severity": "warning|info"
- "equal":
- "namespace"
- "alertname"
"source_match":
"severity": "warning"
"target_match_re":
"severity": "info"
"receivers":
- "name": "Default"
"email_configs":
- "send_resolved": true
"to": "2576978433@qq.com"
- "name": "Watchdog"
"email_configs":
- "send_resolved": true
"to": "2576978433@qq.com"
- "name": "Critical"
"email_configs":
- "send_resolved": true
"to": "2576978433@qq.com"
"route":
"group_by":
- "namespace"
"group_interval": "5m"
"group_wait": "30s"
"receiver": "Default"
"repeat_interval": "12h"
"routes":
- "match":
"alertname": "Watchdog"
"receiver": "Watchdog"
- "match":
"severity": "critical"
"receiver": "Critical"
type: Opaque
在alertmanager pod中生成的配置文件如下
global:
resolve_timeout: 5m
邮件告警配置
smtp_from: 1532916189@qq.com
smtp_smarthost: smtp.qq.com:465
smtp_hello: hello from alertmanager
smtp_auth_username: 1532916189@qq.com
smtp_auth_password: xxxxxxxxxxxx
smtp_require_tls: false
# 抑制规则,当出现critical告警时 忽略warning
inhibit_rules:
- equal:
- namespace
- alertname
source_match:
severity: critical
target_match_re:
severity: warning|info
- equal:
- namespace
- alertname
source_match:
severity: warning
target_match_re:
severity: info
# 收件人配置
receivers:
- name: Default
email_configs:
- send_resolved: true
to: 2576978433@qq.com
- name: Watchdog
email_configs:
- send_resolved: true
to: 2576978433@qq.com
- name: Critical
email_configs:
- send_resolved: true
to: 2576978433@qq.com
route:
group_by:
- namespace
- job
- alertname
group_interval: 5m
group_wait: 30s
receiver: Default
repeat_interval: 12h
routes:
- match:
alertname: Watchdog
receiver: Watchdog
- match:
severity: critical
receiver: Critical
替换配置文件
kubectl replace -f kube-prometheus/manifests/alertmanager-secret.yaml
1.9.3 查看邮件报警信息
确保缩进正确,在配置完成后altertmanager容器会自动重新加载配置文件,查看邮箱告警信息
1.9.4 添加自定义报警规则
以blackbox为例演示自定义报警规则的编写,更多实例可参考这里:https://awesome-prometheus-alerts.grep.to/rules
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
labels:
app.kubernetes.io/component: exportor
app.kubernetes.io/name: blackbox-exportor
prometheus: k8s
role: alert-rules
name: blackbox
namespace: monitoring
spec:
groups:
- name: blackbox-exportor
rules:
- alert: BlackboxProbeSlowHttp
annotations:
description: |-
HTTP 请求时间 花费时间超过1秒
VALUE = {{ $value }}
LABELS = {{ $labels }}
summary: '检测到域名访问时间过长 (域名是 {{ $labels.instance }})'
expr: 'avg_over_time(probe_http_duration_seconds[1m]) > 1'
for: 1m
labels:
severity: warning
1.10 Prometheus自动发现
以自动发现集群内部ingress资源为例
1.10.1 添加additional configuration
编辑或者添加文件prometheus-additional.yaml
- job_name: 'auto_discovery'
metrics_path: /probe
params:
module: [http_2xx]
kubernetes_sd_configs:
- role: ingress
relabel_configs:
- source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_http_probe]
action: keep
regex: true
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
regex: (.+);(.+);(.+)
replacement: ${1}://${2}${3}
target_label: __param_target
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
regex: (.+);(.+);(.+)
replacement: ${1}://${2}${3}
target_label: target
- target_label: __address__
replacement: blackbox-exporter:9115
- source_labels: [__param_target]
target_label: instance
- action: labelmap
regex: __meta_kubernetes_ingress_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_ingress_name]
target_label: kubernetes_name
kubectl create secret generic additional-scrape-configs --from-file=prometheus-additional.yaml --dry-run -oyaml > additional-scrape-configs.yaml
kubectl apply -f additional-scrape-configs.yaml -n monitoring
编辑名为k8s
的prometheus资源
kubectl -n monitoring edit prometheus k8s
spec子级添加如下内容
additionalScrapeConfigs:
name: additional-scrape-configs
key: prometheus-additional.yaml
1.10.2 添加clusterrole和clusterrolebinding
自动发现需要对ingress资源有权限,建立对ingress有只读资源的custerrole,并创建clusterrolebinding给monitoring:prometheus-k8s SA权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ingress-view
rules:
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- watch
- list
kubectl -n monitoring create clusterrolebinding prometheus-discovery --clusterrole=ingress-view --serviceaccount=monitoring:prometheus-k8s
1.11 监控业务应用
以springboot应用为例,,监控jvm信息,https://github.com/gongchangwangpi/spring-cloud-demo2
1.11.1 手动配置应用监控
项目加入metrics
项目依赖加入metrics接口
修改依赖信息,spring-cloud-demo2/spring-cloud-eureka/pom.xml
加入如下依赖
<!-- Micrometer Prometheus registry -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- finished -->
项目配置文件加入:spring-cloud-demo2/spring-cloud-eureka/src/main/resources/application.yml
management:
endpoints:
web:
exposure:
include: '*'
shutdown:
enable: false
metrics:
tags:
application: "${spring.application.name}"
编译:
mvn clean package -DskipTests
启动
java -jar target/spring-cloud-eureka-0.0.1-SNAPSHOT.jar
通过additional configuration加入监控target
具体配置不详细说明,参考官方文档:https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/additional-scrape-config.md
- job_name: 'jvm-prometheus'
scheme: http
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['192.168.2.10:8761'] #springboot项目的地址,k8s集群内可以写成service地址
查看Prometheus target
grafana导入dashboard
导入id为12856
的dashboard
1.11.2 console自动发现应用监控
eureka配置eureka-consul-adapter
pom.xml
引入eureka-consul-adapter
<dependency>
<groupId>at.twinformatics</groupId>
<artifactId>eureka-consul-adapter</artifactId>
<version>1.4.0</version>
</dependency>
eureka-consul-adapter注意和springboot的版本匹配要求,本例的prometheus版本较高,eureka-consul-adapter应该采用1.4.0版本,如果采用较低版本会出现如下报错
level=error ts=2021-08-01T11:16:50.303Z caller=consul.go:513 component="discovery manager scrape" discovery=consul msg="Error refreshing service" service=CLOUD-USER tags= err="Unexpected response code: 404 ({\"timestamp\":\"2021-08-01T11:16:50.301+0000\",\"status\":404,\"error\":\"Not Found\",\"message\":\"No message available\",\"path\":\"/v1/health/service/CLOUD-USER\"})"
重新编译
mvn clean package -DskipTests
修改additional configuration
- job_name: 'jvm-discovery-prometheus'
scheme: http
metrics_path: '/actuator/prometheus'
consul_sd_configs:
- server: '192.168.2.10:8761' #eureka的地址
scheme: http
services: []
配置示例服务注册至eureka
注册配置不再详细解释,参考:https://blog.csdn.net/u014320421/article/details/78272678/
注册完成后访问eureka,可以看到名为CLOUD-USER的应用已经注册过来了
查看Prometheus target
可以看到配置的jvm-discovery-prometheus的job已经正常获取到了
查看Dashboard
可以看到prometheus已经通过自动发现获取到了注册到eureka的应用