原文链接:https://fuckcloudnative.io/posts/aggregate-metrics-user-prometheus-operator/

Promtheus 本身只支持单机部署,没有自带支持集群部署,也不支持高可用以及水平扩容,它的存储空间受限于本地磁盘的容量。同时随着数据采集量的增加,单台 Prometheus 实例能够处理的时间序列数会达到瓶颈,这时 CPU 和内存都会升高,一般内存先达到瓶颈,主要原因有:

  • Prometheus 的内存消耗主要是因为每隔 2 小时做一个 Block 数据落盘,落盘之前所有数据都在内存里面,因此和采集量有关。
  • 加载历史数据时,是从磁盘到内存的,查询范围越大,内存越大。这里面有一定的优化空间。
  • 一些不合理的查询条件也会加大内存,如 Group 或大范围 Rate。

这个时候要么加内存,要么通过集群分片来减少每个实例需要采集的指标。本文就来讨论通过 Prometheus Operator 部署的 Prometheus 如何根据服务维度来拆分实例。

1. 根据服务维度拆分 Prometheus

Prometheus 主张根据功能或服务维度进行拆分,即如果要采集的服务比较多,一个 Prometheus 实例就配置成仅采集和存储某一个或某一部分服务的指标,这样根据要采集的服务将 Prometheus 拆分成多个实例分别去采集,也能一定程度上达到水平扩容的目的。

在 Kubernetes 集群中,我们可以根据 namespace 来拆分 Prometheus 实例,例如将所有 Kubernetes 集群组件相关的监控发送到一个 Prometheus 实例,将其他所有监控发送到另一个 Prometheus 实例。

Prometheus Operator 通过 CRD 资源名 Prometheus 来控制 Prometheus 实例的部署,其中可以通过在配置项 serviceMonitorNamespaceSelector 和 podMonitorNamespaceSelector 中指定标签来限定抓取 target 的 namespace。例如,将 namespace kube-system 打上标签 monitoring-role=system,将其他的 namespace 打上标签 monitoring-role=others。

2. 告警规则拆分

将 Prometheus 拆分成多个实例之后,就不能再使用默认的告警规则了,因为默认的告警规则是针对所有 target 的监控指标的,每一个 Prometheus 实例都无法获取所有 target 的监控指标,势必会一直报警。为了解决这个问题,需要对告警规则进行拆分,使其与每个 Prometheus 实例的服务维度一一对应,按照上文的拆分逻辑,这里只需要拆分成两个告警规则,打上不同的标签,然后在 CRD 资源 Prometheus 中通过配置项 ruleSelector 指定规则标签来选择相应的告警规则。

3. 集中数据存储

解决了告警问题之后,还有一个问题,现在监控数据比较分散,使用 Grafana 查询监控数据时我们也需要添加许多数据源,而且不同数据源之间的数据还不能聚合查询,监控页面也看不到全局的视图,造成查询混乱的局面。

为了解决这个问题,我们可以让 Prometheus 不负责存储数据,只将采集到的样本数据通过 Remote Write 的方式写入远程存储的 Adapter,然后将 Grafana 的数据源设为远程存储的地址,就可以在 Grafana 中查看全局视图了。这里选择 VictoriaMetrics 来作为远程存储。VictoriaMetrics 是一个高性能,低成本,可扩展的时序数据库,可以用来做 Prometheus 的长期存储,分为单机版本和集群版本,均已开源。如果数据写入速率低于每秒一百万个数据点,官方建议使用单节点版本而不是集群版本。本文作为演示,仅使用单机版本,架构如图:

4. 实践

确定好了方案之后,下面来进行动手实践。

部署 VictoriaMetrics

