Kubernetes 集羣和應用監控方案的設計與實踐 (轉)

原文鏈接

 

 

 

Kubernetes 監控

當你的應用部署到 Kubenetes 後,你很難看到容器內部發生了什麼,一旦容器死掉,裏面的數據可能就永遠無法恢復,甚至無法查看日誌以定位問題所在,何況一個應用可能存在很多個實例,用戶的一個請求不指定被哪個容器處理了,這使得在 Kubernetes 中對應用進行故障排除較爲複雜。在應用之外,由於 Kubernetes 作爲基礎設施,掌管這整個集羣的生死,Kubernetes 的任何故障,必定影響到應用服務的運行,因此監控 Kubernetes 運行狀況也至關重要。

當你的應用上了雲原生,那你就不得不關注各個服務器的運行狀態,基礎設施和中間件的運行狀態,Kubernetes 中每個組件和資源對象的運行狀態,每個應用的運行狀態。當然,這個運行狀態是一個模糊的概念,取決於我們的關注點,每個被監控的對象要表達的 "運行狀態" 是不一樣的。爲了可以監控我們關注的對象,對象需要做出一些配合,提供合適的運行狀態的表達信息,以供我們收集和分析,這可以稱爲可觀測性。

在雲原生中,一般對可觀測性分爲三大作用域:

你可以在 Kubernetes 文檔中瞭解如何監控、調試,以及瞭解如何對日誌進行處理:

https://v1-20.docs.kubernetes.io/docs/tasks/debug-application-cluster/

在本文中,所提到的監控,只包括 Metrics 。

Metrics、Tracing、Logging 不是完全獨立的,在上圖中,Metrics 也會可能包含 Logging 和 Tracing 的信息。

監控對象

要採集的監控數據,來源於被監控對象,而在 Kubernetes 集羣中,我們可以將要監控的對象分爲三大部分:

  • 機器:集羣中的所有節點機器,指標有 CPU 內存使用率、網絡和硬盤 IO 速率等;
  • Kubernetes 對象狀態:Deployments, Pods, Daemonsets, Statefulset 等對象的狀態和某些指標信息;
  • 應用:Pod 中每個容器的狀態或指標,以及容器本身可能提供的 /metrics 端點。

Prometheus

在基礎環境中,一個完整的監控應包括採集數據、存儲數據、分析存儲數據、展示數據、告警等多個部分,而每個部分都有相關的工具或技術解決雲原生中環境的多樣需求和複雜性問題。

既然要做監控,那麼就需要監控工具。監控工具可以獲取所有重要的指標和日誌(Metrics也可以包含一些日誌),並將它們存儲在一個安全、集中的位置,以便可以隨時訪問它們來制定方案解決問題。由於在雲原生中,應用在 Kubernetes 集羣中部署,因此,監控 Kubernetes 可以讓你深入瞭解集羣的運行狀況和性能指標、資源計數以及集羣內部情況的頂級概覽。發生錯誤時,監控工具會提醒你(告警功能),以便你快速推出修復程序。

Prometheus 是一個 CNCF 項目,可以原生監控 Kubernetes、節點和 Prometheus 本身,目前 Kubernetes 官方文檔主要推薦使用 Prometheus 本身,它爲 Kubernetes 容器編排平臺提供開箱即用的監控能力。因此在本文中,對監控方案的設計是圍繞 Prometheus 展開的。

下面是 Prometheus 的一些組件介紹:

  1. Metric Collection: Prometheus 使用拉模型通過 HTTP 檢索度量。在 Prometheus 無法獲取指標的情況下,可以選擇利用 Pushgateway 將指標推給 Prometheus 。
  2. Metric Endpoint: 希望使用 Prometheus 監視的系統應該公開某個/度量端點的度量, Prometheus 利用這個端點以固定的間隔提取指標。
  3. PromQL: Prometheus 附帶了 PromQL,這是一種非常靈活的查詢語言,可用於查詢 Prometheus 儀表板中的指標。此外,Prometheus UI 和 Grafana 將使用 PromQL 查詢來可視化指標。
  4. Prometheus Exporters: 有許多庫和服務器可以幫助將第三方系統中的現有指標導出爲 Prometheus 指標。這對於無法直接使用 Prometheus 指標檢測給定系統的情況。
  5. TSDB (time-series database): Prometheus 使用 TSDB 高效地存儲所有數據。默認情況下,所有數據都存儲在本地。然而,爲了避免單點故障,prometheustsdb 可以選擇集成遠程存儲。

