最近工作中的主要任务都是在业务的高可用上,由于项目中使用到了Promethues,所以也花了一些时间研究了一下Promethues的高可用方案。发现也没有blog告诉怎么去deploy一个Thanos的集群,所以本文也会给出deploy的方法和源文件(本人也是一边试用一边总结,如果理解有错,请帮忙矫正)
由于Promethues本身仅是一个采样系统,如果做成master-slave模式,存在切换开销,并且增加系统的复杂性。因此官方给出的高可用建议方案如下图,使用多个对等的Promethues,对所有的DataSource均进行采样。这里的Service是K8S的Service,所以理论上访问该Service会随机地访问后端的两个Promethues。
上面方案中,当其中一个Promethues pod中断时,K8S会将流量仅导向另外一个pod。但是pod中断期间,其无法获取数据,因此当中断的pod恢复之后,在存储端,需要进行sync。可是,何时sync,怎么sync是一个比较复杂的问题,就算能解决这两个问题,实际生产环境中进行文件sync,本身也会存在各式各样的风险。
所以Thanos就没有使用存储端Sync的方法来保证数据的一致性,而是采用才query端对查询到的数据进行合并。下面会简单介绍一下Thanos的原理。
1. Thanos基本原理
基于官方的介绍,我将Thanos的架构简化,仅保存最基本的,我所关心的部分如下, 主要包含3部分:
- Thanos Query. 主要是对从Promethues Pod采集来的数据进行merge,提供查询接口给客户端(官方文档上暂时没看到merge的原理,这篇总结之后需要花些时间看源码学习一下);
- Thanos SideCar. 将Promethues container的数据进行封装,以提供接口给Thanos Query(实际上SideCar还能提供更多用处,但是这里暂时我们仅关心数据查询,后面再进一步研究,暂时不要图多);
- Prometheus Container. 采集数据,通过Remote Read API提供接口给Thanos SideCar。
2. Thanos部署
学习一样新工具,部署和使用是必不可少的,暂时我也没看到网上有现成的thanos部署方法。通过修改官网的demo文件,这里我成功的部署了sidecar和query, 能够实现一个最basic的Promethues高可用集群。你可以直接下载我的源文件部署一个thanos的实验环境。
2.1 Prometheus和SideCar
由于涉及的yaml文件比较多,这里我只是截取最重要的部分解释一下, 首先我们创建一个replicas为2的statefulset, 每个pod里面包含一个Promethues和SideCar容器。
---
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,30901
和30902
就是之前部署的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-0
和prometheus-1
的数据。
如果勾上
deduplication
,结果会根据replica
这个label进行合并(简单看了一下源码,如果两个pod都有数据,query会取timestamp更小的结果):
小结
这篇blog简单介绍了thanos,学习的顺序应当是先使用,感受一下,再仔细研究。Thanos另外还有Rule
, Compact
, Bucket
几个重要的模块,后面有时间会再整理一下。