首先部署一个单实例的 VictoriaMetrics,完整的 yaml 如下:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: victoriametrics
namespace: kube-system
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: victoriametrics
name: victoriametrics
namespace: kube-system
spec:
serviceName: pvictoriametrics
selector:
matchLabels:
app: victoriametrics
replicas: 1
template:
metadata:
labels:
app: victoriametrics
spec:
nodeSelector:
blog: "true"
containers:
- args:
- --storageDataPath=/storage
- --httpListenAddr=:8428
- --retentionPeriod=1
image: victoriametrics/victoria-metrics
imagePullPolicy: IfNotPresent
name: victoriametrics
ports:
- containerPort: 8428
protocol: TCP
readinessProbe:
httpGet:
path: /health
port: 8428
initialDelaySeconds: 30
timeoutSeconds: 30
livenessProbe:
httpGet:
path: /health
port: 8428
initialDelaySeconds: 120
timeoutSeconds: 30
resources:
limits:
cpu: 2000m
memory: 2000Mi
requests:
cpu: 2000m
memory: 2000Mi
volumeMounts:
- mountPath: /storage
name: storage-volume
restartPolicy: Always
priorityClassName: system-cluster-critical
volumes:
- name: storage-volume
persistentVolumeClaim:
claimName: victoriametrics
---
apiVersion: v1
kind: Service
metadata:
labels:
app: victoriametrics
name: victoriametrics
namespace: kube-system
spec:
ports:
- name: http
port: 8428
protocol: TCP
targetPort: 8428
selector:
app: victoriametrics
type: ClusterIP

有几个启动参数需要注意:

  • storageDataPath : 数据目录的路径。 VictoriaMetrics 将所有数据存储在此目录中。
  • retentionPeriod : 数据的保留期限(以月为单位)。旧数据将自动删除。默认期限为1个月。
  • httpListenAddr : 用于监听 HTTP 请求的 TCP 地址。默认情况下,它在所有网络接口上监听端口 8428。

给 namespace 打标签

为了限定抓取 target 的 namespace,我们需要给 namespace 打上标签,使每个 Prometheus 实例只抓取特定 namespace 的指标。根据上文的方案,需要给 kube-system 打上标签 monitoring-role=system:

$ kubectl label ns kube-system monitoring-role=system

给其他的 namespace 打上标签 monitoring-role=others。例如:

$ kubectl label ns monitoring monitoring-role=others
$ kubectl label ns default monitoring-role=others

拆分 PrometheusRule

告警规则需要根据监控目标拆分成两个 PrometheusRule。具体做法是将 kube-system namespace 相关的规则整合到一个 PrometheusRule 中,并修改名称和标签:

# prometheus-rules-system.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
labels:
prometheus: system
role: alert-rules
name: prometheus-system-rules
namespace: monitoring
spec:
groups:
...
...

剩下的放到另外一个 PrometheusRule 中,并修改名称和标签:

# prometheus-rules-others.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
labels:
prometheus: others
role: alert-rules
name: prometheus-others-rules
namespace: monitoring
spec:
groups:
...
...

然后删除默认的 PrometheusRule:

$ kubectl -n monitoring delete prometheusrule prometheus-k8s-rules

新增两个 PrometheusRule:

$ kubectl apply -f prometheus-rules-system.yaml
$ kubectl apply -f prometheus-rules-others.yaml

如果你实在不知道如何拆分规则,或者不想拆分,想做一个伸手党,可以看这里:

拆分 Prometheus

下一步是拆分 Prometheus 实例,根据上面的方案需要拆分成两个实例,一个用来监控 kube-system namespace,另一个用来监控其他 namespace:

# prometheus-prometheus-system.yaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
labels:
prometheus: system
name: system
namespace: monitoring
spec:
remoteWrite:
- url: http://victoriametrics.kube-system.svc.cluster.local:8428/api/v1/write
queueConfig:
maxSamplesPerSend: 10000
retention: 2h
alerting:
alertmanagers:
- name: alertmanager-main
namespace: monitoring
port: web
image: quay.io/prometheus/prometheus:v2.17.2
nodeSelector:
beta.kubernetes.io/os: linux
podMonitorNamespaceSelector:
matchLabels:
monitoring-role: system
podMonitorSelector: {}
replicas: 1
resources:
requests:
memory: 400Mi
limits:
memory: 2Gi
ruleSelector:
matchLabels:
prometheus: system
role: alert-rules
securityContext:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 1000
serviceAccountName: prometheus-k8s
serviceMonitorNamespaceSelector:
matchLabels:
monitoring-role: system
serviceMonitorSelector: {}
version: v2.17.2
---
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
labels:
prometheus: others
name: others
namespace: monitoring
spec:
remoteWrite:
- url: http://victoriametrics.kube-system.svc.cluster.local:8428/api/v1/write
queueConfig:
maxSamplesPerSend: 10000
retention: 2h
alerting:
alertmanagers:
- name: alertmanager-main
namespace: monitoring
port: web
image: quay.io/prometheus/prometheus:v2.17.2
nodeSelector:
beta.kubernetes.io/os: linux
podMonitorNamespaceSelector:
matchLabels:
monitoring-role: others
podMonitorSelector: {}
replicas: 1
resources:
requests:
memory: 400Mi
limits:
memory: 2Gi
ruleSelector:
matchLabels:
prometheus: others
role: alert-rules
securityContext:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 1000
serviceAccountName: prometheus-k8s
serviceMonitorNamespaceSelector:
matchLabels:
monitoring-role: others
serviceMonitorSelector: {}
additionalScrapeConfigs:
name: additional-scrape-configs
key: prometheus-additional.yaml
version: v2.17.2