Prometheus 在 Kubernetes 中的監控方案結構如下:

img

【圖源:https://devopscube.com/setup-prometheus-monitoring-on-kubernetes/】

指標

要監控的對象種類很多,我們把相同類型的對象稱爲一個實體,而每個實體運行時的對象產生的數據有各種各樣的,爲了歸納收集這些數據, Prometheus 將實體中的各種屬性值分爲 Counter (計數器)、Gauge (儀表盤)、Histogram(累積直方圖)、Summary(摘要)四種類型,實體中的每個屬性,稱爲指標,例如 容器已累計使用 CPU 量,使用指標名稱 container_cpu_usage_seconds_total 記錄。

每個指標一般格式爲:

指標名稱{元數據=值} 指標值

每個對象都在無時無刻產生數據,爲了區分當前指標值屬於哪個對象,可以給指標除了指標值外,附加大量的元數據信息,示例如下表示。

container_cpu_usage_seconds_total{
	beta_kubernetes_io_arch = "amd64",
	  beta_kubernetes_io_os = "linux", 
	  container = "POD", 
	  cpu = "total", 
	  id = "...", 
	  image = "k8s.gcr.io/pause:3.5", 
	  instance = "slave1", 
	  job = "kubernetes-cadvisor", 
	  kubernetes_io_arch = "amd64", 
	  kubernetes_io_hostname = "slave1",
	  kubernetes_io_os = "linux", 
	  name = "k8s_POD_pvcpod_default_02ed547b-6279-4346-8918-551b87877e91_0", 
	  namespace = "default", 
	  pod = "pvcpod"
}

對象生成類似這種結構的文本後,可以暴露 metrics 端點,讓 Prometheus 自動採集,或通過 Pushgateway 推送到 Prometheus 中。

接下來,我們將在 Kubernetes 中搭建一個完整的 Prometheus 監控體系。

實踐

節點監控

本章參考資料:https://devopscube.com/node-exporter-kubernetes/

node exporter 是用 Golang 編寫的,用於在 Linux 系統上,收集內核公開的所有硬件和操作系統級別的指標,包括 CPU 、信息、網卡流量、系統負載、socket 、機器配置等。

讀者可參考中列舉出的 https://github.com/prometheus/node_exporter 中列舉出的所有默認開啓或默認關閉的指標。

既然要監控集羣中的每個節點,那麼就要做到每個節點都運行這一個 node exporter 實例,並且在集羣新增節點的時候自動調度一個 node exporter 到這個節點中運行,因此需要採用 node exporter 的部署需要 DaemontSet 模式。

查看集羣中的所有節點:

root@master:~# kubectl get nodes
NAME     STATUS                     ROLES                  AGE     VERSION
master   Ready,SchedulingDisabled   control-plane,master   98d     v1.22.2
salve2   Ready                      <none>                 3h50m   v1.23.3
slave1   Ready                      <none>                 98d     v1.22.2

Bibin Wilson 大佬已經封裝好了用於 Kubernetes 的 node exporter 的 YAML 文件,我們直接下載即可:

git clone https://github.com/bibinwilson/kubernetes-node-exporter

打開倉庫中的 daemonset.yaml 文件,大概瞭解其中的信息。

在 YAML 文件中,可以看到 node exporter 會被部署到命名空間 monitoring 中運行,它有兩個 label:

   labels:
     app.kubernetes.io/component: exporter
     app.kubernetes.io/name: node-exporter

