一、概述
1、Prometheus簡介
Prometheus是一個開源的服務監控系統和時序數據庫,其提供了通用的數據模型和快捷數據采集、存儲和查詢接口。它的核心組件Prometheus服務器定期從靜態配置的監控目標或者基於服務發現自動配置的目標中進行拉取數據,新拉取到啊的 數據大於配置的內存緩存區時,數據就會持久化到存儲設備當中。Prometheus組件架構圖如下:
如上圖,每個被監控的主機都可以通過專用的exporter
程序提供輸出監控數據的接口,並等待Prometheus
服務器周期性的進行數據抓取。如果存在告警規則,則抓取到數據之后會根據規則進行計算,滿足告警條件則會生成告警,並發送到Alertmanager
完成告警的匯總和分發。當被監控的目標有主動推送數據的需求時,可以以Pushgateway
組件進行接收並臨時存儲數據,然后等待Prometheus
服務器完成數據的采集。
任何被監控的目標都需要事先納入到監控系統中才能進行時序數據采集、存儲、告警和展示,監控目標可以通過配置信息以靜態形式指定,也可以讓Prometheus通過服務發現的機制進行動態管理。下面是組件的一些解析:
- 監控代理程序:如node_exporter:收集主機的指標數據,如平均負載、CPU、內存、磁盤、網絡等等多個維度的指標數據。
- kubelet(cAdvisor):收集容器指標數據,也是K8S的核心指標收集,每個容器的相關指標數據包括:CPU使用率、限額、文件系統讀寫限額、內存使用率和限額、網絡報文發送、接收、丟棄速率等等。
- API Server:收集API Server的性能指標數據,包括控制隊列的性能、請求速率和延遲時長等等
- etcd:收集etcd存儲集群的相關指標數據
- kube-state-metrics:該組件可以派生出k8s相關的多個指標數據,主要是資源類型相關的計數器和元數據信息,包括制定類型的對象總數、資源限額、容器狀態以及Pod資源標簽系列等。
Prometheus 能夠 直接 把 Kubernetes API Server 作為 服務 發現 系統 使用 進而 動態 發現 和 監控 集群 中的 所有 可被 監控 的 對象。 這里 需要 特別 說明 的 是, Pod 資源 需要 添加 下列 注解 信息 才 能被 Prometheus 系統 自動 發現 並 抓取 其 內建 的 指標 數據。
- 1) prometheus. io/ scrape: 用於 標識 是否 需要 被 采集 指標 數據, 布爾 型 值, true 或 false。
- 2) prometheus. io/ path: 抓取 指標 數據 時 使用 的 URL 路徑, 一般 為/ metrics。
- 3) prometheus. io/ port: 抓取 指標 數據 時 使 用的 套 接 字 端口, 如 8080。
另外, 僅 期望 Prometheus 為 后端 生成 自定義 指標 時 僅 部署 Prometheus 服務器 即可, 它 甚至 也不 需要 數據 持久 功能。 但 若要 配置 完整 功能 的 監控 系統, 管理員 還需 要在 每個 主機 上 部署 node_ exporter、 按 需 部署 其他 特有 類型 的 exporter 以及 Alertmanager。
2、Prometheus-Operator的架構
上圖是Prometheus-Operator官方提供的架構圖,從下向上看,Operator可以部署並且管理Prometheus Server,並且Operator可以觀察Prometheus,那么這個觀察是什么意思呢,上圖中Service1 - Service5其實就是kubernetes的service,kubernetes的資源分為Service、Deployment、ServiceMonitor、ConfigMap等等,所以上圖中的Service和ServiceMonitor都是kubernetes資源,一個ServiceMonitor可以通過labelSelector的方式去匹配一類Service(一般來說,一個ServiceMonitor對應一個Service),Prometheus也可以通過labelSelector去匹配多個ServiceMonitor。
-
Operator : Operator是整個系統的主要控制器,會以Deployment的方式運行於Kubernetes集群上,並根據自定義資源(Custom Resources Definition)CRD 來負責管理與部署Prometheus,Operator會通過監聽這些CRD的變化來做出相對應的處理。
-
Prometheus : Operator會觀察集群內的Prometheus CRD(Prometheus 也是一種CRD)來創建一個合適的statefulset在monitoring(.metadata.namespace指定)命名空間,並且掛載了一個名為prometheus-k8s的Secret為Volume到/etc/prometheus/config目錄,Secret的data包含了以下內容
- configmaps.json指定了rule-files在configmap的名字
- prometheus.yaml為主配置文件
-
ServiceMonitor : ServiceMonitor就是一種kubernetes自定義資源(CRD),Operator會通過監聽ServiceMonitor的變化來動態生成Prometheus的配置文件中的Scrape targets,並讓這些配置實時生效,operator通過將生成的job更新到上面的prometheus-k8s這個Secret的Data的prometheus.yaml字段里,然后prometheus這個pod里的sidecar容器
prometheus-config-reloader
當檢測到掛載路徑的文件發生改變后自動去執行HTTP Post請求到/api/-reload-
路徑去reload配置。該自定義資源(CRD)通過labels選取對應的Service,並讓prometheus server通過選取的Service拉取對應的監控信息(metric) -
Service :Service其實就是指kubernetes的service資源,這里特指Prometheus exporter的service,比如部署在kubernetes上的mysql-exporter的service
想象一下,我們以傳統的方式去監控一個mysql服務,首先需要安裝mysql-exporter,獲取mysql metrics,並且暴露一個端口,等待prometheus服務來拉取監控信息,然后去Prometheus Server的prometheus.yaml文件中在scarpe_config中添加mysql-exporter的job,配置mysql-exporter的地址和端口等信息,再然后,需要重啟Prometheus服務,就完成添加一個mysql監控的任務
現在我們以Prometheus-Operator的方式來部署Prometheus,當我們需要添加一個mysql監控我們會怎么做,首先第一步和傳統方式一樣,部署一個mysql-exporter來獲取mysql監控項,然后編寫一個ServiceMonitor通過labelSelector選擇剛才部署的mysql-exporter,由於Operator在部署Prometheus的時候默認指定了Prometheus選擇label為:prometheus: kube-prometheus
的ServiceMonitor,所以只需要在ServiceMonitor上打上prometheus: kube-prometheus
標簽就可以被Prometheus選擇了,完成以上兩步就完成了對mysql的監控,不需要改Prometheus配置文件,也不需要重啟Prometheus服務,是不是很方便,Operator觀察到ServiceMonitor發生變化,會動態生成Prometheus配置文件,並保證配置文件實時生效
2、kube-prometheus 介紹
目前我使用的是 kube-prometheus 版本為 kube-prometheus-release-0.3,
首先Prometheus整體監控結構略微復雜,一個個部署並不簡單。另外監控Kubernetes就需要訪問內部數據,必定需要進行認證、鑒權、准入控制,那么這一整套下來將變得難上加難,而且還需要花費一定的時間,如果你沒有特別高的要求,我還是建議選用開源比較好的一些方案。
本篇主要針對Kubernetes部署Prometheus相關配置介紹,本人采用的是github開源的部署方案:
關於這個kube-prometheus目前應該是開源最好的方案了,該存儲庫收集Kubernetes清單,Grafana儀表板和Prometheus規則,以及文檔和腳本,以使用Prometheus Operator 通過Prometheus提供易於操作的端到端Kubernetes集群監視。以容器的方式部署到k8s集群,而且還可以自定義配置,非常的方便。
kube-prometheus相關部署文件在manifests目錄中,共65個yaml,其中setup文件夾中包含所有自定義資源配置CustomResourceDefinition(一般不用修改,也不要輕易修改),所以部署時必須先執行這個文件夾。其中包括告警(Alertmanager)、監控(Prometheus)、監控項(PrometheusRule)這三類資源定義,所以如果你想直接在k8s中修改對應控制器配置是沒有用的(比如kubectl edit sts prometheus-k8s -n monitoring) 。這里yaml文件看着很多,只要我們梳理一下就會很容易理解了,首先分為7個組件prometheus-operator、prometheus-adapter、prometheus、alertmanager、grafana、kube-state-metrics、node-exporter,然后每個組件都會定義控制器、配置文件、集群權限、訪問配置、監控配置, 但是我們一般只需要進行自定義告警配置和監控項,這樣一篩選發現只需要修改幾個文件即可(其中紅色后面重點說明,紫色可根據項目情況調整資源配置)。
[root@k8s-master yaml]# git clone https://github.com/prometheus-operator/kube-prometheus.git --branch release-0.3 --single-branch [root@localhost manifests]$ tree . ├── alertmanager-alertmanager.yaml ├── alertmanager-secret.yaml ├── alertmanager-serviceAccount.yaml ├── alertmanager-serviceMonitor.yaml ├── alertmanager-service.yaml ├── grafana-dashboardDatasources.yaml ├── grafana-dashboardDefinitions.yaml ├── grafana-dashboardSources.yaml ├── grafana-deployment.yaml ├── grafana-serviceAccount.yaml ├── grafana-serviceMonitor.yaml ├── grafana-service.yaml ├── kube-state-metrics-clusterRoleBinding.yaml ├── kube-state-metrics-clusterRole.yaml ├── kube-state-metrics-deployment.yaml ├── kube-state-metrics-roleBinding.yaml ├── kube-state-metrics-role.yaml ├── kube-state-metrics-serviceAccount.yaml ├── kube-state-metrics-serviceMonitor.yaml ├── kube-state-metrics-service.yaml ├── node-exporter-clusterRoleBinding.yaml ├── node-exporter-clusterRole.yaml ├── node-exporter-daemonset.yaml ├── node-exporter-serviceAccount.yaml ├── node-exporter-serviceMonitor.yaml ├── node-exporter-service.yaml ├── prometheus-adapter-apiService.yaml ├── prometheus-adapter-clusterRoleAggregatedMetricsReader.yaml ├── prometheus-adapter-clusterRoleBindingDelegator.yaml ├── prometheus-adapter-clusterRoleBinding.yaml ├── prometheus-adapter-clusterRoleServerResources.yaml ├── prometheus-adapter-clusterRole.yaml ├── prometheus-adapter-configMap.yaml ├── prometheus-adapter-deployment.yaml ├── prometheus-adapter-roleBindingAuthReader.yaml ├── prometheus-adapter-serviceAccount.yaml ├── prometheus-adapter-service.yaml ├── prometheus-clusterRoleBinding.yaml ├── prometheus-clusterRole.yaml ├── prometheus-operator-serviceMonitor.yaml ├── prometheus-prometheus.yaml ├── prometheus-roleBindingConfig.yaml ├── prometheus-roleBindingSpecificNamespaces.yaml ├── prometheus-roleConfig.yaml ├── prometheus-roleSpecificNamespaces.yaml ├── prometheus-rules.yaml ├── prometheus-serviceAccount.yaml ├── prometheus-serviceMonitorApiserver.yaml ├── prometheus-serviceMonitorCoreDNS.yaml ├── prometheus-serviceMonitorKubeControllerManager.yaml ├── prometheus-serviceMonitorKubelet.yaml ├── prometheus-serviceMonitorKubeScheduler.yaml ├── prometheus-serviceMonitor.yaml ├── prometheus-service.yaml └── setup ├── 0namespace-namespace.yaml ├── prometheus-operator-0alertmanagerCustomResourceDefinition.yaml ├── prometheus-operator-0podmonitorCustomResourceDefinition.yaml ├── prometheus-operator-0prometheusCustomResourceDefinition.yaml ├── prometheus-operator-0prometheusruleCustomResourceDefinition.yaml ├── prometheus-operator-0servicemonitorCustomResourceDefinition.yaml ├── prometheus-operator-clusterRoleBinding.yaml ├── prometheus-operator-clusterRole.yaml ├── prometheus-operator-deployment.yaml ├── prometheus-operator-serviceAccount.yaml └── prometheus-operator-service.yaml 1 directory, 65 files
- alertmanager模塊主要針對告警功能
- grafana 儀表盤
- kube-state-metrics
kube-state-metrics是一個簡單的服務,它監聽Kubernetes API服務器並生成關於對象狀態的度量。(請參閱下面度量標准一節中的示例。)它不關注單個Kubernetes組件的運行狀況,而是關注其中各種對象(如部署、節點和pod)的運行狀況。
kube-state-metrics是關於不用修改就從Kubernetes API對象生成度量的。這確保了kube-state-metrics提供的特性與Kubernetes API對象本身具有相同級別的穩定性。反過來,這意味着在某些情況下kube-state-metrics可能不會顯示與kubectl完全相同的值,因為kubectl應用某些啟發性來顯示可理解的消息。kube-state-metrics從Kubernetes API中公開未經修改的原始數據,這樣用戶就可以獲得他們需要的所有數據,並在他們認為合適的時候執行試探。
度量在HTTP端點上導出/度量在偵聽端口(默認8080)上導出。它們被用作明文。它們被設計為要么由普羅米修斯自己使用,要么由與抓取普羅米修斯客戶端端點兼容的scraper使用。您還可以在瀏覽器中打開/metrics來查看原始指標。注意,在/metrics端點上公開的度量反映了Kubernetes集群的當前狀態。當Kubernetes對象被刪除時,它們在/metrics端點上不再可見。
- node-exporter 監控宿主機的性能
- prometheus-adapter 實現 custom metrics API,resource metrics API 兩種自定義API, 可參考: https://juejin.cn/post/6844903967218991117
二、部署kube-prometheus
如果不需要持久化和添加額外監控可以直接運行以下命令執行創建監控
[root@localhost package]# cd manifests [root@localhost manifests ]# kubectl apply -f setup/ [root@localhost manifests ]# kubectl apply -f .
以下是我新加的幾個yaml文件,主要做了持久化和添加額外監控。
[root@localhost manifests]$ tree . ├── alertmanager-alertmanager.yaml ├── alertmanager-secret.yaml ├── alertmanager-serviceAccount.yaml ├── alertmanager-serviceMonitor.yaml ├── alertmanager-service.yaml ├── grafana-dashboardDatasources.yaml ├── grafana-dashboardDefinitions.yaml ├── grafana-dashboardSources.yaml ├── grafana-deployment.yaml ├── grafana-pvc.yaml ### 新添加,主要作為 grafan 持久化存儲 ├── grafana-serviceAccount.yaml ├── grafana-serviceMonitor.yaml ├── grafana-service.yaml ├── kube-state-metrics-clusterRoleBinding.yaml ├── kube-state-metrics-clusterRole.yaml ├── kube-state-metrics-deployment.yaml ├── kube-state-metrics-roleBinding.yaml ├── kube-state-metrics-role.yaml ├── kube-state-metrics-serviceAccount.yaml ├── kube-state-metrics-serviceMonitor.yaml ├── kube-state-metrics-service.yaml ├── node-exporter-clusterRoleBinding.yaml ├── node-exporter-clusterRole.yaml ├── node-exporter-daemonset.yaml ├── node-exporter-serviceAccount.yaml ├── node-exporter-serviceMonitor.yaml ├── node-exporter-service.yaml ├── prometheus-adapter-apiService.yaml ├── prometheus-adapter-clusterRoleAggregatedMetricsReader.yaml ├── prometheus-adapter-clusterRoleBindingDelegator.yaml ├── prometheus-adapter-clusterRoleBinding.yaml ├── prometheus-adapter-clusterRoleServerResources.yaml ├── prometheus-adapter-clusterRole.yaml ├── prometheus-adapter-configMap.yaml ├── prometheus-adapter-deployment.yaml ├── prometheus-adapter-roleBindingAuthReader.yaml ├── prometheus-adapter-serviceAccount.yaml ├── prometheus-adapter-service.yaml ├── prometheus-additional.yaml ## 新添加,主要添加 k8s集群外的監控,如其他主機的node-exporter、mysqld-exporter等 ├── prometheus-clusterRoleBinding.yaml ├── prometheus-clusterRole.yaml ├── prometheus-kubeControllerManagerService.yaml ###新添加, 針對ControllerManagerService 的監控 ├── prometheus-kubeSchedulerService.yaml ### 新添加, 主要針對 kubeScheduler 的監控 ├── prometheus-operator-serviceMonitor.yaml ├── prometheus-prometheus.yaml ├── prometheus-roleBindingConfig.yaml ├── prometheus-roleBindingSpecificNamespaces.yaml ├── prometheus-roleConfig.yaml ├── prometheus-roleSpecificNamespaces.yaml ├── prometheus-rules.yaml ├── prometheus-serviceAccount.yaml ├── prometheus-serviceMonitorApiserver.yaml ├── prometheus-serviceMonitorCoreDNS.yaml ├── prometheus-serviceMonitorKubeControllerManager.yaml ├── prometheus-serviceMonitorKubelet.yaml ├── prometheus-serviceMonitorKubeScheduler.yaml ├── prometheus-serviceMonitor.yaml ├── prometheus-service.yaml └── setup ├── 0namespace-namespace.yaml ├── prometheus-operator-0alertmanagerCustomResourceDefinition.yaml ├── prometheus-operator-0podmonitorCustomResourceDefinition.yaml ├── prometheus-operator-0prometheusCustomResourceDefinition.yaml ├── prometheus-operator-0prometheusruleCustomResourceDefinition.yaml ├── prometheus-operator-0servicemonitorCustomResourceDefinition.yaml ├── prometheus-operator-clusterRoleBinding.yaml ├── prometheus-operator-clusterRole.yaml ├── prometheus-operator-deployment.yaml ├── prometheus-operator-serviceAccount.yaml └── prometheus-operator-service.yaml 1 directory, 69 files
三、修改 prometheus 配置
1、添加k8s外部監控
一個項目開始可能很難實現全部容器化,比如數據庫、CDH集群。但是我們依然需要監控他們,如果分成兩套prometheus不利於管理,所以我們統一添加這些監控到kube-prometheus中。
那么接下來我們新建 prometheus-additional.yaml 文件,添加額外監控組件配置scrape_configs。
- job_name: 'node-exporter-others' static_configs: - targets: - *.*.*.149:31190 - *.*.*.150:31190 - *.*.*.122:31190 - job_name: 'mysql-exporter' static_configs: - targets: - *.*.*.104:9592 - *.*.*.125:9592 - *.*.*.128:9592 - job_name: 'nacos-exporter' metrics_path: '/nacos/actuator/prometheus' static_configs: - targets: - *.*.*.113:8848 - *.*.*.114:8848 - *.*.*.118:8848 - job_name: 'elasticsearch-exporter' static_configs: - targets: - *.*.*.110:9597 - *.*.*.107:9597 - *.*.*.117:9597 - job_name: 'zookeeper-exporter' static_configs: - targets: - *.*.*.115:9595 - *.*.*.121:9595 - *.*.*.120:9595 - job_name: 'nginx-exporter' static_configs: - targets: - *.*.*.149:9593 - *.*.*.150:9593 - *.*.*.122:9593 - job_name: 'redis-exporter' static_configs: - targets: - *.*.*.109:9594 - job_name: 'redis-exporter-targets' static_configs: - targets: - redis://*.*.*.146:7090 - redis://*.*.*.144:7090 - redis://*.*.*.133:7091 metrics_path: /scrape relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: *.*.*.109:9594 prometheus-additional.yaml
然后我們需要將這些監控配置以secret資源類型存儲到k8s集群中。
kubectl create secret generic additional-scrape-configs --from-file=prometheus-additional.yaml -n monitoring
2、修改 prometheus 文件
vim prometheus-prometheus.yaml
1)replicas:根據項目情況調整副本數
2)retention:修改Prometheus數據保留期限,默認值為“24h”,並且必須與正則表達式“ [0-9] +(ms | s | m | h | d | w | y)”匹配。
3)additionalScrapeConfigs:增加額外監控項配置,具體配置查看第五部分“添加k8s外部監控”。
4)添加 持久化存儲
apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: labels: prometheus: k8s name: k8s namespace: monitoring spec: imagePullSecrets: - name: harborsecret alerting: alertmanagers: - name: alertmanager-main namespace: monitoring port: web baseImage: 10.2.57.16:5000/kubernetes/prometheus nodeSelector: kubernetes.io/os: linux podMonitorNamespaceSelector: {} podMonitorSelector: {} additionalScrapeConfigs: name: additional-scrape-configs key: prometheus-additional.yaml retention: 15d replicas: 2 resources: requests: memory: 400Mi ruleSelector: matchLabels: prometheus: k8s role: alert-rules securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 1000 serviceAccountName: prometheus-k8s serviceMonitorNamespaceSelector: {} serviceMonitorSelector: {} version: v2.11.0 storage: volumeClaimTemplate: spec: storageClassName: monitoring-use resources: requests: storage: 50Gi
Scheduler和Controller配置
展開Status菜單,查看targets,可以看到只有圖中兩個監控任務沒有對應的目標,這和serviceMonitor資源對象有關。
查看yaml文件prometheus-serviceMonitorKubeScheduler.yaml,selector匹配的是service的標簽,但是kube-system namespace中並沒有k8s-app=kube-scheduler的service
新建prometheus-kubeSchedulerService.yaml
apiVersion: v1 kind: Service metadata: namespace: kube-system name: kube-scheduler labels: k8s-app: kube-scheduler spec: selector: component: kube-scheduler ports: - name: http-metrics port: 10251 targetPort: 10251 protocol: TCP
同理新建prometheus-kubeControllerManagerService.yaml
apiVersion: v1 kind: Service metadata: namespace: kube-system name: kube-controller-manager labels: k8s-app: kube-controller-manager spec: selector: component: kube-controller-manager ports: - name: http-metrics port: 10252 targetPort: 10252 protocol: TCP
五、Grafana 配置
默認Grafana不做數據持久化,那么服務重啟以后配置的Dashboard、賬號密碼、監控數據等信息將會丟失,所以做數據持久化也是很有必要的。
原始的數據是以 emptyDir 形式存放在pod里面,生命周期與pod相同,出現問題時,容器重啟,監控相關的數據就全部消失了。
這里我們通過 storageclass 來做數據持久化,具體配置可以參考:Kubernetes實戰總結 - 動態存儲管理StorageClass
對於Grafana來說,我們需要在grafana-deployment.yaml中增加PVC配置,並且更改volumes.grafana-storage。
新建 grafana-pvc.yaml 文件
--- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: grafana namespace: monitoring annotations: volume.beta.kubernetes.io/storage-class: "monitoring-use" spec: storageClassName: monitoring-use accessModes: - ReadWriteOnce resources: requests: storage: 20Gi
修改 grafana-deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: labels: app: grafana name: grafana namespace: monitoring spec: replicas: 1 selector: matchLabels: app: grafana template: metadata: labels: app: grafana spec: imagePullSecrets: - name: harborsecret containers: - image: 10.2.57.16:5000/kubernetes/grafana:6.4.3 name: grafana ports: - containerPort: 3000 name: http readinessProbe: httpGet: path: /api/health port: http resources: limits: cpu: 200m memory: 200Mi requests: cpu: 100m memory: 100Mi volumeMounts: - mountPath: /var/lib/grafana name: grafana-storage readOnly: false volumes: - name: grafana-storage persistentVolumeClaim: claimName: grafana