Stories

Detail Return Return

抽絲剝繭--從零開始建設k8s監控之水平拆分(五) - Stories Detail

前言

書接上文,經過之前的不懈努力,我們已經有了較為完善的監控系統與告警系統,而prometheus的工作模式就像一個單點,拉取數據回來之後存儲在自己的磁盤上

當監控數據越來越多,那prometheus單點的壓力就會變大,那本文就來討論一下如何降低單點prometheus的壓力

環境準備

組件 版本
操作系統 Ubuntu 22.04.4 LTS
docker 24.0.7
kube-state-metrics v2.13.0
thanos 0.36.1

水平拆分

水平拆分的目的就是為了拆成多個prometheus,讓單個prometheus負載降低,不要這麼容易掛掉,並且拆成多個之後,就算掛掉一個,其餘的也可以正常工作。比如一個prometheus專門負責節點監控數據採集、一個prometheus專門負責k8s監控數據採集等

1. 根據採集的目標進行拆分

每個業務都有一個prometheus對其進行採集,並且不同prometheus之間解耦

這時候業務部門提出需求,k8s的監控還是太多了,一個prometheus依然不堪重負,那怎麼辦呢?

2. kube-state-metrics拆分

由於k8s是通過kube-state-metrics這個exporter進行採集,所以我們需要對其進行拆分

2.1 根據namespace進行拆分

這個拆分是顯而易見的,不同的namespace採集進入不同的prometheus即可,配置也很簡單,只需要修改kube-state-metrics的啓動參數即可

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kube-state-metrics
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kube-state-metrics
  template:
    metadata:
      labels:
        app: kube-state-metrics
    spec:
      serviceAccountName: kube-state-metrics
      containers:
      - args:
        - --metric-labels-allowlist=pods=[*]
        - --metric-annotations-allowlist=pods=[*]
        - --namespaces=default # 新增
        name: kube-state-metrics
        image: registry.cn-beijing.aliyuncs.com/wilsonchai/kube-state-metrics:v2.13.0
        ports:
        - containerPort: 8080

--namespaces=default 告訴kube-state-metrics只採集namespace為default的數據

創建多個prometheus以及kube-state-metrics,然後指定採集不同的namespace

這種方法配置簡單,但是分配多個kube-state-metrics的採集策略就比較複雜,一旦業務複雜,namespace多起來之後,也會造成頻繁修改配置,還有沒有更簡單的方法呢?

2.2 kube-state-metrics根據shard拆分

kube-state-metrics的高版本(具體是哪個版本待查,筆者的版本是v2.13.0),支持了自動分片的採集策略,就是讓多個kube-state-metrics自己去分片,省去人為配置的煩惱

關於水平分片的例子,可以參考 kube-state-metrics

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/version: v2.13.0
  name: kube-state-metrics
  namespace: kube-system
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - apps
  resourceNames:
  - kube-state-metrics
  resources:
  - statefulsets
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/version: v2.13.0
  name: kube-state-metrics
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kube-state-metrics
subjects:
- kind: ServiceAccount
  name: kube-state-metrics
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/version: v2.13.0
  name: kube-state-metrics
  namespace: kube-system
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: kube-state-metrics
  serviceName: kube-state-metrics
  template:
    metadata:
      labels:
        app.kubernetes.io/name: kube-state-metrics
        app.kubernetes.io/version: v2.13.0
    spec:
      containers:
      - args:
        - --pod=$(POD_NAME)
        - --pod-namespace=$(POD_NAMESPACE)
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        image: registry.cn-beijing.aliyuncs.com/wilsonchai/kube-state-metrics:v2.13.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          timeoutSeconds: 5
        name: kube-state-metrics
        ports:
        - containerPort: 8080
          name: http-metrics
        - containerPort: 8081
          name: telemetry
        readinessProbe:
          httpGet:
            path: /
            port: 8081
          initialDelaySeconds: 5
          timeoutSeconds: 5
        securityContext:
          runAsUser: 65534
      nodeSelector:
        kubernetes.io/os: linux
      serviceAccountName: kube-state-metrics

啓動起來之後檢查一下metrics的指標數量

▶ curl -s 10.244.0.107:8080/metrics | wc -l
949
▶ curl -s 10.244.0.108:8080/metrics | wc -l
909

看起來已經打散到2個節點去了,如果我再增加一個節點,那指標數量又分散了

▶ curl -s 10.244.0.107:8080/metrics | wc -l
702
▶ curl -s 10.244.0.108:8080/metrics | wc -l
733
▶ curl -s 10.244.0.109:8080/metrics | wc -l
663

這時候只需要把不同的prometheus配置採集不同kube-state-metrics即可,架構也變成了這個樣子

當然kube-state-metrics也是有手動分片模式的,就是通過參數--shard來實現了,只不過有自動分片的話,沒有極致特殊的需求,我們還是用自動分片來處理更加合適

多prometheus數據匯聚

當我們拆分了監控數據,用不同的prometheus來採集的時候,又帶來了新的問題

  • 由於prometheus使用本地磁盤存儲數據,所以通過prometheus的web界面查看監控數據時,也只能查看到本prometheus的監控數據,不能跨prometheus查詢監控數據
  • 使用grafana添加數據源的時候,就出現了多prometheus數據源的情況,造成管理複雜

  • 有一個公共的storage組件,prometheus通過remote_write的方式,把數據匯聚在這個組件,就可以解決數據分散的問題,並且數據存儲的方式就很靈活了,可以存儲在本地,然後通過傳統的raid做數據備份,也可以直接通過雲 平台的對象存儲保存歷史數據
  • 最後再來一個統一的web界面進行查詢,同時這個web界面兼容了prometheus的promQL,並且兼容了prometheus的api,可以直接作為數據源添加至grafana中
  • 有這種功能的組件就很多了,比如thanos、cortext、influxDB等等,都可以完成這個工作

小結

  • 下一小節,通過thanos來詳細討論一下怎麼做數據匯聚

聯繫我

  • 聯繫我,做深入的交流


至此,本文結束
在下才疏學淺,有撒湯漏水的,請各位不吝賜教...

user avatar huankuaideliushu Avatar goustercloud Avatar abigmiu_6623a1b3cafc9 Avatar
Favorites 3 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.