爲了 node exporter 能夠被調度到 master 節點中運行,我們需要爲 Pod 添加容忍度屬性:

  template:
    metadata:
      labels:
        app.kubernetes.io/component: exporter
        app.kubernetes.io/name: node-exporter
    spec:
    # 複製下面這部分到對應的位置
      tolerations:
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"
      - key: "node.kubernetes.io/unschedulable"
        operator: "Exists"
        effect: "NoSchedule"

爲了部署 node exporter ,我們先創建命名空間:

kubectl create namespace monitoring

執行命令部署 node exporter:

kubectl create -f daemonset.yaml

查看 node exporter 實例

root@master:~# kubectl get daemonset -n monitoring
NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
node-exporter   3         3         3       3            3           <none>          22h

由於 node exporter Pod 分散在各個節點,爲了便於 Prometheus 收集這些 node exporter 的 Pod IP,需要創建 Endpoint 統一收集,這裏通過創建 Service 自動生成 Endpoint 來達到目的。

查看倉庫下的 service.yaml 文件,其定義如下:

kind: Service
apiVersion: v1
metadata:
  name: node-exporter
  namespace: monitoring
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/port:   '9100'
spec:
  selector:
      app.kubernetes.io/component: exporter
      app.kubernetes.io/name: node-exporter
  ports:
  - name: node-exporter
    protocol: TCP
    port: 9100
    targetPort: 9100

此 Service 的選擇器如下:

selector:
   app.kubernetes.io/component: exporter
   app.kubernetes.io/name: node-exporter

創建 Service:

kubectl create -f service.yaml

查看 Endpoint 收集的 node exporter 的 Pod IP:

root@master:~# kubectl get endpoints -n monitoring 
NAME                    ENDPOINTS                                       AGE
node-exporter           10.32.0.27:9100,10.36.0.4:9100,10.44.0.3:9100   22h

node exporter 除了收集各種指標數據外,不會再幹什麼。

部署 Prometheus

本節參考https://devopscube.com/setup-prometheus-monitoring-on-kubernetes/

現在有了 node exporter ,可以收集節點各類指標,接下來便是對 Kubernetes 基礎設施的 metrics 數據收集。

Kubernetes 自身提供的很多 metrics 數據,有三大端點 /metrics/cadvisor, /metrics/resource and /metrics/probes

/metrics/cadvisor 爲例,cAdvisor 分析在給定節點上運行的所有容器的內存、CPU、文件和網絡使用情況的指標,你可以參考 https://github.com/google/cadvisor/blob/master/docs/storage/prometheus.md 瞭解 cAdvisor 的所有指標。

其它資料:

源碼位置:https://github.com/kubernetes/metrics/blob/master/pkg/apis/metrics/v1beta1/types.go

Kubernetes 監控架構設計:https://github.com/kubernetes/design-proposals-archive

在本節中,部署的 Prometheus 將會對 kubenetes 進行以下動作以便收集 metrics 數據:

  1. Kubernetes-apiservers: 從 API 服務器獲得所有的指標;
  2. Kubernetes 節點: 它收集所有的 kubernetes 節點指標;
  3. kubernetes-pods: pod 元數據上加上 prometheus.io/scrape 和 prometheus.io/port 註釋,所有的 pod 指標都會被發現;
  4. kubernetes-cadvisor: 收集所有 cAdvisor 指標,與容器相關;
  5. Kubernetes-Service-endpoints: 如果服務元數據使用 prometheus.io/scrape 註釋和 prometheus.io/port 註釋,那麼所有的服務端點都將被廢棄;

Bibin Wilson 大佬已經封裝好了相關的部署定義文件,我們直接下載即可:

git clone https://github.com/bibinwilson/kubernetes-prometheus

Prometheus 通過使用 Kubernetes API Server ,獲取 各節點、Pod、Deployment 等所有可用的指標。因此,我們需要創建具有對所需 API 組的只有讀訪問權限的 RBAC 策略,並將策略綁定到監視名稱空間,以限制 Prometheus Pod 只能對 API 進行讀操作。

查看 clusterRole.yaml 文件,可以其要監控的資源對象列表:

