Sidecar 组件
首先将前面章节中的 Prometheus 相关的资源对象全部删除,然后我们需要在 Prometheus 中去自动发现集群的一些资源对象,所以依然需要对应的 RBAC 权限声明:(rbac.yaml)
Prometheus需要去做自动发现,所以RBAC还是不可少的。
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: kube-mon
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- apiGroups:
- ""
resources:
- nodes
- services
- endpoints
- pods
- nodes/proxy
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- nodes/metrics
verbs:
- get
- nonResourceURLs:
- /metrics
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus
subjects:
- kind: ServiceAccount
name: prometheus
namespace: kube-mon
然后需要部署 Prometheus 的配置文件,下面的资源对象是创建 Prometheus 配置文件的模板(注意这里只是一个模板),该模板将由 Thanos sidecar 组件进行读取,最终会通过该模板生成实际的配置文件,在同一个 Pod 中的 Prometheus 容器将读取最终的配置文件,在配置文件中添加 external_labels
标签是非常重要的,以便让 Queirer
可以基于这些标签对数据进行去重处理:(configmap.yaml)(和之前的Prometheus不同就是global里面的external_labels,这个可以喂集群添加一个通用的标签,这个可有可无。因为是HA,有两个Prometheus server,那么产生的指标得带上是由哪个Prometheus产生的,即replica,那么query组件在做查询的时候就会对数据进行去重)
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: kube-mon
data:
prometheus.yaml.tmpl: | # 注意这里的名称是 prometheus.yaml.tmpl
global:
scrape_interval: 15s
scrape_timeout: 15s
external_labels:
cluster: ydzs-test
replica: $(POD_NAME) # 每个 Prometheus 有一个唯一的标签
rule_files: # 报警规则文件配置
- /etc/prometheus/rules/*rules.yaml
alerting:
alert_relabel_configs: # 我们希望告警从不同的副本中也是去重的
- regex: replica
action: labeldrop
alertmanagers:
- scheme: http
path_prefix: /
static_configs:
- targets: ['alertmanager:9093']
scrape_configs:
...... # 其他抓取任务配置和前面章节中的配置保持一致即可
上面配置了报警规则文件,由于这里配置文件太大了,所以为了更加清晰,我们将报警规则文件拆分到另外的 ConfigMap 对象中来,下面我们配置了两个报警规则:(rules-configmap.yaml)
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-rules
namespace: kube-mon
data:
alert-rules.yaml: |-
groups:
- name: Deployment
rules:
- alert: Deployment at 0 Replicas
annotations:
summary: Deployment {
{$labels.deployment}} in {
{$labels.exported_namespace}} is currently having no pods running
expr: |
sum(kube_deployment_status_replicas) by (deployment,exported_namespace) < 1
for: 1m
labels:
team: node
- name: Pods
rules:
- alert: Container restarted
annotations:
summary: Container named {
{$labels.container}} in {
{$labels.pod}} in {
{$labels.exported_namespace}} was restarted
expr: |
sum(increase(kube_pod_container_status_restarts_total[1m])) by (pod,exported_namespace,container) > 0
for: 0m
labels:
team: node
Thanos 通过 Sidecar 和现有的 Prometheus 进行集成,将 Prometheus 的数据备份到对象存储中,所以首先我们需要将 Prometheus 和 Sidecar 部署在同一个 Pod 中,另外 Prometheus 中一定要开启下面两个参数:
--web.enable-admin-api
允许 Thanos 的 Sidecar 从 Prometheus 获取元数据。--web.enable-lifecycle
允许 Thanos 的 Sidecar 重新加载 Promehtues 的配置和规则文件。(如果配置文件做了相应的更改,sidecar组件会自动的重新加载配置)
由于 Prometheus 默认每2h
生成一个 TSDB 数据块,所以仍然并不意味着 Prometheus 可以是完全无状态的,因为如果它崩溃并重新启动,我们将丢失〜2 个小时的指标,因此强烈建议依然对 Prometheus 做数据持久化,所以我们这里使用了 StatefulSet
来管理这个应用,添加 volumeClaimTemplates
来声明了数据持久化的 PVC 模板:(sidecar.yaml)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: prometheus
namespace: kube-mon
labels:
app: prometheus
spec:
serviceName: "prometheus"
replicas: 2
selector:
matchLabels:
app: prometheus
thanos-store-api: "true"
template:
metadata:
labels:
app: prometheus
thanos-store-api: "true"
spec:
serviceAccountName: prometheus
volumes:
- name: prometheus-config
configMap:
name: prometheus-config
- name: prometheus-rules
configMap:
name: prometheus-rules
- name: prometheus-config-shared
emptyDir: {}
containers:
- name: prometheus
image: prom/prometheus:v2.14.0
imagePullPolicy: IfNotPresent
args:
- "--config.file=/etc/prometheus-shared/prometheus.yaml"
- "--storage.tsdb.path=/prometheus"
- "--storage.tsdb.retention.time=6h"
- "--storage.tsdb.no-lockfile"
- "--storage.tsdb.min-block-duration=2h" # Thanos处理数据压缩
- "--storage.tsdb.max-block-duration=2h"
- "--web.enable-admin-api" # 通过一些命令去管理数据
- "--web.enable-lifecycle" # 支持热更新 localhost:9090/-/reload 加载
ports:
- name: http
containerPort: 9090
resources:
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "2Gi"
cpu: "1"
volumeMounts:
- name: prometheus-config-shared
mountPath: /etc/prometheus-shared/
- name: prometheus-rules
mountPath: /etc/prometheus/rules
- name: data
mountPath: "/prometheus"
- name: thanos
image: thanosio/thanos:v0.18.0
imagePullPolicy: IfNotPresent
args:
- sidecar
- --log.level=debug
- --tsdb.path=/prometheus
- --prometheus.url=http://localhost:9090
- --reloader.config-file=/etc/prometheus/prometheus.yaml.tmpl
- --reloader.config-envsubst-file=/etc/prometheus-shared/prometheus.yaml
- --reloader.rule-dir=/etc/prometheus/rules/
ports:
- name: http-sidecar
containerPort: 10902
- name: grpc
containerPort: 10901
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
resources:
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "2Gi"
cpu: "1"
volumeMounts:
- name: prometheus-config-shared
mountPath: /etc/prometheus-shared/
- name: prometheus-config
mountPath: /etc/prometheus
- name: prometheus-rules
mountPath: /etc/prometheus/rules
- name: data
mountPath: "/prometheus"
volumeClaimTemplates: # 由于prometheus每2h生成一个TSDB数据块,所以还是需要保存本地的数据
- metadata:
name: data
labels:
app: prometheus
spec:
storageClassName: openebs-jiva-default
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
thanos-store-api: "true" 实现了store api这个接口了,这个是为了query对接pod提供数据用的。
由于 Prometheus 和 Thanos 的 Sidecar 在同一个 Pod 中了,所以我们完全可以用 localhost
就可以访问到了,然后将数据目录做了声明挂载,所以同样可以在两个容器中共享数据目录了,一定要注意几个配置文件的挂载方式。此外在上面的配置文件中我们通过 POD_NAME
这个环境变量作为 external
标签附加到了 Prometheus 实例上,这里我们通过 Downward API
去设置该环境变量。
由于现在使用的是 StatefulSet
控制器,所以需要创建一个 Headless Service,而且后面的 Thanos Query 还将使用该无头服务来查询所有 Prometheus 实例中的数据,当然我们也可以为每一个 Prometheus 实例去创建一个 Service 对象便于调试,当然这个不是必须的:(headless.yaml)
# 该服务为 querier 创建 srv 记录,以便查找 store-api 的信息
apiVersion: v1
kind: Service
metadata:
name: thanos-store-gateway
namespace: kube-mon
spec:
type: ClusterIP
clusterIP: None
ports:
- name: grpc
port: 10901
targetPort: grpc
selector:
thanos-store-api: "true"
然后我们就可以使用上面的这些资源对象来创建带有 Thanos Sidecar 容器的高可用 Prometheus 应用了:
$ kubectl apply -f rbac.yaml
$ kubectl apply -f configmap.yaml
$ kubectl apply -f rules-configmap.yaml
$ kubectl apply -f headless.yaml
$ kubectl apply -f sidecar.yaml
$ kubectl get pods -n kube-mon -l app=prometheus
NAME READY STATUS RESTARTS AGE
prometheus-0 2/2 Running 0 86s
prometheus-1 2/2 Running 0 74s