需要注意的配置:

  • 通过 remoteWrite 指定 remote write 写入的远程存储。
  • 通过 ruleSelector 指定 PrometheusRule。
  • 限制内存使用上限为 2Gi,可根据实际情况自行调整。
  • 通过 retention 指定数据在本地磁盘的保存时间为 2 小时。因为指定了远程存储,本地不需要保存那么长时间,尽量缩短。
  • Prometheus 的自定义配置可以通过 additionalScrapeConfigs 在 others 实例中指定,当然你也可以继续拆分,放到其他实例中。

删除默认的 Prometheus 实例:

$ kubectl -n monitoring delete prometheus k8s

创建新的 Prometheus 实例:

$ kubectl apply -f prometheus-prometheus.yaml

查看运行状况:

$ kubectl -n monitoring get prometheus
NAME VERSION REPLICAS AGE
system v2.17.2 1 29h
others v2.17.2 1 29h $ kubectl -n monitoring get sts
NAME READY AGE
prometheus-system 1/1 29h
prometheus-others 1/1 29h
alertmanager-main 1/1 25d

查看每个 Prometheus 实例的内存占用:

$ kubectl -n monitoring top pod -l app=prometheus
NAME CPU(cores) MEMORY(bytes)
prometheus-others-0 12m 110Mi
prometheus-system-0 121m 1182Mi

最后还要修改 Prometheus 的 Service,yaml 如下:

apiVersion: v1
kind: Service
metadata:
labels:
prometheus: system
name: prometheus-system
namespace: monitoring
spec:
ports:
- name: web
port: 9090
targetPort: web
selector:
app: prometheus
prometheus: system
sessionAffinity: ClientIP
---
apiVersion: v1
kind: Service
metadata:
labels:
prometheus: others
name: prometheus-others
namespace: monitoring
spec:
ports:
- name: web
port: 9090
targetPort: web
selector:
app: prometheus
prometheus: others
sessionAffinity: ClientIP

删除默认的 Service:

$ kubectl -n monitoring delete svc prometheus-k8s

创建新的 Service:

$ kubectl apply -f prometheus-service.yaml

修改 Grafana 数据源

Prometheus 拆分成功之后,最后还要修改 Grafana 的数据源为 VictoriaMetrics 的地址,这样就可以在 Grafana 中查看全局视图,也能聚合查询。

打开 Grafana 的设置页面,将数据源修改为 http://victoriametrics.kube-system.svc.cluster.local:8428:

点击 Explore 菜单:

在查询框内输入 up,然后按下 Shift+Enter 键查询:

可以看到查询结果中包含了所有的 namespace。

写这篇文章的起因是我的 k3s 集群每台节点的资源很紧张,而且监控的 target 很多,导致 Prometheus 直接把节点的内存资源消耗完了,不停地 OOM。为了充分利用我的云主机,不得不另谋他路,这才有了这篇文章。


Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12离线安装包发布地址http://store.lameleg.com ,欢迎体验。 使用了最新的sealos v3.3.6版本。 作了主机名解析配置优化,lvscare 挂载/lib/module解决开机启动ipvs加载问题, 修复lvscare社区netlink与3.10内核不兼容问题,sealos生成百年证书等特性。更多特性 https://github.com/fanux/sealos 。欢迎扫描下方的二维码加入钉钉群 ,钉钉群已经集成sealos的机器人实时可以看到sealos的动态。