- apiGroups: [""]
  resources:
  - nodes
  - nodes/proxy
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups:
  - extensions
  resources:
  - ingresses

在集羣中創建角色和角色綁定:

kubectl create -f clusterRole.yaml

可以通過 通過命令行標誌和配置文件 對 Prometheus 進行配置。雖然命令行標誌配置了不可變的系統參數(例如存儲位置、要保存在磁盤和內存中的數據量等),但配置文件定義了與抓取作業及其實例相關的所有內容,以及加載哪些規則文件,因此部署 Permetheus 少不了做文件配置。

Permetheus 的配置文件以 YAML 格式編寫,具體規則可以參考:https://prometheus.io/docs/prometheus/latest/configuration/configuration/

爲了便於將配置文件映射到 Permetheus Pod 中,我們需要將配置放到 configmap ,然後掛載到 Pod,配置內容可以查看 config-map.yaml 。config-map.yaml 中定義了很多采集數據源的規則,例如收集 Kubernetes 集羣和 node exporter ,配置可參考:

    scrape_configs:
      - job_name: 'node-exporter'
        kubernetes_sd_configs:
          - role: endpoints
        relabel_configs:
        - source_labels: [__meta_kubernetes_endpoints_name]
          regex: 'node-exporter'
          action: keep

你可以打開 https://raw.githubusercontent.com/bibinwilson/kubernetes-prometheus/master/config-map.yaml 在線預覽這個文件。

創建 configmap:

kubectl create -f config-map.yaml

這個配置很重要,需要根據實際情況配置,一般由運維處理,這裏就不再討論。

接下來將要部署 Prometeus ,由於示例文件中使用 emtpy 卷存儲 Prometheus 數據,因此一旦 Pod 重啓等,數據將會丟失,因此這裏可以改成 hostpath 卷。

打開 prometheus-deployment.yaml 文件:

          emptyDir: {}

改成

          hostPath:
            path: /data/prometheus
            type: Directory  

可改可不改。

如果改的話,需要在被調度此 Pod 對應的節點上創建 /data/prometheus 目錄。

部署 Prometeus :

kubectl create  -f prometheus-deployment.yaml 

查看部署狀態:

root@master:~# kubectl get deployments --namespace=monitoring
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
prometheus-deployment   1/1     1            1           23h

爲了在外界訪問 Prometeus ,需要創建 Service:

apiVersion: v1
kind: Service
metadata:
  name: prometheus-service
  namespace: monitoring
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/port:   '9090'
  
spec:
  selector: 
    app: prometheus-server
  type: NodePort  
  ports:
    - port: 8080
      targetPort: 9090 
      nodePort: 30000
kubectl create -f prometheus-service.yaml

接下來可以訪問 Prometeus UI 面板。

點擊 Graph,點擊🌏圖標,選擇需要顯示的指標值,再點擊 Execute 查詢顯示。

image-20220210205949823

image-20220210205829297

你還可以在 Service Discobery 中,查看 Prometheus 採集的 metrics 數據源。

image-20220210210215530

image-20220210210331859

如果你的集羣沒有安裝過 kube-state-metrics,那麼這個數據源會顯示紅色標記,在下一節中,我們繼續部署這個組件。

至此,我們的監控結構如下所示:

image-20220210214630990

部署 Kube State Metrics

本節參考資料:https://devopscube.com/setup-kube-state-metrics/

Kube State metrics 是一個服務,它與 Kubernetes API Server 通信,以獲取所有 API 對象的詳細信息,如 Deployment、Pod 等。

Kube State metrics 提供了無法直接從本地 Kubernetes 監視組件獲得的 Kubernetes 對象和資源 度量,因爲 Kubenetes Metrics 本身提供的指標並不是很全面,因此需要 Kube State Metrics 以獲得與 kubernetes 對象相關的所有度量。

以下是可以從 Kube State metrics 中獲得的一些重要度量:

  1. Node status, node capacity (CPU and memory)
  2. Replica-set compliance (desired/available/unavailable/updated status of replicas per deployment)
  3. Pod status (waiting, running, ready, etc)
  4. Ingress metrics
  5. PV, PVC metrics
  6. Daemonset & Statefulset metrics.
  7. Resource requests and limits.
  8. Job & Cronjob metrics

