基于Thanos sidecar模式扩展Prometheus

举报
可以交个朋友 发表于 2023/12/29 16:13:43 2023/12/29
【摘要】 在这种监控方案局限的背景下,Thanos监控技术栈诞生了。Thanos的出现不是为了取代Prometheus,是为了我们更好的使用Prometheus。

一、 Prometheus使用现状

Prometheus上了生产环境不足的地方:

  1. 缺乏全局视图,无法管理多个Prometheus。即便使用联邦机制,GlobalPrometheus也会遇到大数据量瓶颈。
  2. 缺乏历史数据的长期存储方案,必需依赖第三方存储,缺少针对历史数据的降采样。
  3. 单实例,不可扩展。即便手动扩展多实例后,缺乏去重机制,无法满足数据一致性。Prometheus只聚焦核心的功能,扩展性的功能留给社区解决。

在这种监控方案局限的背景下,Thanos监控技术栈诞生了。Thanos的出现不是为了取代Prometheus,是为了我们更好的使用Prometheus。


二、 Thanos使用背景

image.png

为什么选择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模式架构

image.png


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 、、、

image.png

image.png


4.1 创建对象存储

Thanos 使用对象存储作为指标和元数据的主要存储。sidecar,compactor,store都涉及对象存储的配置。

  1. 前往OBS云服务创建存储介质
    Prometheus采集的历史指标数据都会存放在对象存储里
    image.png

  2. 构建对象存储配置文件

    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
    
  3. 根据以上配置文件创建k8s secret
    kubectl create secret generic thanos-obs --from-file=thanos.yaml=thanos-storage-obs.yaml -n monitoring
    创建完成。
    image.png


4.2 Thanos Sidecar集成

  1. 修改Prometheus CRD
    Thanos Sidecar容器需要伴随Prometheus容器一同部署,所以需要修改Prometheus的部署配置:
    kubectl get prometheus -n monitoring,查看集群中的Prometheus设置:
    image.png
    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
    
  2. 修改重点说明,如何注入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中获取元数据。

  3. 修改重点说明,本地数据持久化
    开源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。

  4. 注入Thanos sidecar配置后,观察容器启动参数变化
    Prometheus容器启动参数会添加:--storage.tsdb.max-block-duration=2h
    --storage.tsdb.min-block-duration=2h 这两个参数相等会保证Prometheus关闭本地压缩,如果不关闭本地压缩,Thanos sidcar无法上传Block块至对象存储中。
    image.png
    thanos-sidecar容器参数会添加Prometheus访问地址、对象存储的访问信息、以及本地数据的存储路径
    image.png

  5. Thanos sidecar部署后,可通过查看sidecar容器日志验证是否接入成功
    image.png
    Thanos sidecar集成后,如果需要验证block上传情况,最少需要等待2h,第一次upload block时间略长。完成upload后,可前往对象存储查看上传数据
    image.png

  6. Thaons sidecar每隔30s读取一次本地元数据,查看是否有新的监控数据落盘,如果有则读取本地数据块并将其上传到对象存储。标记最新的读取时间,并通过本地json文件保存已经上传的块,避免重复上传。可以通过查看容器中的thanos.shipper.json文件查看上传信息
    image.png


4.3 Thanos Querier集成

Prometheus是有状态的,存储的数据相互独立。这意味着,通过运行多个 Prometheus 副本来提高高可用性并不容易。例如,在某个副本实例崩溃后,后面恢复正常,但查询该副本数据时,会发现在其宕机期间出现了一个数据小缺口。第二个副本可能是正常的,但也有可能在其他时间段(如滚动重启)宕机,因此在这些副本上实现负载平衡的效果并不好。
但是Thanos Querier组件在查询层可以帮助我们从收集的指标中进行重复数据删除从而实现Prometheus 高可用。


  1. 部署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选择对外暴露访问端点
    image.png
    image.png

  2. Querier关键启动参数解读
    - --query.replica-label=prometheus_replica: prometheus-operator中replicaExternalLabelName默认为:prometheus_replica, 当prometheus对接远程存储时会在指标中加上该标签。Querier根据这个标签进行指标数据去重。
    image.png
    我们可以通过Thanos Querier提供的去重功能,在Thanos querier UI界面可以勾选deduplication进行数据合并去重,不然高可用场景下会出现同个指标的多条数据。quereier会取timestamp更小的结果
    image.png
    --store=dnssrv+thanos-store:10901 : 配置Thanos Store 的服务发现地址,从指定对象存储中检索历史指标数据。该项配置可以在Thanos Store组件集成后在加上,也可提前配置。
    --store=dnssrv+prometheus-operated:10901 : 配置Thanos Sidecar组件的服务发现地址,从sidecar 中查询实时的指标数据。如下图所示,通过服务发现获取Sidecar信息
    image.png
    注意: 通过--store参数指定 storeAPI的方式在后面的版本会被废弃。建议使用endpoint参数配置storeAPI地址:--endpoint=dnssrv+_grpc._tcp.thanos-store:10901``--endpoint=dnssrv+_grpc._tcp.prometheus-operated:10901


4.4 Thanos Store集成

  1. 部署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
    

  1. 启动参数分析
    --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

  2. 调优配置
    Store组件可以通过配置本地磁盘对 obs中的指标数据做索引加快查询速度。这些数据并不重要,可以进行删除,删除后会自动去对象存储中拉取存储数据重新建立索引。所以为了避免每次重启容器都重新建立索引,可以采用StatefulSet形式部署Thanos store组件,然后挂载一个小容量的pv即可

  3. 部署完成后可前往Thanos Querier的UI界面查看Store信息
    image.png


4.5 Thanos Compactor集成

  1. 部署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
    
  2. Compactor 必须作为单例运行,并且在手动修改存储桶中的数据时不得运行。并非所有对象存储都实现安全锁定机制,因此需要确保只有一个 Compactor实例针对单个存储桶上的单个block进行压缩处理。运行多个 Compactor 可能会导致数据重叠问题。

  3. Compactor需要本地磁盘来存储处理的数据和缓存信息。建议提供100-300GB的本地磁盘空间用于数据处理,具体取决于Block的大小。磁盘数据可以被安全删除,但是建议提供对 Compactor配置 持久化存储,以便在重新启动时有效加载使用存储桶状态缓存。

  4. 存储的数据如果不特别设置,数据将被永远保留。可通过启动参数 --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存储时长一样。所以理想情况下,这三种分辨率下的存储设置为相同的保留时长,或者不设置(默认永久保留)。这样的好处就是拥有放大能力,而且可提高大范围查询速度。毕竟对象存储十分便宜。存储大小没有那么重要。

  5. block删除设置: 为了实现compactor和所有对象存储使用者之间的协调而不存在竞争,不会直接删除存储块block。会通过block块上传delete-mark.json 文件来标记要删除的块。
    注意 这个文件包含了存储块block被标记为删除的unix时间戳,并非指指定删除的时间。
    可以使用启动参数 --delete-delay=48h来指定存储块被标记为删除后,需要等待多久才会从桶中删除。(默认是48h),如果设置为0,存储块会直接被删除。但这样做会操成查询异常: 如果store中存在该加载的block,或者compactor由于正在压缩该block,忽略了这个删除配置。

  6. 登录Compactor前端UI,查看压缩和降采样信息
    image.png
    image.png


五、备注/Q&A

  1. Thanos分为若干个组件,其实从部署文件中可以看出来。都是基于同一镜像的不同启动命令进行功能区分的。
  2. 如果业务不需要对接对象存储,只要求Prometheus高可用的话。可以只集成Thanos sidecar组件和Thanos Querier组件
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。