Prometheus高可用Thanos学习(1)-sidercar和query

最近工作中的主要任务都是在业务的高可用上,由于项目中使用到了Promethues,所以也花了一些时间研究了一下Promethues的高可用方案。发现也没有blog告诉怎么去deploy一个Thanos的集群,所以本文也会给出deploy的方法和源文件(本人也是一边试用一边总结,如果理解有错,请帮忙矫正)

由于Promethues本身仅是一个采样系统,如果做成master-slave模式,存在切换开销,并且增加系统的复杂性。因此官方给出的高可用建议方案如下图,使用多个对等的Promethues,对所有的DataSource均进行采样。这里的Service是K8S的Service,所以理论上访问该Service会随机地访问后端的两个Promethues。

Prometheus高可用Thanos学习(1)-sidercar和query_第1张图片
Prometheus HA

上面方案中,当其中一个Promethues pod中断时,K8S会将流量仅导向另外一个pod。但是pod中断期间,其无法获取数据,因此当中断的pod恢复之后,在存储端,需要进行sync。可是,何时sync,怎么sync是一个比较复杂的问题,就算能解决这两个问题,实际生产环境中进行文件sync,本身也会存在各式各样的风险。

所以Thanos就没有使用存储端Sync的方法来保证数据的一致性,而是采用才query端对查询到的数据进行合并。下面会简单介绍一下Thanos的原理。

1. Thanos基本原理

基于官方的介绍,我将Thanos的架构简化,仅保存最基本的,我所关心的部分如下, 主要包含3部分:

  1. Thanos Query. 主要是对从Promethues Pod采集来的数据进行merge,提供查询接口给客户端(官方文档上暂时没看到merge的原理,这篇总结之后需要花些时间看源码学习一下);
  2. Thanos SideCar. 将Promethues container的数据进行封装,以提供接口给Thanos Query(实际上SideCar还能提供更多用处,但是这里暂时我们仅关心数据查询,后面再进一步研究,暂时不要图多);
  3. Prometheus Container. 采集数据,通过Remote Read API提供接口给Thanos SideCar
Prometheus高可用Thanos学习(1)-sidercar和query_第2张图片
Thanos.png

2. Thanos部署

学习一样新工具,部署和使用是必不可少的,暂时我也没看到网上有现成的thanos部署方法。通过修改官网的demo文件,这里我成功的部署了sidecar和query, 能够实现一个最basic的Promethues高可用集群。你可以直接下载我的源文件部署一个thanos的实验环境。

2.1 Prometheus和SideCar

由于涉及的yaml文件比较多,这里我只是截取最重要的部分解释一下, 首先我们创建一个replicas为2的statefulset, 每个pod里面包含一个PromethuesSideCar容器。

---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: prometheus
  labels:
    app: prometheus
spec:
  serviceName: "prometheus"
  replicas: 2
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
        # We will use this label to put all StoreAPis
        # under the same headless service for
        # SRV lookup: thanos-store-api.default.svc
        thanos-store-api: "true"
    spec:
      securityContext:
        runAsUser: 1000
        fsGroup: 2000
        runAsNonRoot: true
      serviceAccountName: prometheus
      containers:
      - name: prometheus
        image: quay.io/prometheus/prometheus:v2.6.1
        args:
          - --config.file=/etc/prometheus-shared/prometheus.yaml
          - --storage.tsdb.path=/var/prometheus
          - --web.enable-lifecycle
          # TODO: Make retention shorter once all old blocks will be uploaded (!)
          - --storage.tsdb.retention=2w
          # Disable compaction.
          - --storage.tsdb.min-block-duration=2h
          - --storage.tsdb.max-block-duration=2h
          - --web.enable-admin-api
        ports:
          - name: http-prometheus
            containerPort: 9090
        volumeMounts:
          - name: config-shared
            mountPath: /etc/prometheus-shared
          - name: rules
            mountPath: /etc/prometheus/rules
          - name: prometheus
            mountPath: /var/prometheus
      - name: thanos
        image: improbable/thanos:v0.3.0
        args:
          - sidecar
          - --log.level=debug
          - --tsdb.path=/var/prometheus
          - --prometheus.url=http://localhost:9090
          - --cluster.disable
          - --reloader.config-file=/etc/prometheus/prometheus.yaml.tmpl
          - --reloader.config-envsubst-file=/etc/prometheus-shared/prometheus.yaml
        env:
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
        ports:
          - name: http-sidecar
            containerPort: 10902
          - name: grpc
            containerPort: 10901

上面可以看到SideCar使用的是10901这个port暴露服务,因此为了让Query能够访问SideCar, 这里我们需要暴露两个Service:

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: prometheus
  name: sidecar-0
spec:
  ports:
    - port: 10901
      protocol: TCP
      targetPort: grpc
      name: grpc
      nodePort: 30901
  selector:
    statefulset.kubernetes.io/pod-name: prometheus-0
  type: NodePort
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: prometheus
  name: sidecar-1
spec:
  ports:
    - port: 10901
      protocol: TCP
      targetPort: grpc
      name: grpc
      nodePort: 30902
  selector:
    statefulset.kubernetes.io/pod-name: prometheus-1
  type: NodePort

2.2 Query

有了Prometheus的pod,现在我们就可以部署Query的Pod啦, 这里的192.168.56.101是我的实验环境的IP,所以需要您改成自己的IP,3090130902就是之前部署的SideCar的Service:

      containers:
      - name: thanos
        image: improbable/thanos:v0.3.0
        args:
        - query
        - --log.level=debug
        - --query.replica-label=replica
        - --cluster.disable
        # Discover local store APIs using DNS SRV.
        - --store=dnssrv+thanos-store-gateway.default.svc
        # Get remote store APIs by IP:Port.
        - --store=192.168.56.101:30901
        - --store=192.168.56.101:30902

部署完毕之后,我们就可以去访问Query的Service啦,这里我创建的是一个30903的nodePort用来暴露服务, 所以访问该端口192.168.56.101:30903就能看到Thanos的界面啦。这里,我没有勾上deduplication,所以thanos不会帮我合并,所以能够看到prometheus-0prometheus-1的数据。

Prometheus高可用Thanos学习(1)-sidercar和query_第3张图片
nomerge.png

如果勾上 deduplication,结果会根据 replica这个label进行合并(简单看了一下源码,如果两个pod都有数据,query会取timestamp更小的结果):

Prometheus高可用Thanos学习(1)-sidercar和query_第4张图片
merge.png

小结

这篇blog简单介绍了thanos,学习的顺序应当是先使用,感受一下,再仔细研究。Thanos另外还有Rule, Compact, Bucket几个重要的模块,后面有时间会再整理一下。

你可能感兴趣的:(Prometheus高可用Thanos学习(1)-sidercar和query)