Prometheus Operator 教程:根据服务维度对 Prometheus 分片的更多相关文章

  1. Prometheus 入门教程(一):Prometheus 快速入门

    文章首发于[陈树义]公众号,点击跳转到原文:https://mp.weixin.qq.com/s/ZXlBPHGcWeYh2hjBzacc3A Prometheus 是任何一个高级工程师必须要掌握的技 ...

  2. Prometheus入门教程(二):Prometheus + Grafana实现可视化、告警

    文章首发于[陈树义]公众号,点击跳转到原文:https://mp.weixin.qq.com/s/56S290p4j9KROB5uGRcGkQ Prometheus UI 提供了快速验证 PromQL ...

  3. k8s Helm安装Prometheus Operator

    Ubuntu 18 Kubernetes集群的安装和部署 以及Helm的安装完成了k8s的集群和helm的安装,今天我们来看看Prometheus的监控怎么搞.Prometheus Operator ...

  4. prometheus operator(Kubernetes 集群监控)

    一.Prometheus Operator 介绍 Prometheus Operator 是 CoreOS 开发的基于 Prometheus 的 Kubernetes 监控方案,也可能是目前功能最全面 ...

  5. 使用Prometheus Operator 监控Kubernetes(15)

    一.Prometheus概述: Prometheus是一个开源系统监测和警报工具箱. Prometheus Operator 是 CoreOS 开发的基于 Prometheus 的 Kubernete ...

  6. Kubernetes 监控:Prometheus Operator

    安装 前面的章节中我们学习了用自定义的方式来对 Kubernetes 集群进行监控,基本上也能够完成监控报警的需求了.但实际上对上 Kubernetes 来说,还有更简单方式来监控报警,那就是 Pro ...

  7. Prometheus Operator 对接 Thanos

    文章转载自:https://jishuin.proginn.com/p/763bfbd56ae4 使用 Prometheus Operator 来进行监控,在 Prometheus 高可用的章节中也手 ...

  8. Prometheus Operator - 每天5分钟玩转 Docker 容器技术(177)

    前面我们介绍了 Kubernetes 的两种监控方案 Weave Scope 和 Heapster,它们主要的监控对象是 Node 和 Pod.这些数据对 Kubernetes 运维人员是必须的,但还 ...

  9. Kubernetes 监控方案之 Prometheus Operator(十九)

    目录 一.Prometheus 介绍 1.1.Prometheus 架构 1.2.Prometheus Operator 架构 二.Helm 安装部署 2.1.Helm 客户端安装 2.2.Tille ...

随机推荐

  1. Firefox 底部多出了一个白条

    如图所示 下方多了个白条 html{ font-size:0px; }

  2. OSCP Learning Notes - Capstone(2)

    BTRSys v2.1 Walkthrough Preparation: Download the BTRSys virtual machine from the following website: ...

  3. 五大高效的PDF文件搜索引擎

    当你花了半个多小时在线搜索PDF文档,却发现您找到的文档都不是您需要的PDF格式.如前说述,您可以先打开PDF文档查看是不是PDF格式的,然后再到web浏览器中下载该文档.那么,为了确保您获得的文档是 ...

  4. super,this关键字用法 Java

    super 用法 1.调用父类变量2.调用父类方法3.子类构造方法第一句 this 用法 super关键字用来访问父类内容, this 关键字用来访问本类中的内容, 有三种用法 1.在本类的成员方法中 ...

  5. Windows下安装Python 3.X 版本

    一. Python下载 Python官方下载地址 演示下载的版本为Python 3.8.3 ,你可以根据自己的选择安装其他版本的Python 二. Python 安装 下载完安装包双击安装时出错(Wi ...

  6. Ribbon负载均衡接口

    IRule--负载均衡规则 1.RounRobinRule:轮询负载均衡,通过累加取余获取服务,默认规则 2.RandomRule:随机负载均衡 3.WeightedResponseTimeRule: ...

  7. asp.net core 3 使用nlog日志组件,使用$ {basedir}保存位置不对,记录下怎么解决

    $ {basedir}指向的是  AppDomain.CurrentDomain.BaseDirectory, Asp.Net.Core的解决方法可能如下(在Program.cs中添加两行): var ...

  8. 学习 bypass csp记录

    最近看到一篇bypas csp的记录复现学习下 配置csp 这里直接设置html头达到配置csp的效果. Content-Security-Policy: script-src 'self' 'uns ...

  9. python学习笔记1 -- 面向对象编程高级编程1

    说起高级其实也就是些基础的东西,但是活用和熟用肯定会大幅度提升代码质量 首先要记录的是面向对象的灵活性,及如何去控制其灵活性,她允许你在实例中新增属性和方法,允许你给类新增属性和方法,也支持在定义类时 ...

  10. 使用@ControllerAdvice处理异常

    在Spring 3.2中,新增了@ControllerAdvice.@RestControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder.@Mode ...