基于Thanos sidecar模式扩展Prometheus
一、 Prometheus使用现状
Prometheus上了生产环境不足的地方:
- 缺乏全局视图,无法管理多个Prometheus。即便使用联邦机制,GlobalPrometheus也会遇到大数据量瓶颈。
- 缺乏历史数据的长期存储方案,必需依赖第三方存储,缺少针对历史数据的降采样。
- 单实例,不可扩展。即便手动扩展多实例后,缺乏去重机制,无法满足数据一致性。Prometheus只聚焦核心的功能,扩展性的功能留给社区解决。
在这种监控方案局限的背景下,Thanos监控技术栈诞生了。Thanos的出现不是为了取代Prometheus,是为了我们更好的使用Prometheus。
二、 Thanos使用背景
为什么选择Thaons:
- 全局查询: Thaons可以跨多个Prometheus实例来查询存储的监控指标
- 无限制存储: Thanos本身不提供存储,但是它支持对象存储系统,使用对象存储来扩容数据存储,以此来无限的存储监控数据。Prometheus自从2.x版本加入Remote Read/Write API后,社区涌现大量长期存储的方案。但是通过Thanos使用对象存储后,降本效果十分明显。
- 兼容Prometheus: Thanos 完全兼容Prometheus的API接口,无论使用Grafana或者其他支持Prometheus API的工具,使用过程无任何异样。
- 数据降准和压缩:Thanos会对Prometheus的数据进行降准,当查询大时间范围内的监控数据或者配置复杂的保留策略时可以加快查询速度,另外也会对实时数据进行压缩。
- 高可用集群:Thanos可以针对Prometheus提供高可用集群,并对重复数据进行删除和合并。
- 无侵入性:Prometheus版本快速更迭,一旦有侵入绑定,升级优化会变得很烦。Thanos通过sidecar模式或者receiver模式进行数据的转储,未侵入修改。
三、 Thanos sidecar模式架构
Thanos Sidecar组件需要和Prometheus实例一起部署,该模式为默认模式,该模式的特点:
- Thanos sidecar基于Prometheus Remote Read API获取block数据,然后上传给对象存储,这个上传是实时的,只要发现有新的监控数据保存到磁盘。
- Thanos sidecar实现了store api接口负责querier组件的查询需求。(只会查询2h内未落盘的指标)
Thanos的核心组件包括: Sidecar、Querier/Query、Store/Store gateway、Compactor、
- Sideacr主要负责连接Prometheus,并把Prometheus的数据暴露给查询网关(querier)提供实时查询,并且可以上传Block数据至对象存储。
- Querier组件实现了Prometheus HTTP V1 API,可以通过PromQL在Thanos系统里面查询指标数据。简而言之,它从底层 StoreAPI 收集评估查询所需的数据,评估查询并返回结果。Querier组件是完全无状态的,可以水平扩缩。
- Store组件用来暴露对象存储桶中的历史指标数据。Store Gateway 公开了 Store API,可以被 ThanosQuerier发现。
- Compactor组件会下载读取对象存储中的Block数据进行压缩和降采样,然后上传处理后的Block,也是为一个能Delete Bolck数据的组件
四、Thanos组件部署
前提条件:Kubernetes容器环境、k8s集群已经安装Prometheus-operator或者Kube-prometheus。
注意: Prometheus版本不得低于v2.2.1。推荐Prometheus版本大于2.13,这之后优化了remote read、remote write API
当前演示环境为: 1.27 kubernetes & Kube-prometheus 0.13 release版本(对应Prometheus v2.46)
各组件部署顺序可参考序号标识:先准备对象存储、然后集成Thanos sidecar 、、、
4.1 创建对象存储
Thanos 使用对象存储作为指标和元数据的主要存储。sidecar,compactor,store都涉及对象存储的配置。
-
前往OBS云服务创建存储介质
Prometheus采集的历史指标数据都会存放在对象存储里
-
构建对象存储配置文件
type: s3 config: bucket: for-thanos-store #桶名称 endpoint: obs.cn-north-4.myhuaweicloud.com access_key: xxx # 云服务账号aksk信息 secret_key: xxx insecure: true signature_version2: false
-
根据以上配置文件创建k8s secret
kubectl create secret generic thanos-obs --from-file=thanos.yaml=thanos-storage-obs.yaml -n monitoring
创建完成。
4.2 Thanos Sidecar集成
-
修改Prometheus CRD
Thanos Sidecar容器需要伴随Prometheus容器一同部署,所以需要修改Prometheus的部署配置:
kubectl get prometheus -n monitoring
,查看集群中的Prometheus设置:
kubectl edit prometheus k8s -n monitoring
修改内容如下:apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.46.0 name: k8s namespace: monitoring spec: alerting: alertmanagers: - apiVersion: v2 name: alertmanager-main namespace: monitoring port: web enableFeatures: [] externalLabels: {} image: quay.io/prometheus/prometheus:v2.46.0 nodeSelector: kubernetes.io/os: linux podMetadata: labels: app.kubernetes.io/component: prometheus app.kubernetes.io/instance: k8s app.kubernetes.io/name: prometheus app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 2.46.0 podMonitorNamespaceSelector: {} podMonitorSelector: {} probeNamespaceSelector: {} probeSelector: {} replicas: 2 resources: requests: memory: 400Mi ruleNamespaceSelector: {} ruleSelector: {} securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 1000 serviceAccountName: prometheus-k8s serviceMonitorNamespaceSelector: {} serviceMonitorSelector: {} version: 2.46.0 # 添加thanos sidecar thanos: image: thanosio/thanos:v0.32.0 resources: limits: cpu: 500m memory: 500Mi requests: cpu: 100m memory: 100Mi objectStorageConfig: key: thanos.yaml name: thanos-obs enableAdminAPI: true #允许 Thanos 的 Sidecar 从 Prometheus 获取元数据。 retention: 10h #设置本地数据保存时间。默认是24h # Prometheus数据持久化,2h内的 storage: volumeClaimTemplate: metadata: name: prometheus-k8s-db labels: failure-domain.beta.kubernetes.io/region: cn-north-4 #failure-domain.beta.kubernetes.io/zone: cn-north-4a annotations: everest.io/disk-volume-type: GPSSD spec: accessModes: - ReadWriteOnce resources: requests: storage: 11Gi storageClassName: csi-disk-topology
-
修改重点说明,如何注入thanos sidecar
Promethues crd 支持添加thanos sidecar至Pod中。需要显式配置spec.thanos.xxx
相关参数,包括镜像版本选择(必选)、资源配额限制、以及访问对象存储OBS桶的密钥配置。thanos: image: thanosio/thanos:v0.32.0 resources: limits: cpu: 500m memory: 500Mi requests: cpu: 100m memory: 100Mi objectStorageConfig: key: thanos.yaml name: thanos-obs
另外还需注意
enableAdminAPI: true
必须配置,表示允许Thanos sidecar 从prometheus中获取元数据。 -
修改重点说明,本地数据持久化
开源Prometheus-operator、kube-prometheus进行安装时,没有对Prometheus设置数据持久化,默认使用emptyDir保存数据,如果Promtheus服务宕机或者重启,~2h内的所用样本数据都会丢失。所以有必要对prometheus配置storage保证本地数据持久化。storage: volumeClaimTemplate: metadata: name: prometheus-k8s-db labels: failure-domain.beta.kubernetes.io/region: cn-north-4 #failure-domain.beta.kubernetes.io/zone: cn-north-4a annotations: everest.io/disk-volume-type: GPSSD spec: accessModes: - ReadWriteOnce resources: requests: storage: 11Gi storageClassName: csi-disk-topology
需要注意下配置合适的本地存储硬盘的大小,设置过小会因为数据堆积导致Thanos sidecar无法上传Block至对象存储、也会Prometheus 容器因磁盘空间不足导致宕机。
另外还需关注spec.retention
的配置,表示本地数据的保存时间,默认是24h,最低不要少于6h。 -
注入Thanos sidecar配置后,观察容器启动参数变化
Prometheus容器启动参数会添加:--storage.tsdb.max-block-duration=2h
--storage.tsdb.min-block-duration=2h
这两个参数相等会保证Prometheus关闭本地压缩,如果不关闭本地压缩,Thanos sidcar无法上传Block块至对象存储中。
thanos-sidecar容器参数会添加Prometheus访问地址、对象存储的访问信息、以及本地数据的存储路径
-
Thanos sidecar部署后,可通过查看sidecar容器日志验证是否接入成功
Thanos sidecar集成后,如果需要验证block上传情况,最少需要等待2h,第一次upload block时间略长。完成upload后,可前往对象存储查看上传数据
-
Thaons sidecar每隔30s读取一次本地元数据,查看是否有新的监控数据落盘,如果有则读取本地数据块并将其上传到对象存储。标记最新的读取时间,并通过本地json文件保存已经上传的块,避免重复上传。可以通过查看容器中的thanos.shipper.json文件查看上传信息
4.3 Thanos Querier集成
Prometheus是有状态的,存储的数据相互独立。这意味着,通过运行多个 Prometheus 副本来提高高可用性并不容易。例如,在某个副本实例崩溃后,后面恢复正常,但查询该副本数据时,会发现在其宕机期间出现了一个数据小缺口。第二个副本可能是正常的,但也有可能在其他时间段(如滚动重启)宕机,因此在这些副本上实现负载平衡的效果并不好。
但是Thanos Querier组件在查询层可以帮助我们从收集的指标中进行重复数据删除从而实现Prometheus 高可用。
-
部署yaml文件如下
Querier组件是无状态的,以Deployment形式部署。# thanos-querier.yaml apiVersion: apps/v1 kind: Deployment metadata: name: thanos-querier namespace: monitoring labels: app: thanos-querier spec: replicas: 1 selector: matchLabels: app: thanos-querier template: metadata: labels: app: thanos-querier spec: containers: - name: thanos image: thanosio/thanos:v0.32.0 args: - query - --log.level=info # 可选debug、等 - --query.replica-label=prometheus_replica #- --store=dnssrv+thanos-store:10901 #- --store=dnssrv+prometheus-operated:10901 - --endpoint=dnssrv+_grpc._tcp.thanos-store:10901 - --endpoint=dnssrv+_grpc._tcp.prometheus-operated:10901 ports: - name: http containerPort: 10902 - name: grpc containerPort: 10901 resources: requests: memory: 512Mi cpu: 500m limits: memory: 1Gi cpu: 1 livenessProbe: httpGet: path: /-/healthy port: http initialDelaySeconds: 10 readinessProbe: httpGet: path: /-/healthy port: http initialDelaySeconds: 15 --- apiVersion: v1 kind: Service metadata: name: thanos-querier namespace: monitoring labels: app: thanos-querier spec: ports: - port: 9090 targetPort: http name: http selector: app: thanos-querier type: NodePort
其中前端界面访问端口为
10902
。可以通过service选择对外暴露访问端点
-
Querier关键启动参数解读
- --query.replica-label=prometheus_replica
: prometheus-operator中replicaExternalLabelName
默认为:prometheus_replica
, 当prometheus对接远程存储时会在指标中加上该标签。Querier根据这个标签进行指标数据去重。
我们可以通过Thanos Querier提供的去重功能,在Thanos querier UI界面可以勾选deduplication进行数据合并去重,不然高可用场景下会出现同个指标的多条数据。quereier会取timestamp更小的结果
--store=dnssrv+thanos-store:10901
: 配置Thanos Store 的服务发现地址,从指定对象存储中检索历史指标数据。该项配置可以在Thanos Store组件集成后在加上,也可提前配置。
--store=dnssrv+prometheus-operated:10901
: 配置Thanos Sidecar组件的服务发现地址,从sidecar 中查询实时的指标数据。如下图所示,通过服务发现获取Sidecar信息
注意: 通过--store
参数指定 storeAPI的方式在后面的版本会被废弃。建议使用endpoint
参数配置storeAPI地址:--endpoint=dnssrv+_grpc._tcp.thanos-store:10901``--endpoint=dnssrv+_grpc._tcp.prometheus-operated:10901
4.4 Thanos Store集成
-
部署yaml文件如下
Store组件需要以StatefulSet形式部署# thanos-store.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: thanos-store namespace: monitoring labels: app: thanos-store spec: replicas: 2 selector: matchLabels: app: thanos-store serviceName: thanos-store template: metadata: labels: app: thanos-store spec: containers: - name: thanos image: thanosio/thanos:v0.32.0 args: - 'store' - '--log.level=debug' - '--data-dir=/data' - '--objstore.config-file=/etc/secret/thanos.yaml' - '--index-cache-size=500MB' - '--chunk-pool-size=500MB' ports: - name: http containerPort: 10902 - name: grpc containerPort: 10901 livenessProbe: httpGet: port: 10902 path: /-/healthy readinessProbe: httpGet: port: 10902 path: /-/ready volumeMounts: - name: object-storage-config mountPath: /etc/secret readOnly: false - mountPath: /data name: thanos-store-db volumes: - name: object-storage-config secret: secretName: thanos-obs volumeClaimTemplates: - metadata: name: thanos-store-db namespace: monitoring labels: failure-domain.beta.kubernetes.io/region: cn-north-4 # failure-domain.beta.kubernetes.io/zone: cn-north-4a annotations: everest.io/disk-volume-type: GPSSD spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: csi-disk-topology --- apiVersion: v1 kind: Service metadata: name: thanos-store namespace: monitoring spec: type: ClusterIP clusterIP: None ports: - name: grpc port: 10901 targetPort: grpc selector: app: thanos-store
-
启动参数分析
--data-dir=/var/thanos/store
设置缓存数据的本地目录
--objstore.config-file=/etc/secret/thanos.yaml
Thanos Store组件需要访问对象存储获取指标数据,然后暴露StoreAPI提供数据给Querier组件。所以需要将对象存储的密钥信息告知Store组件
--index-cache-size=500MB
设置最大索引缓存数据大小
--chunk-pool-size=500MB
后续使用中可根据需要定制化配置启动参数:https://github.com/thanos-io/thanos/blob/main/docs/components/store.md -
调优配置
Store组件可以通过配置本地磁盘对 obs中的指标数据做索引加快查询速度。这些数据并不重要,可以进行删除,删除后会自动去对象存储中拉取存储数据重新建立索引。所以为了避免每次重启容器都重新建立索引,可以采用StatefulSet形式部署Thanos store组件,然后挂载一个小容量的pv即可 -
部署完成后可前往Thanos Querier的UI界面查看Store信息
4.5 Thanos Compactor集成
-
部署yaml文件如下
# thanos-compactor.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: thanos-compactor namespace: monitoring labels: app: thanos-compactor spec: replicas: 1 selector: matchLabels: app: thanos-compactor serviceName: thanos-compactor template: metadata: labels: app: thanos-compactor spec: containers: - name: thanos image: thanosio/thanos:v0.30.2 args: - 'compact' - '--log.level=debug' - '--data-dir=/var/thanos/compact' - '--objstore.config-file=/etc/secret/thanos.yaml' - '--wait' ports: - name: http containerPort: 10902 livenessProbe: httpGet: port: 10902 path: /-/healthy initialDelaySeconds: 10 readinessProbe: httpGet: port: 10902 path: /-/ready initialDelaySeconds: 15 volumeMounts: - name: object-storage-config mountPath: /etc/secret readOnly: false - name: thanos-compactor-db mountPath: /var/thanos/compact volumes: - name: object-storage-config secret: secretName: thanos-obs volumeClaimTemplates: - metadata: name: thanos-compactor-db namespace: monitoring labels: failure-domain.beta.kubernetes.io/region: cn-north-4 annotations: everest.io/disk-volume-type: GPSSD spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: csi-disk-topology --- apiVersion: v1 kind: Service metadata: name: thanos-compactor namespace: monitoring labels: app: thanos-compactor spec: ports: - port: 10902 targetPort: http name: http selector: app: thanos-compactor type: NodePort
-
Compactor 必须作为单例运行,并且在手动修改存储桶中的数据时不得运行。并非所有对象存储都实现安全锁定机制,因此需要确保只有一个 Compactor实例针对单个存储桶上的单个block进行压缩处理。运行多个 Compactor 可能会导致数据重叠问题。
-
Compactor需要本地磁盘来存储处理的数据和缓存信息。建议提供100-300GB的本地磁盘空间用于数据处理,具体取决于Block的大小。磁盘数据可以被安全删除,但是建议提供对 Compactor配置 持久化存储,以便在重新启动时有效加载使用存储桶状态缓存。
-
存储的数据如果不特别设置,数据将被永远保留。可通过启动参数
--retention.resolution-raw
--retention.resolution-5m --retention.resolution-1h
进行配置,即原始数据保留时间,降采样5分钟的数据保留时间,降采样1h的数据保留时间,单位默认是天数 day。
所有--retention.resolution-raw
精度下的样本数据,如果存储时间超过40h,将会被降采样成--retention.resolution-5m
精度下的block
所有--retention.resolution-5m
精度下的样本数据,如果存储时间超过10days,将会被降采样成--retention.resolution-1h
精度下的block
所以: 降采样的目标就不是为了节省磁盘或者对象存储的空间。事实上,降采样不会节省任何存储空间,相反还会为每个原始的block额外增加两个block,这些block只比原始block稍小或者基本相等。这意味着降采样后,存储空间需要原来的3倍。降采样的会加速大范围时间间隔(年/月)的查询速度。关于三个分辨率下的数据存储时间问题,如果你需要放大查询一年前某一天的数据,就需要将原始数据设置的和1h/5m存储时长一样。所以理想情况下,这三种分辨率下的存储设置为相同的保留时长,或者不设置(默认永久保留)。这样的好处就是拥有放大能力,而且可提高大范围查询速度。毕竟对象存储十分便宜。存储大小没有那么重要。 -
block删除设置: 为了实现compactor和所有对象存储使用者之间的协调而不存在竞争,不会直接删除存储块block。会通过block块上传delete-mark.json 文件来标记要删除的块。
注意 这个文件包含了存储块block被标记为删除的unix时间戳,并非指指定删除的时间。
可以使用启动参数--delete-delay=48h
来指定存储块被标记为删除后,需要等待多久才会从桶中删除。(默认是48h),如果设置为0,存储块会直接被删除。但这样做会操成查询异常: 如果store中存在该加载的block,或者compactor由于正在压缩该block,忽略了这个删除配置。 -
登录Compactor前端UI,查看压缩和降采样信息
五、备注/Q&A
- Thanos分为若干个组件,其实从部署文件中可以看出来。都是基于同一镜像的不同启动命令进行功能区分的。
- 如果业务不需要对接对象存储,只要求Prometheus高可用的话。可以只集成Thanos sidecar组件和Thanos Querier组件
- 点赞
- 收藏
- 关注作者
评论(0)