可以在這裏的文檔中查看受支持的詳細指標:https://github.com/kubernetes/kube-state-metrics/tree/master/docs

image-20220210210642889

Bibin Wilson 大佬已經封裝好了相關的部署定義文件,我們直接下載即可:

git clone https://github.com/devopscube/kube-state-metrics-configs.git

直接應用所有 YAML 創建對應的資源:

kubectl apply -f kube-state-metrics-configs/
├── cluster-role-binding.yaml
├── cluster-role.yaml
├── deployment.yaml
├── service-account.yaml
└── service.yaml

上面創建的資源,包含以下部分,這一小節,就不展開講解。

  1. Service Account
  2. Cluster Role
  3. Cluster Role Binding
  4. Kube State Metrics Deployment
  5. Service

使用以下命令檢查部署狀態:

kubectl get deployments kube-state-metrics -n kube-system

隨後,刷新 Prometheus Service Discobery ,可以看到紅色變成了藍色,點擊此數據源,可以看到以下信息:

image-20220210211101241

- job_name: 'kube-state-metrics'
  static_configs:
    - targets: ['kube-state-metrics.kube-system.svc.cluster.local:8080']

此配置爲 kube-state-metrics 的訪問地址。

在此,我們部署的 Prometeus 結構如下:

image-20220210214807996

部署 Grafana

本節參考資料:https://devopscube.com/setup-grafana-kubernetes/

經過前面幾個小節的部署,已經搞好數據源的採集以及數據存儲,接下來我們將部署 Grafana,利用 Grafana 對指標數據進行分析以及可視化。

Bibin Wilson 大佬已經封裝好了相關的部署定義文件,我們直接下載即可:

git clone https://github.com/bibinwilson/kubernetes-grafana.git

首先查看 grafana-datasource-config.yaml 文件,此配置是爲了 Grafana 自動配置好 Prometheus 數據源。

image-20220210212258986

裏面還有一個很重要的地址:

                "url": "http://prometheus-service.monitoring.svc:8080",

這裏要確認你的 CoreDNS 是否正常,你可以參考 https://kubernetes.io/zh/docs/tasks/administer-cluster/dns-debugging-resolution/ 中列舉的 DNS 調試方法,確認你的集羣中是否可以通過 DNS 訪問 Pod。
最簡單的方法是啓動一個 Pod,然後使用命令測試 curl http://prometheus-service.monitoring.svc:8080,看看能不能獲取到響應數據,如果出現:

root@master:~/jk/kubernetes-prometheus# curl http://prometheus-deployment.monitoring.svc:8080
curl: (6) Could not resolve host: prometheus-deployment.monitoring.svc
root@master:~/jk/kubernetes-prometheus# curl http://prometheus-deployment.monitoring.svc.cluster.local:8080
curl: (6) Could not resolve host: prometheus-deployment.monitoring.svc.cluster.local

可能是你 coredns 沒有安裝或者別的原因,導致無法通過此地址訪問 Prometheus ,爲了爲了避免過多操作,可以改爲使用 IP,而不是域名。

查看 Prometheus 的 Service IP:

root@master:~/jk/kubernetes-prometheus# kubectl get svc -n monitoring
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
prometheus-deployment   NodePort    10.105.95.8     <none>        9090:32330/TCP   23h

測試通過 Service IP 訪問是否正常

root@master:~/jk/kubernetes-prometheus# curl 10.105.95.8:9090
<a href="/graph">Found</a>.

grafana-datasource-config.yaml 中的 prometheus-deployment.monitoring.svc.cluster.local:8080 改成對應的 Service IP,並且端口改成 9090。

創建配置

kubectl create -f grafana-datasource-config.yaml

