prometheus基于kubernetes監控
prometheus對kubernetes的監控
對于Kubernetes而言,我們可以把當中所有的資源分為幾類:
- 基礎設施層(Node):集群節點,為整個集群和應用提供運行時資源
- 容器基礎設施(Container):為應用提供運行時環境
- 用戶應用(Pod):Pod中會包含一組容器,它們一起工作,并且對外提供一個(或者一組)功能
- 內部服務負載均衡(Service):在集群內,通過Service在集群暴露應用功能,集群內應用和應用之間訪問時提供內部的負載均衡
- 外部訪問入口(Ingress):通過Ingress提供集群外的訪問入口,從而可以使外部客戶端能夠訪問到部署在Kubernetes集群內的服務
因此,如果要構建一個完整的監控體系,我們應該考慮,以下5個方面:
- 集群節點狀態監控:從集群中各節點的kubelet服務獲取節點的基本運行狀態
- 集群節點資源用量監控:通過Daemonset的形式在集群中各節點部署Node Exporter采集節點的資源使用情況
- 節點中運行的容器監控:通過各個節點中kubelet內置的cAdvisor中獲取各節點中所有容器的運行狀態和資源使用狀態
- 如果在集群中部署的應用程序本身內置了對prometheus的監控支持,那么我們還應該找到相應的pod實例,并從該pod實例中獲取其內部運行狀態的監控指標
- 對k8s本身的組件做監控:apiserver、scheduler、controller-manager、kubelet、kube-proxy
我的機器規劃
master節點 | node節點 | |
---|---|---|
數量 | 1 | 2 |
hostname | wentaomaster1 | wentaonode1|wentaonode2 |
IP | 192.168.184.10 | 192.168.184.20|192.168.184.30 |
k8s版本 | 1.25.0 | 1.25.0 |
node_exporter組件安裝和配置
node_exporter介紹
node_exporter可以采集機器(物理機、虛擬機、云主機等)的監控指標數據,能夠采集到的指標包括CPU、內存、磁盤、網絡、文件數等信息
安裝node_exporter
[root@wentaomaster1]#kubectl create ns monitor-sa
[root@wentaomaster1]#ctr -n k8s.io images import node-exporter.tar.gz
[root@wentaonode1]#ctr -n k8s.io images import node-exporter.tar.gz
[root@wentaonode2]#ctr -n k8s.io images import node-exporter.tar.gz
[root@wentaomaster1]#cat node-export.yaml
apiVersion: apps/v1
kind: DaemonSet #可以保證k8s集群的每個節點都運行完全一樣的pod
metadata:name: node-exporternamespace: monitor-salabels:name: node-exporter
spec:selector:matchLabels:name: node-exportertemplate:metadata:labels:name: node-exporterspec:hostPID: truehostIPC: truehostNetwork: true# hostNetwork、hostIPC、hostPID都為True時,表示這個Pod里的所有容器,會直接使用宿主機的網絡,直接與宿主機進行IPC(進程間通信)通信,可以看到宿主機里正在運行的所有進程。加入了hostNetwork:true會直接將我們的宿主機的9100端口映射出來,從而不需要創建service 在我們的宿主機上就會有一個9100的端口containers:- name: node-exporterimage: prom/node-exporter:v0.16.0imagePullPolicy: IfNotPresentports:- containerPort: 9100resources:requests:cpu: 0.15securityContext:privileged: true #開啟特權模式args:- --path.procfs#配置掛載宿主機(node節點)的路徑- /host/proc- --path.sysfs#配置掛載宿主機(node節點)的路徑- /host/sys- --collector.filesystem.ignored-mount-points- '"^/(sys|proc|dev|host|etc)($|/)"'#通過正則表達式忽略某些文件系統掛載點的信息收集volumeMounts:- name: devmountPath: /host/dev- name: procmountPath: /host/proc- name: sysmountPath: /host/sys- name: rootfsmountPath: /rootfs#將主機/dev、/proc、/sys這些目錄掛在到容器中,這是因為我們采集的很多節點數據都是通過這些文件來獲取系統信息的。tolerations:- key: ""operator: "Exists"effect: "NoSchedule" #對污點為NoSchedule的節點定義容忍度volumes:- name: prochostPath:path: /proc- name: devhostPath:path: /dev- name: syshostPath:path: /sys- name: rootfshostPath:path: /
[root@wentaomaster1]#kubectl apply -f node-export.yaml
#通過kubectl apply更新node-exporter.yaml文件
[root@wentaomaster1]#kubectl get pod -n monitor-sa
#查看node-exporter是否部署成功
#顯示如下,看到pod的狀態都是running,說明部署成功
[root@wentaomaster1]# curl http://192.168.184.20:9100/metrics
#通過node-exporter采集數據
#node-export默認的監聽端口是9100,可以看到當前主機獲取到的所有監控數據
[root@wentaomaster1]# curl http://192.168.184.20:9100/metrics | grep node_cpu_seconds
#顯示192.168.184.20主機cpu的使用情況
prometheus server安裝和配置
創建serviceaccount賬號,對其做RBAC授權
#創建一個sa賬號monitor
[root@wentaomaster1 ~]# kubectl create serviceaccount monitor -n monitor-sa
#把sa賬號monitor通過clusterrolebing綁定到clusterrole上
[root@wentaomaster1 ~]# kubectl create clusterrolebinding monitor-clusterrolebinding -n monitor-sa --clusterrole=cluster-admin --serviceaccount=monitor-sa:monitor
[root@wentaomaster1~]# kubectl create clusterrolebinding monitor-clusterrolebinding-1 -n monitor-sa --clusterrole=cluster-admin --user=system:serviceaccount:monitor:monitor-sa
創建prometheus數據存儲目錄
#在k8s集群的兩個node節點上創建數據存儲目錄
[root@wentaonode1 ~]# mkdir /data
[root@wentaonode1 ~]# chmod 777 /data/
[root@wentaonode2 ~]# mkdir /data
[root@wentaonode2 ~]# chmod 777 /data/
安裝prometheus server服務
創建一個configmap存儲卷,用來存放prometheus配置信息
[root@wentaomaster1]# cat prometheus-cfg.yaml
---
kind: ConfigMap
apiVersion: v1
metadata:labels:app: prometheusname: prometheus-confignamespace: monitor-sa
data:prometheus.yml: |global:scrape_interval: 15sscrape_timeout: 10sevaluation_interval: 1mscrape_configs:- job_name: 'kubernetes-node'kubernetes_sd_configs:- role: noderelabel_configs:- source_labels: [__address__]regex: '(.*):10250'replacement: '${1}:9100'target_label: __address__action: replace- action: labelmapregex: __meta_kubernetes_node_label_(.+)- job_name: 'kubernetes-node-cadvisor'kubernetes_sd_configs:- role: nodescheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenrelabel_configs:- action: labelmapregex: __meta_kubernetes_node_label_(.+)- target_label: __address__replacement: kubernetes.default.svc:443- source_labels: [__meta_kubernetes_node_name]regex: (.+)target_label: __metrics_path__replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor- job_name: 'kubernetes-apiserver'kubernetes_sd_configs:- role: endpointsscheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenrelabel_configs:- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]action: keepregex: default;kubernetes;https- job_name: 'kubernetes-service-endpoints'kubernetes_sd_configs:- role: endpointsrelabel_configs:- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]action: keepregex: true- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]action: replacetarget_label: __scheme__regex: (https?)- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]action: replacetarget_label: __metrics_path__regex: (.+)- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]action: replacetarget_label: __address__regex: ([^:]+)(?::\d+)?;(\d+)replacement: $1:$2- action: labelmapregex: __meta_kubernetes_service_label_(.+)- source_labels: [__meta_kubernetes_namespace]action: replacetarget_label: kubernetes_namespace- source_labels: [__meta_kubernetes_service_name]action: replacetarget_label: kubernetes_name
[root@wentaomaster1]#kubectl apply -f prometheus-cfg.yaml
通過deployment部署prometheus
[root@wentaonode1 ~]# ctr -n=k8s.io images import prometheus-2-2-1.tar.gz
[root@wentaonode2 ~]# ctr -n=k8s.io images import prometheus-2-2-1.tar.gz
[root@wentaomaster1 ~]# cat prometheus-deploy.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:name: prometheus-servernamespace: monitor-salabels:app: prometheus
spec:replicas: 2selector:matchLabels:app: prometheuscomponent: server#matchExpressions:#- {key: app, operator: In, values: [prometheus]}#- {key: component, operator: In, values: [server]}template:metadata:labels:app: prometheuscomponent: serverannotations:prometheus.io/scrape: 'false'spec:serviceAccountName: monitorcontainers:- name: prometheusimage: prom/prometheus:v2.2.1imagePullPolicy: IfNotPresentcommand:- prometheus- --config.file=/etc/prometheus/prometheus.yml- --storage.tsdb.path=/prometheus #舊數據存儲目錄- --storage.tsdb.retention=720h #何時刪除舊數據,默認為15天。- --web.enable-lifecycle #開啟熱加載ports:- containerPort: 9090protocol: TCPvolumeMounts:- mountPath: /etc/prometheusname: prometheus-config- mountPath: /prometheus/name: prometheus-storage-volumevolumes:- name: prometheus-configconfigMap:name: prometheus-config- name: prometheus-storage-volumehostPath:path: /datatype: Directory
[root@xianchaomaster1]# kubectl apply -f prometheus-deploy.yaml
#查看prometheus是否部署成功
[root@xianchaomaster1]# kubectl get pods -n monitor-sa
#顯示如下,可看到pod狀態是running,說明prometheus部署成功
給prometheus pod創建一個service
[root@wentaomaster1 ~]# cat prometheus-svc.yaml
apiVersion: v1
kind: Service
metadata:name: prometheusnamespace: monitor-salabels:app: prometheus
spec:type: NodePortports:- port: 9090targetPort: 9090protocol: TCPselector:app: prometheuscomponent: server[root@wentaomaster1 ~]# kubectl apply -f prometheus-svc.yaml
[root@wentaomaster1 ~]# kubectl get svc -n monitor-sa
#查看service在物理機映射的端口
通過上面可以看到service在宿主機上映射的端口是30065,這樣我們訪問k8s集群的node1節點的ip:30065,就可以訪問到prometheus的web ui界面了
點擊頁面的Status->Targets,可看到如下,說明我們配置的服務發現可以正常采集數據
prometheus熱加載
#為了每次修改配置文件可以熱加載prometheus,也就是不停止prometheus,就可以使配置生效,想要使配置生效可用如下熱加載命令:
[root@wentaomaster1 ~]# kubectl get pod -n monitor-sa -o wide
#10.244.166.172/10.244.105.15是k8s內部的prometheus的pod的ip地址
#想要使配置熱生效可用如下命令熱加載:
[root@wentaomaster1 ~]# curl -X POST http://10.244.166.172:9090/-/reload
#熱加載速度比較慢,可以暴力重啟prometheus,如修改上面的prometheus-cfg.yaml文件之后,可執行如下強制刪除:
kubectl delete -f prometheus-cfg.yaml
kubectl delete -f prometheus-deploy.yaml
然后再通過apply更新:
kubectl apply -f prometheus-cfg.yaml
kubectl apply -f prometheus-deploy.yaml
注意:
線上最好熱加載,暴力刪除可能造成監控數據的丟失
可視化UI界面Grafana的安裝和配置
Grafana介紹
Grafana是一個跨平臺的開源的度量分析和可視化工具,可以將采集的數據可視化的展示,并及時通知給告警接收方。它主要有以下六大特點:
1、展示方式:快速靈活的客戶端圖表,面板插件有許多不同方式的可視化指標和日志,官方庫中具有豐富的儀表盤插件,比如熱圖、折線圖、圖表等多種展示方式;
2、數據源:Graphite,InfluxDB,OpenTSDB,Prometheus,Elasticsearch,CloudWatch和KairosDB等;
3、通知提醒:以可視方式定義最重要指標的警報規則,Grafana將不斷計算并發送通知,在數據達到閾值時通過Slack、PagerDuty等獲得通知;
4、混合展示:在同一圖表中混合使用不同的數據源,可以基于每個查詢指定數據源,甚至自定義數據源;
5、注釋:使用來自不同數據源的豐富事件注釋圖表,將鼠標懸停在事件上會顯示完整的事件元數據和標記。
安裝Grafana
[root@wentaonode1 ~]# ctr -n=k8s.io images import heapster-grafana-amd64_v5_0_4.tar.gz
[root@wentaonode2 ~]# ctr -n=k8s.io images import heapster-grafana-amd64_v5_0_4.tar.gz
[root@wentaomaster1 ~]# cat grafana.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: monitoring-grafananamespace: kube-system
spec:replicas: 2selector:matchLabels:task: monitoringk8s-app: grafanatemplate:metadata:labels:task: monitoringk8s-app: grafanaspec:containers:- name: grafanaimage: k8s.gcr.io/heapster-grafana-amd64:v5.0.4imagePullPolicy: IfNotPresentports:- containerPort: 3000protocol: TCPvolumeMounts:- mountPath: /etc/ssl/certsname: ca-certificatesreadOnly: true- mountPath: /varname: grafana-storageenv:- name: INFLUXDB_HOSTvalue: monitoring-influxdb- name: GF_SERVER_HTTP_PORTvalue: "3000"# The following env variables are required to make Grafana accessible via# the kubernetes api-server proxy. On production clusters, we recommend# removing these env variables, setup auth for grafana, and expose the grafana# service using a LoadBalancer or a public IP.- name: GF_AUTH_BASIC_ENABLEDvalue: "false"- name: GF_AUTH_ANONYMOUS_ENABLEDvalue: "true"- name: GF_AUTH_ANONYMOUS_ORG_ROLEvalue: Admin- name: GF_SERVER_ROOT_URL# If you're only using the API Server proxy, set this value instead:# value: /api/v1/namespaces/kube-system/services/monitoring-grafana/proxyvalue: /volumes:- name: ca-certificateshostPath:path: /etc/ssl/certs- name: grafana-storageemptyDir: {}
---
apiVersion: v1
kind: Service
metadata:labels:# For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons)# If you are NOT using this as an addon, you should comment out this line.kubernetes.io/cluster-service: 'true'kubernetes.io/name: monitoring-grafananame: monitoring-grafananamespace: kube-system
spec:# In a production setup, we recommend accessing Grafana through an external Loadbalancer# or through a public IP.# type: LoadBalancer# You could also use NodePort to expose the service at a randomly-generated port# type: NodePortports:- port: 80targetPort: 3000selector:k8s-app: grafanatype: NodePort
#更新yaml文件:
[root@wentaomaster1 ~]# kubectl apply -f grafana.yaml
#查看grafana是否創建成功:
[root@wentaomaster1 ~]# kubectl get pod -n kube-system -l task=monitoring
#顯示如下,說明部署成功
Grafana界面接入prometheus數據源
#查看grafana前端的service
[root@wentaomaster1 ~]# kubectl get svc -n kube-system
- 登錄grafana,在瀏覽器訪問192.168.184.10:32562 ,可看到如下頁面
- 配置grafana界面:
- 開始配置grafana的web界面:
選擇Create your first data source
- 開始配置grafana的web界面:
- 出現如下:
#注:
#Name: Prometheus
#Type: Prometheus
#HTTP 處的URL寫 如下:
#http://prometheus.monitor-sa.svc:9090
- 點擊左下角Save & Test,出現如下Data source is working,說明prometheus數據源成功的被grafana接入了
-
導入的監控模板,可在如下鏈接搜索
https://grafana.com/dashboards?dataSource=prometheus&search=kubernetes -
導入監控模板,按如下步驟:
上面Save & Test測試沒問題之后,就可以返回Grafana主頁面
點擊左側+號下面的import,如下:
選擇Upload json file,然后選擇一個本地的json文件
這里選擇的是node_exporter.json這個文件,選擇之后出現如下:
Prometheus后面需要變成Prometheus,然后再點擊Import,就可以出現如下界面:
導入docker_rev1.json監控模板,步驟和上面導入node_exporter.json步驟一樣,導入之后顯示如下:
安裝kube-state-metrics組件
kube-state-metrics是什么?
kube-state-metrics通過監聽API Server生成有關資源對象的狀態指標,比如Node、Pod,需要注意的是kube-state-metrics只是簡單的提供一個metrics數據,并不會存儲這些指標數據,所以我們可以使用Prometheus來抓取這些數據然后存儲,主要關注的是業務相關的一些元數據,比如Pod副本狀態等;調度了多少個replicas?現在可用的有幾個?多少個Pod是running/stopped/terminated狀態?Pod重啟了多少次?我有多少job在運行中。
安裝kube-state-metrics組件
- 創建sa,并對sa授權
[root@wentaomaster1 ~]# cat kube-state-metrics-rbac.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:name: kube-state-metricsnamespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: kube-state-metrics
rules:
- apiGroups: [""]resources: ["nodes", "pods", "services", "resourcequotas", "replicationcontrollers", "limitranges", "persistentvolumeclaims", "persistentvolumes", "namespaces", "endpoints"]verbs: ["list", "watch"]
- apiGroups: ["extensions"]resources: ["daemonsets", "deployments", "replicasets"]verbs: ["list", "watch"]
- apiGroups: ["apps"]resources: ["statefulsets"]verbs: ["list", "watch"]
- apiGroups: ["batch"]resources: ["cronjobs", "jobs"]verbs: ["list", "watch"]
- apiGroups: ["autoscaling"]resources: ["horizontalpodautoscalers"]verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: kube-state-metrics
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: kube-state-metrics
subjects:
- kind: ServiceAccountname: kube-state-metricsnamespace: kube-system
[root@wentaomaster1 ~]# kubectl apply -f kube-state-metrics-rbac.yaml
- 安裝kube-state-metrics組件
[root@wentaonode1 ~]#ctr -n=k8s.io images import kube-state-metrics_1_9_0.tar.gz
[root@wentaonode2 ~]#ctr -n=k8s.io images import kube-state-metrics_1_9_0.tar.gz
- 通過kubectl apply更新yaml文件
[root@wentaomaster1 ~]# cat kube-state-metrics-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: kube-state-metricsnamespace: kube-system
spec:replicas: 2selector:matchLabels:app: kube-state-metricstemplate:metadata:labels:app: kube-state-metricsspec:serviceAccountName: kube-state-metricscontainers:- name: kube-state-metricsimage: quay.io/coreos/kube-state-metrics:v1.9.0imagePullPolicy: IfNotPresentports:- containerPort: 8080
[root@wentaomaster1 ~]# kubectl apply -f kube-state-metrics-deploy.yaml
#查看kube-state-metrics是否部署成功
[root@wentaomaster1 ~]# kubectl get pod -n kube-system -l app=kube-state-metrics
#顯示如下,看到pod處于running狀態,說明部署成功
- 創建service
在k8s的控制節點生成一個kube-state-metrics-svc.yaml文件
[root@wentaomaster1 ~]# cat kube-state-metrics-svc.yaml
apiVersion: v1
kind: Service
metadata:annotations:prometheus.io/scrape: 'true'name: kube-state-metricsnamespace: kube-systemlabels:app: kube-state-metrics
spec:ports:- name: kube-state-metricsport: 8080protocol: TCPselector:app: kube-state-metrics
[root@wentaomaster1 ~]# kubectl apply -f kube-state-metrics-svc.yaml
#查看service是否創建成功
[root@wentaomaster1 ~]# kubectl get svc -n kube-system
#顯示如下,說明創建成功
- 在grafana web界面導入Kubernetes Cluster (Prometheus)-1577674936972.json和Kubernetes cluster monitoring (via Prometheus) (k8s 1.16)-1577691996738.json
基于Alertmanager發送報警到多個接收方
配置alertmanager發送報警到QQ郵箱
- 報警:指prometheus將監測到的異常事件發送給alertmanager
- 通知:alertmanager將報警信息發送到郵件、企業微信、釘釘等
創建alertmanager-configmap文件
#先提前看一下要創建alertmanager配置文件
#在k8s的可直接點創建alertmanager-cm.yaml文件
[root@wentaomaster1 prometheus]# cat alertmanager-cm.yaml
kind: ConfigMap
apiVersion: v1
metadata:name: alertmanagernamespace: monitor-sa
data:alertmanager.yml: |-global:resolve_timeout: 1msmtp_smarthost: 'smtp.163.com:25' #這是網易的郵箱,可以自己注冊一個,地址mail.163.com,'smtp.163.com:25'這是默認發送系統,填的都一樣smtp_from: '177****8421@163.com' #這是你自己在網易注冊的郵箱,是你發送報警信息的郵箱smtp_auth_username: '177****8421@163.com' #username同上smtp_auth_password: 'PU*********ZIBR'smtp_require_tls: falseroute:group_by: [alertname]group_wait: 10sgroup_interval: 10srepeat_interval: 5mreceiver: default-receiverreceivers:- name: 'default-receiver'email_configs:- to: '2580***386@qq.com' #這是你接收報警的郵箱send_resolved: true
注冊后在設置中找到POP3/SMTP/IMAP:
開啟IMAP/SMTP服務和POP3/SMTP服務,然后會得到一個授權密碼(注意:這個授權密碼只會出現一次,一定要截圖/復制下來,寫配置文件alertmanager-cm.yaml要用):
#創建alertmanager配置文件
#在k8s的可直接點創建alertmanager-cm.yaml文件
[root@wentaomaster1 prometheus]# cat alertmanager-cm.yaml
kind: ConfigMap
apiVersion: v1
metadata:name: alertmanagernamespace: monitor-sa
data:alertmanager.yml: |-global:resolve_timeout: 1msmtp_smarthost: 'smtp.163.com:25' #這是網易的郵箱,可以自己注冊一個,地址mail.163.com,'smtp.163.com:25'這是默認發送系統,填的都一樣smtp_from: '177****8421@163.com' #這是你自己在網易注冊的郵箱,是你發送報警信息的郵箱smtp_auth_username: '177****8421@163.com' #username同上smtp_auth_password: 'PU*********ZIBR'smtp_require_tls: falseroute:group_by: [alertname]group_wait: 10sgroup_interval: 10srepeat_interval: 5mreceiver: default-receiverreceivers:- name: 'default-receiver'email_configs:- to: '2580***386@qq.com' #這是你接收報警的qq郵箱send_resolved: true
alertmanager配置文件解釋說明:
smtp_smarthost: 'smtp.163.com:25'
#163郵箱的SMTP服務器地址+端口
smtp_from: '177****8421@163.com'
#這是指定從哪個郵箱發送報警
smtp_auth_username: '177****8421@163.com'
smtp_auth_password: ' PU*********ZIBR'
#這是發送郵箱的授權碼而不是登錄密碼email_configs:- to: '2580***386@qq.com'
#to后面指定發送到哪個郵箱,我發送到我的qq郵箱route: #用于設置告警的分發策略group_by: [alertname]
#alertmanager會根據group_by配置將Alert分組group_wait: 10s # 分組等待時間。也就是告警產生后等待10s,如果有同組告警一起發出group_interval: 10s # 上下兩組發送告警的間隔時間repeat_interval: 5m # 重復發送告警的時間,減少相同郵件的發送頻率,默認是1hreceiver: default-receiver #定義誰來收告警
- Prometheus 一條告警的觸發流程、等待時間
- 報警處理流程如下:
-
Prometheus Server監控目標主機上暴露的http接口(這里假設接口A),通過Promethes配置的’scrape_interval’定義的時間間隔,定期采集目標主機上監控數據。
-
當接口A不可用的時候,Server端會持續的嘗試從接口中取數據,直到"scrape_timeout"時間后停止嘗試。這時候把接口的狀態變為“DOWN”。
-
Prometheus同時根據配置的"evaluation_interval"的時間間隔,定期(默認1min)的對Alert Rule進行評估;當到達評估周期的時候,發現接口A為DOWN,即UP=0為真,激活Alert,進入“PENDING”狀態,并記錄當前active的時間;
-
當下一個alert rule的評估周期到來的時候,發現UP=0繼續為真,然后判斷警報Active的時間是否已經超出rule里的‘for’ 持續時間,如果未超出,則進入下一個評估周期;如果時間超出,則alert的狀態變為“FIRING”;同時調用Alertmanager接口,發送相關報警數據。
-
AlertManager收到報警數據后,會將警報信息進行分組,然后根據alertmanager配置的“group_wait”時間先進行等待。等wait時間過后再發送報警信息。
-
屬于同一個Alert Group的警報,在等待的過程中可能進入新的alert,如果之前的報警已經成功發出,那么間隔“group_interval”的時間間隔后再重新發送報警信息。比如配置的是郵件報警,那么同屬一個group的報警信息會匯總在一個郵件里進行發送。
-
如果Alert Group里的警報一直沒發生變化并且已經成功發送,等待‘repeat_interval’時間間隔之后再重復發送相同的報警郵件;如果之前的警報沒有成功發送,則相當于觸發第6條條件,則需要等待group_interval時間間隔后重復發送。
同時最后至于警報信息具體發給誰,滿足什么樣的條件下指定警報接收人,設置不同報警發送頻率,這里由alertmanager的route路由規則進行配置。
創建prometheus和告警規則配置文件
#安裝prometheus和alertmanager,需要把alertmanager.tar.gz鏡像包上傳的k8s的各個工作節點,手動解壓:
[root@wentaonode1 ~]# ctr -n=k8s.io images import alertmanager.tar.gz
[root@wentaonode2 ~]# ctr -n=k8s.io images import alertmanager.tar.gz
#生成一個etcd-certs,這個在部署prometheus需要
[root@wentaomaster1 ~]#kubectl -n monitor-sa create secret generic etcd-certs --from-file=/etc/kubernetes/pki/etcd/server.key --from-file=/etc/kubernetes/pki/etcd/server.crt --from-file=/etc/kubernetes/pki/etcd/ca.crt
#在k8s的控制節點生成一個prometheus-alertmanager-cfg.yaml文件
[root@wentaomaster1 ~]# cat prometheus-alertmanager-cfg.yaml
kind: ConfigMap
apiVersion: v1
metadata:labels:app: prometheusname: prometheus-confignamespace: monitor-sa
data:prometheus.yml: |rule_files:- /etc/prometheus/rules.ymlalerting:alertmanagers:- static_configs:- targets: ["localhost:9093"]global:scrape_interval: 15sscrape_timeout: 10sevaluation_interval: 1mscrape_configs:- job_name: 'kubernetes-node'kubernetes_sd_configs:- role: noderelabel_configs:- source_labels: [__address__]regex: '(.*):10250'replacement: '${1}:9100'target_label: __address__action: replace- action: labelmapregex: __meta_kubernetes_node_label_(.+)- job_name: 'kubernetes-node-cadvisor'kubernetes_sd_configs:- role: nodescheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenrelabel_configs:- action: labelmapregex: __meta_kubernetes_node_label_(.+)- target_label: __address__replacement: kubernetes.default.svc:443- source_labels: [__meta_kubernetes_node_name]regex: (.+)target_label: __metrics_path__replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor- job_name: 'kubernetes-apiserver'kubernetes_sd_configs:- role: endpointsscheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenrelabel_configs:- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]action: keepregex: default;kubernetes;https- job_name: 'kubernetes-service-endpoints'kubernetes_sd_configs:- role: endpointsrelabel_configs:- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]action: keepregex: true- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]action: replacetarget_label: __scheme__regex: (https?)- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]action: replacetarget_label: __metrics_path__regex: (.+)- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]action: replacetarget_label: __address__regex: ([^:]+)(?::\d+)?;(\d+)replacement: $1:$2- action: labelmapregex: __meta_kubernetes_service_label_(.+)- source_labels: [__meta_kubernetes_namespace]action: replacetarget_label: kubernetes_namespace- source_labels: [__meta_kubernetes_service_name]action: replacetarget_label: kubernetes_name- job_name: 'kubernetes-pods'kubernetes_sd_configs:- role: podrelabel_configs:- action: keepregex: truesource_labels:- __meta_kubernetes_pod_annotation_prometheus_io_scrape- action: replaceregex: (.+)source_labels:- __meta_kubernetes_pod_annotation_prometheus_io_pathtarget_label: __metrics_path__- action: replaceregex: ([^:]+)(?::\d+)?;(\d+)replacement: $1:$2source_labels:- __address__- __meta_kubernetes_pod_annotation_prometheus_io_porttarget_label: __address__- action: labelmapregex: __meta_kubernetes_pod_label_(.+)- action: replacesource_labels:- __meta_kubernetes_namespacetarget_label: kubernetes_namespace- action: replacesource_labels:- __meta_kubernetes_pod_nametarget_label: kubernetes_pod_name- job_name: 'kubernetes-etcd'scheme: httpstls_config:ca_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/ca.crtcert_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.crtkey_file: /var/run/secrets/kubernetes.io/k8s-certs/etcd/server.keyscrape_interval: 5sstatic_configs:- targets: ['192.168.184.10:2379']rules.yml: |groups:- name: examplerules:- alert: apiserver的cpu使用率大于80%expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}組件的cpu使用率超過80%"- alert: apiserver的cpu使用率大于90%expr: rate(process_cpu_seconds_total{job=~"kubernetes-apiserver"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}組件的cpu使用率超過90%"- alert: etcd的cpu使用率大于80%expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}組件的cpu使用率超過80%"- alert: etcd的cpu使用率大于90%expr: rate(process_cpu_seconds_total{job=~"kubernetes-etcd"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}組件的cpu使用率超過90%"- alert: kube-state-metrics的cpu使用率大于80%expr: rate(process_cpu_seconds_total{k8s_app=~"kube-state-metrics"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.k8s_app}}組件的cpu使用率超過80%"value: "{{ $value }}%"threshold: "80%"- alert: kube-state-metrics的cpu使用率大于90%expr: rate(process_cpu_seconds_total{k8s_app=~"kube-state-metrics"}[1m]) * 100 > 0for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.k8s_app}}組件的cpu使用率超過90%"value: "{{ $value }}%"threshold: "90%"- alert: coredns的cpu使用率大于80%expr: rate(process_cpu_seconds_total{k8s_app=~"kube-dns"}[1m]) * 100 > 80for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.k8s_app}}組件的cpu使用率超過80%"value: "{{ $value }}%"threshold: "80%"- alert: coredns的cpu使用率大于90%expr: rate(process_cpu_seconds_total{k8s_app=~"kube-dns"}[1m]) * 100 > 90for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.k8s_app}}組件的cpu使用率超過90%"value: "{{ $value }}%"threshold: "90%"- alert: kube-proxy打開句柄數>600expr: process_open_fds{job=~"kubernetes-kube-proxy"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>600"value: "{{ $value }}"- alert: kube-proxy打開句柄數>1000expr: process_open_fds{job=~"kubernetes-kube-proxy"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>1000"value: "{{ $value }}"- alert: kubernetes-schedule打開句柄數>600expr: process_open_fds{job=~"kubernetes-schedule"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>600"value: "{{ $value }}"- alert: kubernetes-schedule打開句柄數>1000expr: process_open_fds{job=~"kubernetes-schedule"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>1000"value: "{{ $value }}"- alert: kubernetes-controller-manager打開句柄數>600expr: process_open_fds{job=~"kubernetes-controller-manager"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>600"value: "{{ $value }}"- alert: kubernetes-controller-manager打開句柄數>1000expr: process_open_fds{job=~"kubernetes-controller-manager"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>1000"value: "{{ $value }}"- alert: kubernetes-apiserver打開句柄數>600expr: process_open_fds{job=~"kubernetes-apiserver"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>600"value: "{{ $value }}"- alert: kubernetes-apiserver打開句柄數>1000expr: process_open_fds{job=~"kubernetes-apiserver"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>1000"value: "{{ $value }}"- alert: kubernetes-etcd打開句柄數>600expr: process_open_fds{job=~"kubernetes-etcd"} > 600for: 2slabels:severity: warnningannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>600"value: "{{ $value }}"- alert: kubernetes-etcd打開句柄數>1000expr: process_open_fds{job=~"kubernetes-etcd"} > 1000for: 2slabels:severity: criticalannotations:description: "{{$labels.instance}}的{{$labels.job}}打開句柄數>1000"value: "{{ $value }}"- alert: corednsexpr: process_open_fds{k8s_app=~"kube-dns"} > 600for: 2slabels:severity: warnningannotations:description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 打開句柄數超過600"value: "{{ $value }}"- alert: corednsexpr: process_open_fds{k8s_app=~"kube-dns"} > 1000for: 2slabels:severity: criticalannotations:description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 打開句柄數超過1000"value: "{{ $value }}"- alert: kube-proxyexpr: process_virtual_memory_bytes{job=~"kubernetes-kube-proxy"} > 2000000000for: 2slabels:severity: warnningannotations:description: "組件{{$labels.job}}({{$labels.instance}}): 使用虛擬內存超過2G"value: "{{ $value }}"- alert: schedulerexpr: process_virtual_memory_bytes{job=~"kubernetes-schedule"} > 2000000000for: 2slabels:severity: warnningannotations:description: "組件{{$labels.job}}({{$labels.instance}}): 使用虛擬內存超過2G"value: "{{ $value }}"- alert: kubernetes-controller-managerexpr: process_virtual_memory_bytes{job=~"kubernetes-controller-manager"} > 2000000000for: 2slabels:severity: warnningannotations:description: "組件{{$labels.job}}({{$labels.instance}}): 使用虛擬內存超過2G"value: "{{ $value }}"- alert: kubernetes-apiserverexpr: process_virtual_memory_bytes{job=~"kubernetes-apiserver"} > 2000000000for: 2slabels:severity: warnningannotations:description: "組件{{$labels.job}}({{$labels.instance}}): 使用虛擬內存超過2G"value: "{{ $value }}"- alert: kubernetes-etcdexpr: process_virtual_memory_bytes{job=~"kubernetes-etcd"} > 2000000000for: 2slabels:severity: warnningannotations:description: "組件{{$labels.job}}({{$labels.instance}}): 使用虛擬內存超過2G"value: "{{ $value }}"- alert: kube-dnsexpr: process_virtual_memory_bytes{k8s_app=~"kube-dns"} > 2000000000for: 2slabels:severity: warnningannotations:description: "插件{{$labels.k8s_app}}({{$labels.instance}}): 使用虛擬內存超過2G"value: "{{ $value }}"- alert: HttpRequestsAvgexpr: sum(rate(rest_client_requests_total{job=~"kubernetes-kube-proxy|kubernetes-kubelet|kubernetes-schedule|kubernetes-control-manager|kubernetes-apiservers"}[1m])) > 1000for: 2slabels:team: adminannotations:description: "組件{{$labels.job}}({{$labels.instance}}): TPS超過1000"value: "{{ $value }}"threshold: "1000"- alert: Pod_restartsexpr: kube_pod_container_status_restarts_total{namespace=~"kube-system|default|monitor-sa"} > 0for: 2slabels:severity: warnningannotations:description: "在{{$labels.namespace}}名稱空間下發現{{$labels.pod}}這個pod下的容器{{$labels.container}}被重啟,這個監控指標是由{{$labels.instance}}采集的"value: "{{ $value }}"threshold: "0"- alert: Pod_waitingexpr: kube_pod_container_status_waiting_reason{namespace=~"kube-system|default"} == 1for: 2slabels:team: adminannotations:description: "空間{{$labels.namespace}}({{$labels.instance}}): 發現{{$labels.pod}}下的{{$labels.container}}啟動異常等待中"value: "{{ $value }}"threshold: "1"- alert: Pod_terminatedexpr: kube_pod_container_status_terminated_reason{namespace=~"kube-system|default|monitor-sa"} == 1for: 2slabels:team: adminannotations:description: "空間{{$labels.namespace}}({{$labels.instance}}): 發現{{$labels.pod}}下的{{$labels.container}}被刪除"value: "{{ $value }}"threshold: "1"- alert: Etcd_leaderexpr: etcd_server_has_leader{job="kubernetes-etcd"} == 0for: 2slabels:team: adminannotations:description: "組件{{$labels.job}}({{$labels.instance}}): 當前沒有leader"value: "{{ $value }}"threshold: "0"- alert: Etcd_leader_changesexpr: rate(etcd_server_leader_changes_seen_total{job="kubernetes-etcd"}[1m]) > 0for: 2slabels:team: adminannotations:description: "組件{{$labels.job}}({{$labels.instance}}): 當前leader已發生改變"value: "{{ $value }}"threshold: "0"- alert: Etcd_failedexpr: rate(etcd_server_proposals_failed_total{job="kubernetes-etcd"}[1m]) > 0for: 2slabels:team: adminannotations:description: "組件{{$labels.job}}({{$labels.instance}}): 服務失敗"value: "{{ $value }}"threshold: "0"- alert: Etcd_db_total_sizeexpr: etcd_debugging_mvcc_db_total_size_in_bytes{job="kubernetes-etcd"} > 10000000000for: 2slabels:team: adminannotations:description: "組件{{$labels.job}}({{$labels.instance}}):db空間超過10G"value: "{{ $value }}"threshold: "10G"- alert: Endpoint_readyexpr: kube_endpoint_address_not_ready{namespace=~"kube-system|default"} == 1for: 2slabels:team: adminannotations:description: "空間{{$labels.namespace}}({{$labels.instance}}): 發現{{$labels.endpoint}}不可用"value: "{{ $value }}"threshold: "1"- name: 物理節點狀態-監控告警rules:- alert: 物理節點cpu使用率expr: 100-avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by(instance)*100 > 90for: 2slabels:severity: ccriticalannotations:summary: "{{ $labels.instance }}cpu使用率過高"description: "{{ $labels.instance }}的cpu使用率超過90%,當前使用率[{{ $value }}],需要排查處理"- alert: 物理節點內存使用率expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 90for: 2slabels:severity: criticalannotations:summary: "{{ $labels.instance }}內存使用率過高"description: "{{ $labels.instance }}的內存使用率超過90%,當前使用率[{{ $value }}],需要排查處理"- alert: InstanceDownexpr: up == 0for: 2slabels:severity: criticalannotations:summary: "{{ $labels.instance }}: 服務器宕機"description: "{{ $labels.instance }}: 服務器延時超過2分鐘"- alert: 物理節點磁盤的IO性能expr: 100-(avg(irate(node_disk_io_time_seconds_total[1m])) by(instance)* 100) < 60for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 流入磁盤IO使用率過高!"description: "{{$labels.mountpoint }} 流入磁盤IO大于60%(目前使用:{{$value}})"- alert: 入網流量帶寬expr: ((sum(rate (node_network_receive_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*'}[5m])) by (instance)) / 100) > 102400for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 流入網絡帶寬過高!"description: "{{$labels.mountpoint }}流入網絡帶寬持續5分鐘高于100M. RX帶寬使用率{{$value}}"- alert: 出網流量帶寬expr: ((sum(rate (node_network_transmit_bytes_total{device!~'tap.*|veth.*|br.*|docker.*|virbr*|lo*'}[5m])) by (instance)) / 100) > 102400for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 流出網絡帶寬過高!"description: "{{$labels.mountpoint }}流出網絡帶寬持續5分鐘高于100M. RX帶寬使用率{{$value}}"- alert: TCP會話expr: node_netstat_Tcp_CurrEstab > 1000for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} TCP_ESTABLISHED過高!"description: "{{$labels.mountpoint }} TCP_ESTABLISHED大于1000%(目前使用:{{$value}}%)"- alert: 磁盤容量expr: 100-(node_filesystem_free_bytes{fstype=~"ext4|xfs"}/node_filesystem_size_bytes {fstype=~"ext4|xfs"}*100) > 80for: 2slabels:severity: criticalannotations:summary: "{{$labels.mountpoint}} 磁盤分區使用率過高!"description: "{{$labels.mountpoint }} 磁盤分區使用大于80%(目前使用:{{$value}}%)"
[root@wentaomaster1 ~]# kubectl apply -f prometheus-alertmanager-cfg.yaml
[root@wentaomaster1 ~]# cat prometheus-alertmanager-deploy.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:name: prometheus-servernamespace: monitor-salabels:app: prometheus
spec:replicas: 2selector:matchLabels:app: prometheuscomponent: server#matchExpressions:#- {key: app, operator: In, values: [prometheus]}#- {key: component, operator: In, values: [server]}template:metadata:labels:app: prometheuscomponent: serverannotations:prometheus.io/scrape: 'false'spec:serviceAccountName: monitorcontainers:- name: prometheusimage: prom/prometheus:v2.2.1imagePullPolicy: IfNotPresentcommand:- "/bin/prometheus"args:- "--config.file=/etc/prometheus/prometheus.yml"- "--storage.tsdb.path=/prometheus"- "--storage.tsdb.retention=24h"- "--web.enable-lifecycle"ports:- containerPort: 9090protocol: TCPvolumeMounts:- mountPath: /etc/prometheusname: prometheus-config- mountPath: /prometheus/name: prometheus-storage-volume- name: k8s-certsmountPath: /var/run/secrets/kubernetes.io/k8s-certs/etcd/- name: alertmanagerimage: prom/alertmanager:v0.14.0imagePullPolicy: IfNotPresentargs:- "--config.file=/etc/alertmanager/alertmanager.yml"- "--log.level=debug"ports:- containerPort: 9093protocol: TCPname: alertmanagervolumeMounts:- name: alertmanager-configmountPath: /etc/alertmanager- name: alertmanager-storagemountPath: /alertmanager- name: localtimemountPath: /etc/localtimevolumes:- name: prometheus-configconfigMap:name: prometheus-config- name: prometheus-storage-volumehostPath:path: /datatype: Directory- name: k8s-certssecret:secretName: etcd-certs- name: alertmanager-configconfigMap:name: alertmanager- name: alertmanager-storagehostPath:path: /data/alertmanagertype: DirectoryOrCreate- name: localtimehostPath:path: /usr/share/zoneinfo/Asia/Shanghai
[root@wentaomaster1 ~]# kubectl apply -f prometheus-alertmanager-deploy.yaml
#查看prometheus是否部署成功
[root@wentaomaster1 ~]# kubectl get pod -n monitor-sa -owide
#顯示如下,說明創建成功:
#部署alertmanager的service,方便在瀏覽器訪問
#在k8s的控制節點生成一個alertmanager-svc.yaml文件
[root@wentaomaster1 ~]# cat alertmanager-svc.yaml
---
apiVersion: v1
kind: Service
metadata:labels:name: prometheuskubernetes.io/cluster-service: 'true'name: alertmanagernamespace: monitor-sa
spec:ports:- name: alertmanagernodePort: 30066port: 9093protocol: TCPtargetPort: 9093selector:app: prometheussessionAffinity: Nonetype: NodePort
通過kubectl apply更新yaml文件
[root@wentaomaster1 ~]# kubectl apply -f alertmanager-svc.yaml
#查看service在物理機映射的端口
[root@wentaomaster1 ~]# kubectl get svc -n monitor-sa
可以看到alertmanager的service在物理機映射的端口是30066
訪問http://192.168.184.10:30066/#/alerts
訪問prometheus的web界面,可看到:
點擊Alerts:
把Pod_restarts展開,可看到如下:
可以看到QQ郵箱已經一大堆報警了哈哈哈
擴展:暴力更新配置文件修改prometheus任何一個配置文件之后,可通過kubectl apply使配置生效,執行順序如下:kubectl delete -f alertmanager-cm.yamlkubectl apply -f alertmanager-cm.yamlkubectl delete -f prometheus-alertmanager-cfg.yamlkubectl apply -f prometheus-alertmanager-cfg.yaml kubectl delete -f prometheus-alertmanager-deploy.yaml
kubectl apply -f prometheus-alertmanager-deploy.yaml