前言
书接上文,经过之前的不懈努力,我们已经有了较为完善的监控系统与告警系统,而prometheus的工作模式就像一个单点,拉取数据回来之后存储在自己的磁盘上
当监控数据越来越多,那prometheus单点的压力就会变大,那本文就来讨论一下如何降低单点prometheus的压力
环境准备
组件 | 版本 |
---|---|
操作系统 | Ubuntu 22.04.4 LTS |
docker | 24.0.7 |
kube-state-metrics | v2.13.0 |
thanos | 0.36.1 |
水平拆分
水平拆分的目的就是为了拆成多个prometheus,让单个prometheus负载降低,不要这么容易挂掉,并且拆成多个之后,就算挂掉一个,其余的也可以正常工作。比如一个prometheus专门负责节点监控数据采集、一个prometheus专门负责k8s监控数据采集等
1. 根据采集的目标进行拆分
每个业务都有一个prometheus对其进行采集,并且不同prometheus之间解耦
这时候业务部门提出需求,k8s的监控还是太多了,一个prometheus依然不堪重负,那怎么办呢?
2. kube-state-metrics拆分
由于k8s是通过kube-state-metrics
这个exporter进行采集,所以我们需要对其进行拆分
2.1 根据namespace进行拆分
这个拆分是显而易见的,不同的namespace采集进入不同的prometheus即可,配置也很简单,只需要修改kube-state-metrics
的启动参数即可
apiVersion: apps/v1
kind: Deployment
metadata:
name: kube-state-metrics
namespace: kube-system
spec:
replicas: 1
selector:
matchLabels:
app: kube-state-metrics
template:
metadata:
labels:
app: kube-state-metrics
spec:
serviceAccountName: kube-state-metrics
containers:
- args:
- --metric-labels-allowlist=pods=[*]
- --metric-annotations-allowlist=pods=[*]
- --namespaces=default # 新增
name: kube-state-metrics
image: registry.cn-beijing.aliyuncs.com/wilsonchai/kube-state-metrics:v2.13.0
ports:
- containerPort: 8080
--namespaces=default
告诉kube-state-metrics只采集namespace为default
的数据
创建多个prometheus以及kube-state-metrics,然后指定采集不同的namespace
这种方法配置简单,但是分配多个kube-state-metrics
的采集策略就比较复杂,一旦业务复杂,namespace多起来之后,也会造成频繁修改配置,还有没有更简单的方法呢?
2.2 kube-state-metrics根据shard拆分
在kube-state-metrics
的高版本(具体是哪个版本待查,笔者的版本是v2.13.0),支持了自动分片的采集策略,就是让多个kube-state-metrics
自己去分片,省去人为配置的烦恼
关于水平分片的例子,可以参考 kube-state-metrics
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/name: kube-state-metrics
app.kubernetes.io/version: v2.13.0
name: kube-state-metrics
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- apps
resourceNames:
- kube-state-metrics
resources:
- statefulsets
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/name: kube-state-metrics
app.kubernetes.io/version: v2.13.0
name: kube-state-metrics
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kube-state-metrics
subjects:
- kind: ServiceAccount
name: kube-state-metrics
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: kube-state-metrics
app.kubernetes.io/version: v2.13.0
name: kube-state-metrics
namespace: kube-system
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: kube-state-metrics
serviceName: kube-state-metrics
template:
metadata:
labels:
app.kubernetes.io/name: kube-state-metrics
app.kubernetes.io/version: v2.13.0
spec:
containers:
- args:
- --pod=$(POD_NAME)
- --pod-namespace=$(POD_NAMESPACE)
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: registry.cn-beijing.aliyuncs.com/wilsonchai/kube-state-metrics:v2.13.0
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 5
name: kube-state-metrics
ports:
- containerPort: 8080
name: http-metrics
- containerPort: 8081
name: telemetry
readinessProbe:
httpGet:
path: /
port: 8081
initialDelaySeconds: 5
timeoutSeconds: 5
securityContext:
runAsUser: 65534
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: kube-state-metrics
启动起来之后检查一下metrics的指标数量
▶ curl -s 10.244.0.107:8080/metrics | wc -l
949
▶ curl -s 10.244.0.108:8080/metrics | wc -l
909
看起来已经打散到2个节点去了,如果我再增加一个节点,那指标数量又分散了
▶ curl -s 10.244.0.107:8080/metrics | wc -l
702
▶ curl -s 10.244.0.108:8080/metrics | wc -l
733
▶ curl -s 10.244.0.109:8080/metrics | wc -l
663
这时候只需要把不同的prometheus配置采集不同kube-state-metrics即可,架构也变成了这个样子
当然kube-state-metrics
也是有手动分片模式的,就是通过参数--shard
来实现了,只不过有自动分片的话,没有极致特殊的需求,我们还是用自动分片来处理更加合适
多prometheus数据汇聚
当我们拆分了监控数据,用不同的prometheus来采集的时候,又带来了新的问题
-
由于prometheus使用本地磁盘存储数据,所以通过prometheus的web界面查看监控数据时,也只能查看到本prometheus的监控数据,不能跨prometheus查询监控数据
-
使用grafana添加数据源的时候,就出现了多prometheus数据源的情况,造成管理复杂
-
有一个公共的storage组件,prometheus通过remote_write的方式,把数据汇聚在这个组件,就可以解决数据分散的问题,并且数据存储的方式就很灵活了,可以存储在本地,然后通过传统的raid做数据备份,也可以直接通过云 平台的对象存储保存历史数据
-
最后再来一个统一的web界面进行查询,同时这个web界面兼容了prometheus的promQL,并且兼容了prometheus的api,可以直接作为数据源添加至grafana中
-
有这种功能的组件就很多了,比如thanos、cortext、influxDB等等,都可以完成这个工作
小结
- 下一小节,通过thanos来详细讨论一下怎么做数据汇聚
联系我
- 联系我,做深入的交流
至此,本文结束
在下才疏学浅,有撒汤漏水的,请各位不吝赐教...