打開 deployment.yaml 查看定義,模板中 grafana 的數據存儲也是使用 empty 卷,有數據丟失風險,因此可以改成用 hospath 或其他類型的卷存儲。可參考筆者的配置:

      volumes:
        - name: grafana-storage
          hostPath:
            path: /data/grafana
            type: Directory   

部署 Grafana:

kubectl create -f deployment.yaml

然後創建 Service:

kubectl create -f service.yaml

接着可以通過 32000 端口訪問 Grafana。

賬號密碼都是 admin

至此,我們部署的 Prometheus 監控結構如下:

image-20220210214953273

剛剛進去的時候空空如也,我們需要利用圖表模板製作可視化界面,才能顯示出漂亮的數據。

在 Grafana 官方網站中,有很多社區製作的免費的模板 https://grafana.com/grafana/dashboards/?search=kubernetes

首先打開 https://grafana.com/grafana/dashboards/8588 下載這個模板,然後上傳模板文件,並綁定對應的 Prometheus 數據源。

image-20220210212926323

image-20220210212952395

image-20220210213043764

接下來就可以看到對應的監控界面了。

image-20220210213221217

你可以打開 Browse ,繼續導入更多的模板,然後查看要顯示的模板監控界面。

image-20220210213337031

應用如何接入 Prometheus 和 Grafana

前面已經提及對基礎設施的監控,我們還可以對中間件如 TIDB、Mysql 等生成、收集指標數據,還可以在程序中自定義指標數據,然後自行製作 Grafana 模板。如果你是 .NET 開發,還可以參考筆者的另一篇文章來一步步瞭解這些過程:https://www.cnblogs.com/whuanle/p/14969982.html

告警

在監控體系中,告警是重中之重,一般需要根據公司的實際情況自研告警處理和推送通知組件

我們建議您閱讀 基於 Rob Ewaschuk 在 Google 的觀察的我的警報哲學https://docs.google.com/a/boxever.com/document/d/199PqyG3UsyXlwieHaqbGiWVa8eMWi8zzAn0YfcApr8Q/edit

在前面部署 Prometheus 時,config-map.yaml 便已經定義了一個告警規則。

  prometheus.rules: |-
    groups:
    - name: devopscube demo alert
      rules:
      - alert: High Pod Memory
        expr: sum(container_memory_usage_bytes) > 1
        for: 1m
        labels:
          severity: slack
        annotations:
          summary: High Memory Usage

一條告警規則主要由以下幾部分組成:

  • alert:告警規則的名稱。
  • expr:基於 PromQL 表達式告警觸發條件,用於計算是否有時間序列滿足該條件。
  • for:評估等待時間,可選參數。用於表示只有當觸發條件持續一段時間後才發送告警。在等待期間新產生告警的狀態爲 pending。
  • labels:自定義標籤,允許用戶指定要附加到告警上的一組附加標籤。
  • annotations:用於指定一組附加信息,比如用於描述告警詳細信息的文字等,annotations 的內容在告警產生時會一同作爲參數發送到 Alertmanager。

可參考:https://yunlzheng.gitbook.io/prometheus-book/parti-prometheus-ji-chu/alert/prometheus-alert-rule

image-20220212215935688

在 Grafana 中也可以看到這條規則。

image-20220212220457886

下面我們將來配置告警通知。

首先創建一個告警聯繫方式,筆者使用了釘釘 Webhook。

image-20220212221559333

image-20220212222438650

然後找 Alert Rules,添加一個新的告警規則。

image-20220212225334405

告警規則請參考:https://grafana.com/docs/grafana/latest/alerting/unified-alerting/alerting-rules/create-grafana-managed-rule/

接着打開 Notification policies,爲告警規則和聯繫方式做綁定,符合條件的告警信息將會被推送到指定的聯繫方式中。

image-20220212223912995

image-20220212225530864

在 Alert Rules 中可以看到告警信息的推送記錄。由於筆者的服務器在國外,可能導致服務器無法使用釘釘的 Webhook 功能,因此這裏一直在 Pending,因此筆者這裏就不再做過多的嘗試了,讀者瞭解大概步驟即可。

image-20220212225643237

image-20220212225835855

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章