目錄:java
說在前面的話,如今監控首選的話,確定是Prometheus+Grafana,也就是不少大型公司也都在用,像RBM,360,網易,基本都是使用這一套監控系統。
node
1、Prometheus 是什麼?
Prometheus(普羅米修斯)是一個最初在SoundCloud上構建的監控系統。SoundCloud是搞雲計算的一家國外的公司,也是由一個谷歌的一位工程師來到這家公司以後開發的這個系統,自2012年成爲社區開源項目,擁有很是活躍的開發人員和用戶社區。爲強調開源及獨立維護,Prometheus於2016年加入雲原生雲計算基金會
(CNCF),成爲繼Kubernetes以後的第二個託管項目,這個項目發展的仍是比較快的,隨着k8s的發展,它也起來了。
https://prometheus.io 官方網站
https://github.com/prometheus GitHub地址python
Prometheus組成及架構
接下來看一下它這個官方給出的架構圖,咱們來研究一下
最左邊這塊就是採集的,採集誰監控誰,通常是一些短週期的任務,好比cronjob這樣的任務,也能夠是一些持久性的任務,其實主要就是一些持久性的任務,好比web服務,也就是持續運行的,暴露一些指標,像短時間任務呢,處理一下就關了,分爲這兩個類型,短時間任務會用到Pushgateway,專門收集這些短時間任務的。mysql
中間這塊就是Prometheus它自己,內部是有一個TSDB的數據庫的,從內部的採集和展現Prometheus它均可以完成,展現這塊本身的這塊UI比較lou,因此藉助於這個開源的Grafana來展現,全部的被監控端暴露完指標以後,Prometheus會主動的抓取這些指標,存儲到本身TSDB數據庫裏面,提供給Web UI,或者Grafana,或者API clients經過PromQL來調用這些數據,PromQL至關於Mysql的SQL,主要是查詢這些數據的。linux
中間上面這塊是作服務發現的,也就是你有不少的被監控端時,手動的去寫這些被監控端是不現實的,因此須要自動的去發現新加入的節點,或者以批量的節點,加入到這個監控中,像k8s它內置了k8s服務發現的機制,也就是它會鏈接k8s的API,去發現你部署的哪些應用,哪些pod,統統的都給你暴露出去,監控出來,也就是爲何K8S對prometheus特別友好的地方,也就是它內置了作這種相關的支持了。git
右上角是Prometheus的告警,它告警實現是有一個組件的,Alertmanager,這個組件是接收prometheus發來的告警就是觸發了一些預值,會通知Alertmanager,而Alertmanager來處理告警相關的處理,而後發送給接收人,能夠是email,也能夠是企業微信,或者釘釘,也就是它整個的這個框架,分爲這5塊。github
小結:
• Prometheus Server:收集指標和存儲時間序列數據,並提供查詢接口
• ClientLibrary:客戶端庫,這些能夠集成一些不少的語言中,好比使用JAVA開發的一個Web網站,那麼能夠集成JAVA的客戶端,去暴露相關的指標,暴露自身的指標,但不少的業務指標須要開發去寫的,
• Push Gateway:短時間存儲指標數據。主要用於臨時性的任務
• Exporters:採集已有的第三方服務監控指標並暴露metrics,至關於一個採集端的agent,
• Alertmanager:告警
• Web UI:簡單的Web控制檯web
數據模型
Prometheus將全部數據存儲爲時間序列;具備相同度量名稱以及標籤屬於同一個指標。
每一個時間序列都由度量標準名稱和一組鍵值對(也成爲標籤)惟一標識。 也就是查詢時
也會依據這些標籤來查詢和過濾,就是寫PromQL時
時間序列格式:
<metric name>{<label name>=<label value>, ...}
指標的名字+花括號裏面有不少的值sql
示例:api_http_requests_total{method="POST", handler="/messages"}
( 名稱 )(裏面包含的POST請求,GET請求,請求裏面還包含了請求的資源,好比messages或者API)裏面能夠還有不少的指標,好比請求的協議,或者攜帶了其餘HTTP頭的字段,均可以進行標記出來,就是想監控的均可以經過這種方式監控出來。docker
做業和實例
實例:能夠抓取的目標稱爲實例(Instances),用過zabbix的都知道被監控端是稱爲何,通常就是稱爲主機,被監控端,而在prometheus稱爲一個實例。
做業:具備相同目標的實例集合稱爲做業(Job),也就是將你的被監控端做爲你個集合,好比作一個分組,web 服務有幾臺,好比有3臺,寫一個job下,這個job下就是3臺,就是作一個邏輯上的分組,
2、K8S監控指標
Kubernetes自己監控
• Node資源利用率 :通常生產環境幾十個node,幾百個node去監控
• Node數量 :通常能監控到node,就能監控到它的數量了,由於它是一個實例,一個node能跑多少個項目,也是須要去評估的,總體資源率在一個什麼樣的狀態,什麼樣的值,因此須要根據項目,跑的資源利用率,還有值作一個評估的,好比再跑一個項目,須要多少資源。
• Pods數量(Node):其實也是同樣的,每一個node上都跑多少pod,不過默認一個node上能跑110個pod,但大多數狀況下不可能跑這麼多,好比一個128G的內存,32核cpu,一個java的項目,一個分配2G,也就是能跑50-60個,通常機器,pod也就跑幾十個,不多不多超過100個。
• 資源對象狀態 :好比pod,service,deployment,job這些資源狀態,作一個統計。
Pod監控
• Pod數量(項目):你的項目跑了多少個pod的數量,大概的利益率是多少,好評估一下這個項目跑了多少個資源佔有多少資源,每一個pod佔了多少資源。
• 容器資源利用率 :每一個容器消耗了多少資源,用了多少CPU,用了多少內存
• 應用程序:這個就是偏應用程序自己的指標了,這個通常在咱們運維很難拿到的,因此在監控以前呢,須要開發去給你暴露出來,這裏有不少客戶端的集成,客戶端庫就是支持不少語言的,須要讓開發作一些開發量將它集成進去,暴露這個應用程序的想知道的指標,而後歸入監控,若是開發部配合,基本運維很難作到這一塊,除非本身寫一個客戶端程序,經過shell/python能不能從外部獲取內部的工做狀況,若是這個程序提供API的話,這個很容易作到。
Prometheus監控K8S架構
若是想監控node的資源,就能夠放一個node_exporter,這是監控node資源的,node_exporter是Linux上的採集器,你放上去你就能採集到當前節點的CPU、內存、網絡IO,等待均可以採集的。
若是想監控容器,k8s內部提供cAdvisor採集器,pod呀,容器均可以採集到這些指標,都是內置的,不須要單獨部署,只知道怎麼去訪問這個Cadvisor就能夠了。
若是想監控k8s資源對象,會部署一個kube-state-metrics這個服務,它會定時的API中獲取到這些指標,幫你存取到Prometheus裏,要是告警的話,經過Alertmanager發送給一些接收方,經過Grafana可視化展現。
服務發現:
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#kubernetes_sd_config
3、在K8S中部署Prometheus+Grafana
yaml文件地址:
https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/prometheus
https://grafana.com/grafana/download
這裏我已經當下來了,並作了一些修改
[root@k8s-master prometheus-k8s]# ls alertmanager-configmap.yaml OWNERS alertmanager-deployment.yaml prometheus-configmap.yaml alertmanager-pvc.yaml prometheus-rbac.yaml alertmanager-service.yaml prometheus-rules.yaml grafana.yaml prometheus-service.yaml kube-state-metrics-deployment.yaml prometheus-statefulset-static-pv.yaml kube-state-metrics-rbac.yaml prometheus-statefulset.yaml kube-state-metrics-service.yaml README.md node_exporter.sh
如今先來建立rbac,由於部署它的主服務主進程要引用這幾個服務
由於prometheus來鏈接你的API,從API中獲取不少的指標
而且設置了綁定集羣角色的權限,只能查看,不能修改
[root@k8s-master prometheus-k8s]# cat prometheus-rbac.yaml apiVersion: v1 kind: ServiceAccount metadata: name: prometheus namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: prometheus labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - "" resources: - nodes - nodes/metrics - services - endpoints - pods verbs: - get - list - watch - apiGroups: - "" resources: - configmaps verbs: - get - nonResourceURLs: - "/metrics" verbs: - get --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: prometheus labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus subjects: - kind: ServiceAccount name: prometheus namespace: kube-system [root@k8s-master prometheus-k8s]# kubectl create -f prometheus-rbac.yaml
如今建立一下configmap,
rule_files: - /etc/config/rules/*.rules
這是寫入告警規則的目錄,也就是這個configmap會掛載到普羅米修斯里面,讓主進程讀取這些配置
scrape_configs: - job_name: prometheus static_configs: - targets: - localhost:9090
下面這些都是來配置監控端的,job_name是分組,這是是監控它自己,下面還有監控node,咱們會在node上起一個nodeport,這裏修改要監控node節點
scrape_interval: 30s:這裏採集的時間,每多少秒採集一次數據 這裏還有一個alerting的服務的名字 alerting: alertmanagers: - static_configs: - targets: ["alertmanager:80"]
[root@k8s-master prometheus-k8s]# kubectl create -f prometheus-configmap.yaml [root@k8s-master prometheus-k8s]# cat prometheus-configmap.yaml # Prometheus configuration format https://prometheus.io/docs/prometheus/latest/configuration/configuration/ apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: EnsureExists data: prometheus.yml: | rule_files: - /etc/config/rules/*.rules scrape_configs: - job_name: prometheus static_configs: - targets: - localhost:9090 - job_name: kubernetes-nodes scrape_interval: 30s static_configs: - targets: - 192.168.30.22:9100 - 192.168.30.23:9100 - job_name: kubernetes-apiservers kubernetes_sd_configs: - role: endpoints relabel_configs: - action: keep regex: default;kubernetes;https source_labels: - __meta_kubernetes_namespace - __meta_kubernetes_service_name - __meta_kubernetes_endpoint_port_name scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - job_name: kubernetes-nodes-kubelet kubernetes_sd_configs: - role: node relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - job_name: kubernetes-nodes-cadvisor kubernetes_sd_configs: - role: node relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) - target_label: __metrics_path__ replacement: /metrics/cadvisor scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt insecure_skip_verify: true bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - job_name: kubernetes-service-endpoints kubernetes_sd_configs: - role: endpoints relabel_configs: - action: keep regex: true source_labels: - __meta_kubernetes_service_annotation_prometheus_io_scrape - action: replace regex: (https?) source_labels: - __meta_kubernetes_service_annotation_prometheus_io_scheme target_label: __scheme__ - action: replace regex: (.+) source_labels: - __meta_kubernetes_service_annotation_prometheus_io_path target_label: __metrics_path__ - action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 source_labels: - __address__ - __meta_kubernetes_service_annotation_prometheus_io_port target_label: __address__ - action: labelmap regex: __meta_kubernetes_service_label_(.+) - action: replace source_labels: - __meta_kubernetes_namespace target_label: kubernetes_namespace - action: replace source_labels: - __meta_kubernetes_service_name target_label: kubernetes_name - job_name: kubernetes-services kubernetes_sd_configs: - role: service metrics_path: /probe params: module: - http_2xx relabel_configs: - action: keep regex: true source_labels: - __meta_kubernetes_service_annotation_prometheus_io_probe - source_labels: - __address__ target_label: __param_target - replacement: blackbox target_label: __address__ - source_labels: - __param_target target_label: instance - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: - __meta_kubernetes_namespace target_label: kubernetes_namespace - source_labels: - __meta_kubernetes_service_name target_label: kubernetes_name - job_name: kubernetes-pods kubernetes_sd_configs: - role: pod relabel_configs: - action: keep regex: true source_labels: - __meta_kubernetes_pod_annotation_prometheus_io_scrape - action: replace regex: (.+) source_labels: - __meta_kubernetes_pod_annotation_prometheus_io_path target_label: __metrics_path__ - action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 source_labels: - __address__ - __meta_kubernetes_pod_annotation_prometheus_io_port target_label: __address__ - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - action: replace source_labels: - __meta_kubernetes_namespace target_label: kubernetes_namespace - action: replace source_labels: - __meta_kubernetes_pod_name target_label: kubernetes_pod_name alerting: alertmanagers: - static_configs: - targets: ["alertmanager:80"]
再配置這個角色,這個就是配置告警規則的,這裏分爲兩塊告警規則,一個是通用的告警規則,適用全部的實例,若是實例要是掛了,而後發送告警,實例咱們被監控端的agent,還有一個node角色,這個監控每一個node的CPU、內存、磁盤利用率,在prometheus寫告警值是經過promQL去寫的,來查詢一個數據來比對,若是符合這個比對的表達式,就是爲真的狀況下,去觸發當前這條告警,好比就是下面這條,而後會將這條告警推送給alertmanager,它來處理這個信息的告警。expr: 100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100 > 80
[root@k8s-master prometheus-k8s]# kubectl create -f prometheus-rules.yaml [root@k8s-master prometheus-k8s]# cat prometheus-rules.yaml apiVersion: v1 kind: ConfigMap metadata: name: prometheus-rules namespace: kube-system data: general.rules: | groups: - name: general.rules rules: - alert: InstanceDown expr: up == 0 for: 1m labels: severity: error annotations: summary: "Instance {{ $labels.instance }} 中止工做" description: "{{ $labels.instance }} job {{ $labels.job }} 已經中止5分鐘以上." node.rules: | groups: - name: node.rules rules: - alert: NodeFilesystemUsage expr: 100 - (node_filesystem_free_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"} * 100) > 80 for: 1m labels: severity: warning annotations: summary: "Instance {{ $labels.instance }} : {{ $labels.mountpoint }} 分區使用率太高" description: "{{ $labels.instance }}: {{ $labels.mountpoint }} 分區使用大於80% (當前值: {{ $value }})" - alert: NodeMemoryUsage expr: 100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100 > 80 for: 1m labels: severity: warning annotations: summary: "Instance {{ $labels.instance }} 內存使用率太高" description: "{{ $labels.instance }}內存使用大於80% (當前值: {{ $value }})" - alert: NodeCPUUsage expr: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100) > 60 for: 1m labels: severity: warning annotations: summary: "Instance {{ $labels.instance }} CPU使用率太高" description: "{{ $labels.instance }}CPU使用大於60% (當前值: {{ $value }})"
而後再部署一下statefulset
[root@k8s-master prometheus-k8s]# cat prometheus-statefulset.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: prometheus namespace: kube-system labels: k8s-app: prometheus kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile version: v2.2.1 spec: serviceName: "prometheus" replicas: 1 podManagementPolicy: "Parallel" updateStrategy: type: "RollingUpdate" selector: matchLabels: k8s-app: prometheus template: metadata: labels: k8s-app: prometheus annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: priorityClassName: system-cluster-critical serviceAccountName: prometheus initContainers: - name: "init-chown-data" image: "busybox:latest" imagePullPolicy: "IfNotPresent" command: ["chown", "-R", "65534:65534", "/data"] volumeMounts: - name: prometheus-data mountPath: /data subPath: "" containers: - name: prometheus-server-configmap-reload image: "jimmidyson/configmap-reload:v0.1" imagePullPolicy: "IfNotPresent" args: - --volume-dir=/etc/config - --webhook-url=http://localhost:9090/-/reload volumeMounts: - name: config-volume mountPath: /etc/config readOnly: true resources: limits: cpu: 10m memory: 10Mi requests: cpu: 10m memory: 10Mi - name: prometheus-server image: "prom/prometheus:v2.2.1" imagePullPolicy: "IfNotPresent" args: - --config.file=/etc/config/prometheus.yml - --storage.tsdb.path=/data - --web.console.libraries=/etc/prometheus/console_libraries - --web.console.templates=/etc/prometheus/consoles - --web.enable-lifecycle ports: - containerPort: 9090 readinessProbe: httpGet: path: /-/ready port: 9090 initialDelaySeconds: 30 timeoutSeconds: 30 livenessProbe: httpGet: path: /-/healthy port: 9090 initialDelaySeconds: 30 timeoutSeconds: 30 # based on 10 running nodes with 30 pods each resources: limits: cpu: 200m memory: 1000Mi requests: cpu: 200m memory: 1000Mi volumeMounts: - name: config-volume mountPath: /etc/config - name: prometheus-data mountPath: /data subPath: "" - name: prometheus-rules mountPath: /etc/config/rules terminationGracePeriodSeconds: 300 volumes: - name: config-volume configMap: name: prometheus-config - name: prometheus-rules configMap: name: prometheus-rules volumeClaimTemplates: - metadata: name: prometheus-data spec: storageClassName: managed-nfs-storage accessModes: - ReadWriteOnce resources: requests: storage: "16Gi"
這裏呢由於我以前就把nfs動態建立pvc的搭建好了,使用的nfs作的網絡存儲,因此這裏沒有演示,能夠看我以前的博客,而後這裏已經建立好了
[root@k8s-master prometheus-k8s]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE coredns-bccdc95cf-kqxwv 1/1 Running 3 2d4h coredns-bccdc95cf-nwkbp 1/1 Running 3 2d4h etcd-k8s-master 1/1 Running 2 2d4h kube-apiserver-k8s-master 1/1 Running 2 2d4h kube-controller-manager-k8s-master 1/1 Running 5 2d4h kube-flannel-ds-amd64-dc5z9 1/1 Running 1 2d4h kube-flannel-ds-amd64-jm2jz 1/1 Running 1 2d4h kube-flannel-ds-amd64-z6tt2 1/1 Running 1 2d4h kube-proxy-9ltx7 1/1 Running 2 2d4h kube-proxy-lnzrj 1/1 Running 1 2d4h kube-proxy-v7dqm 1/1 Running 1 2d4h kube-scheduler-k8s-master 1/1 Running 5 2d4h prometheus-0 2/2 Running 0 3m3s
而後看一下service,咱們使用Nodeport類型,端口使用9090。固然也可使用ingress暴露出去
[root@k8s-master prometheus-k8s]# cat prometheus-service.yaml kind: Service apiVersion: v1 metadata: name: prometheus namespace: kube-system labels: kubernetes.io/name: "Prometheus" kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: type: NodePort ports: - name: http port: 9090 protocol: TCP targetPort: 9090 selector: k8s-app: prometheus
如今能夠去訪問一下了,訪問隨機端口32276,咱們的prometheus已經部署成功
[root@k8s-master prometheus-k8s]# kubectl create -f prometheus-service.yaml [root@k8s-master prometheus-k8s]# kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.1.0.10 <none> 53/UDP,53/TCP,9153/TCP 2d4h prometheus NodePort 10.1.58.1 <none> 9090:32276/TCP 22s
一個很是簡潔的UI頁面,沒有什麼好的功能,很難知足企業UI的要求的,不過只在這裏作一個調試,上面主要寫promQL的表達式的,怎麼去查這個數據,就比如mysql的SQL,去查詢出你的數據,能夠在status裏面去進行調試,而裏面的config配置文件咱們增長了告警預值,增長了對nodeport的支持還有指定了alertmanager的地址,而後rules,咱們也是規劃了兩塊,一個是通用規則,一個是node節點規則,主要監控三大塊,內存、磁盤、CPU
如今查看CPU的利用率,通常都是使用Grafana去展現
5、在K8S平臺部署Grafana
這裏也是用statefulset去作的,也是自動建立pv,定義的端口是30007
[root@k8s-master prometheus-k8s]# cat grafana.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: grafana namespace: kube-system spec: serviceName: "grafana" replicas: 1 selector: matchLabels: app: grafana template: metadata: labels: app: grafana spec: containers: - name: grafana image: grafana/grafana ports: - containerPort: 3000 protocol: TCP resources: limits: cpu: 100m memory: 256Mi requests: cpu: 100m memory: 256Mi volumeMounts: - name: grafana-data mountPath: /var/lib/grafana subPath: grafana securityContext: fsGroup: 472 runAsUser: 472 volumeClaimTemplates: - metadata: name: grafana-data spec: storageClassName: managed-nfs-storage accessModes: - ReadWriteOnce resources: requests: storage: "1Gi" --- apiVersion: v1 kind: Service metadata: name: grafana namespace: kube-system spec: type: NodePort ports: - port : 80 targetPort: 3000 nodePort: 30007 selector: app: grafana
默認帳號密碼都是admin
首先咱們將prometheus作爲數據源,添加一個數據源並選擇prometheus
添加一個URL地址,能夠寫你訪問UI頁面的地址也能夠寫service的地址
[root@k8s-master prometheus-k8s]# kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE grafana NodePort 10.1.246.143 <none> 80:30007/TCP 11m kube-dns ClusterIP 10.1.0.10 <none> 53/UDP,53/TCP,9153/TCP 2d5h prometheus NodePort 10.1.58.1 <none> 9090:32276/TCP 40m
查看數據源已經有一個了
6、監控K8S集羣中Pod、Node、資源對象
Pod
kubelet的節點使用cAdvisor提供的metrics接口獲取該節點全部Pod和容器相關的性能指標數據。
也就是kubelet會暴露兩個接口地址:
https://NodeIP:10255/metrics/cadvisor 只讀
https://NodeIP:10250/metrics/cadvisor kubelet的API,受權沒問題的話能夠作任何操做
能夠在node節點去看一下,這個端口主要用做於訪問kubelet的一些API鑑權,和提供一些cAdvisor指標用的,我們部署prometheus的時候,就已經開始收集cAdvisor數據了,爲何會採集,由於prometheus配置文件就已經去定義怎麼去採集數據了
[root@k8s-node1 ~]# netstat -antp |grep 10250 tcp6 0 0 :::10250 :::* LISTEN 107557/kubelet tcp6 0 0 192.168.30.22:10250 192.168.30.23:58692 ESTABLISHED 107557/kubelet tcp6 0 0 192.168.30.22:10250 192.168.30.23:46555 ESTABLISHED 107557/kubelet
Node
使用node_exporter收集器採集節點資源利用率。
https://github.com/prometheus/node_exporter
使用文檔:https://prometheus.io/docs/guides/node-exporter/
資源對象
kube-state-metrics採集了k8s中各類資源對象的狀態信息,
https://github.com/kubernetes/kube-state-metrics
如今導入一個可以查看pod數據的模版,也就是經過模版更能直觀去展現這些數據
7、使用Grafana可視化展現Prometheus監控數據
推薦模板: 也就是在grafana共享中內心面的,也就是別人寫的模版上傳到這裏庫裏面的,本身也能夠寫,寫完上傳上去,別人也能夠訪問到,下面是模版的id,只要獲取這個ID,就能使用這個模版了,只要這個模版,後端提供執行promeQL,只要有數據就能幫你展現出來
Grafana.com
• 集羣資源監控:3119
• 資源狀態監控 :6417
• Node監控 :9276
如今使用這個3319模版,來展現咱們的集羣的資源,打開添加模版,選擇dashboard
選擇導入模版
寫入3119,它能自動幫你識別這個模版的名字
由於這些都有數據了,因此就直接能查看到全部集羣的資源
下面這個是網絡IO的圖表,一個是接收,一個是發送
下面這個是集羣內存的使用狀況
這裏是4G,只識別了3.84G,使用2.26G,CPU是雙核,使用了0.11,右邊這個是集羣文件系統,可是沒有顯示出來,咱們能夠看一下它PromQL怎麼寫的,把這個寫promQL拿到promQL Ui上測試一下有沒有數據,通常是沒有匹配到數據致使的
來看一下這個怎麼解決
拿這個數據去比對,找到數據,一點一點去刪除,如今咱們找到數據了,這裏是匹配的你節點的名稱,根據這個咱們去找,由於這個模版是別人上傳的,咱們本身用確定根據本身的內容去匹配,這裏能夠去匹配相關的promQL,而後改一下咱們grafana的promQL,如今是獲取到數據了
另外咱們可能還作一些其餘的模版的監控,能夠在它Grafana的官方去找一些模版,可是有的可能不能用,本身須要去修改,好比輸入k8s,這裏是監控etcd集羣的
Node
使用node_exporter收集器採集節點資源利用率。
https://github.com/prometheus/node_exporter
使用文檔:https://prometheus.io/docs/guides/node-exporter/
這個目前沒有使用pod去部署,由於沒有展現到一個磁盤的使用率,官方給出了一個statfulset的方式,沒法展現磁盤,不過也能夠以一個守護進程的方式部署在node 節點上,這個部署也比較簡單,以二進制的方式去部署,在宿主機上啓動一個就能夠了
看一下這個腳本,是以systemd去過濾服務啓動監控的狀態,若是守護進程掛了話,也會被Prometheus採集到也就是下面這個參數--collector.systemd --collector.systemd.unit-whitelist=(docker|kubelet|kube-proxy|flanneld).service
[root@k8s-node1 ~]# bash node_exporter.sh #!/bin/bash wget https://github.com/prometheus/node_exporter/releases/download/v0.17.0/node_exporter-0.17.0.linux-amd64.tar.gz tar zxf node_exporter-0.17.0.linux-amd64.tar.gz mv node_exporter-0.17.0.linux-amd64 /usr/local/node_exporter cat <<EOF >/usr/lib/systemd/system/node_exporter.service [Unit] Description=https://prometheus.io [Service] Restart=on-failure ExecStart=/usr/local/node_exporter/node_exporter --collector.systemd --collector.systemd.unit-whitelist=(docker|kubelet|kube-proxy|flanneld).service [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable node_exporter systemctl restart node_exporter
prometheus是主動的去採集資源的指標,而不是被動的被監控端推送這些數據
而後使用的是9276這個模版,咱們能夠先讓這個模版導入進來
[root@k8s-node1 ~]# ps -ef |grep node_ex root 5275 1 0 21:59 ? 00:00:03 /usr/local/node_exporter/node_exporter --collector.systemd --collector.systemd.unit-whitelist=(docker|kubelet|kube-proxy|flanneld).service root 7393 81364 0 22:15 pts/1 00:00:00 grep --color=auto node_ex
選擇nodes ,這裏能夠看到兩個節點的資源狀態
獲取網絡帶寬失敗,而後咱們能夠去測這個promeQL,通常這個狀況就是查看網卡的接口名稱,有的是eth0,有的是ens32,ens33,這個根據本身的去寫
點擊這個保存
如今就有了
K8s資源對象的監控
具體實現 kube-state-metrics ,這種類型pod/deployment/service
這個組件是官方開發的,經過API去獲取k8s資源的狀態,經過metrics來完成數據的採集。好比副本數是多少,當前是什麼狀態了,是獲取這些的
固然github上都有這些,只須要把國外的源換成國外的就能夠了,或者換成個人,我已經把鏡像上傳到docker hub上了。
https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/prometheus
建立rbac受權規則
[root@k8s-master prometheus-k8s]# cat kube-state-metrics-rbac.yaml apiVersion: v1 kind: ServiceAccount metadata: name: kube-state-metrics namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: kube-state-metrics labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: [""] resources: - configmaps - secrets - 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: Role metadata: name: kube-state-metrics-resizer namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: [""] resources: - pods verbs: ["get"] - apiGroups: ["extensions"] resources: - deployments resourceNames: ["kube-state-metrics"] verbs: ["get", "update"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kube-state-metrics labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kube-state-metrics subjects: - kind: ServiceAccount name: kube-state-metrics namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: kube-state-metrics namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: kube-state-metrics-resizer subjects: - kind: ServiceAccount name: kube-state-metrics namespace: kube-system
建立deployment
[root@k8s-master prometheus-k8s]# cat kube-state-metrics-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: kube-state-metrics namespace: kube-system labels: k8s-app: kube-state-metrics kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile version: v1.3.0 spec: selector: matchLabels: k8s-app: kube-state-metrics version: v1.3.0 replicas: 1 template: metadata: labels: k8s-app: kube-state-metrics version: v1.3.0 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: priorityClassName: system-cluster-critical serviceAccountName: kube-state-metrics containers: - name: kube-state-metrics image: zhaocheng172/kube-state-metrics:v1.3.0 ports: - name: http-metrics containerPort: 8080 - name: telemetry containerPort: 8081 readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 timeoutSeconds: 5 - name: addon-resizer image: zhaocheng172/addon-resizer:1.8.3 resources: limits: cpu: 100m memory: 30Mi requests: cpu: 100m memory: 30Mi env: - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumeMounts: - name: config-volume mountPath: /etc/config command: - /pod_nanny - --config-dir=/etc/config - --container=kube-state-metrics - --cpu=100m - --extra-cpu=1m - --memory=100Mi - --extra-memory=2Mi - --threshold=5 - --deployment=kube-state-metrics volumes: - name: config-volume configMap: name: kube-state-metrics-config --- # Config map for resource configuration. apiVersion: v1 kind: ConfigMap metadata: name: kube-state-metrics-config namespace: kube-system labels: k8s-app: kube-state-metrics kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile data: NannyConfiguration: |- apiVersion: nannyconfig/v1alpha1 kind: NannyConfiguration
建立暴露的端口,這裏使用的是service
[root@k8s-master prometheus-k8s]# cat kube-state-metrics-service.yaml apiVersion: v1 kind: Service metadata: name: kube-state-metrics namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "kube-state-metrics" annotations: prometheus.io/scrape: 'true' spec: ports: - name: http-metrics port: 8080 targetPort: http-metrics protocol: TCP - name: telemetry port: 8081 targetPort: telemetry protocol: TCP selector: k8s-app: kube-state-metrics
部署成功以後,導入模版就能監控到咱們的數據
[root@k8s-master prometheus-k8s]# kubectl get pod,svc -n kube-system NAME READY STATUS RESTARTS AGE pod/coredns-bccdc95cf-kqxwv 1/1 Running 3 2d9h pod/coredns-bccdc95cf-nwkbp 1/1 Running 3 2d9h pod/etcd-k8s-master 1/1 Running 2 2d9h pod/grafana-0 1/1 Running 0 4h50m pod/kube-apiserver-k8s-master 1/1 Running 2 2d9h pod/kube-controller-manager-k8s-master 1/1 Running 5 2d9h pod/kube-flannel-ds-amd64-dc5z9 1/1 Running 1 2d9h pod/kube-flannel-ds-amd64-jm2jz 1/1 Running 1 2d9h pod/kube-flannel-ds-amd64-z6tt2 1/1 Running 1 2d9h pod/kube-proxy-9ltx7 1/1 Running 2 2d9h pod/kube-proxy-lnzrj 1/1 Running 1 2d9h pod/kube-proxy-v7dqm 1/1 Running 1 2d9h pod/kube-scheduler-k8s-master 1/1 Running 5 2d9h pod/kube-state-metrics-6474469878-6kpxv 1/2 Running 0 4s pod/kube-state-metrics-854b85d88-zl777 2/2 Running 0 35s pod/prometheus-0 2/2 Running 0 5h30m
仍是剛纔步驟同樣,導入一個6417的模版
數據如今已經展現出來了,它會從target裏面獲取到這些數據,也就是這個來提供的,由prometheus自動的發現了。它這個發現是根據裏面的一個註解來獲取的,也就是在service裏面
annotations:
prometheus.io/scrape: 'true'
也就是聲明瞭部署了哪些應用,能夠被prometheus去自動的發現,若是加這條規則,prometheus會自動把這些帶註解的監控到,也就是本身部署的應用,並提供相應的指標,也能自動發現這些狀態。
磁盤這裏須要更改一個由於這裏更新了,添加bytes
下面這裏是pod的容量,最大能夠建立的數量,也就是kubelet去限制的,總共一個節點能夠建立330個pod,已經分配24個。
小結:
因此有了這些監控,基本上就能瞭解k8s的基本資源的使用狀態了
8、告警規則與告警通知
在K8S中部署Alertmanager
說在前面的話,在k8s使用告警使用的是Alertmanager,先定義監控預值的規則,好比node的內存到達60%,才能告警,先定義好這些規則,若是prometheus採集的指標,匹配到這個規則,就是爲真的話,它會發送告警,會將這個個告警信息推送給 Alertmanager,Alertmanager通過一系列的處理,最終發送到告警人手上,能夠是webhook,email,釘釘,企業微信,目前咱們拿email來作如下實例,企業微信須要註冊企業的一些相關信息營業執照等,而webhook須要對接第三方的系統調一個接口去傳值,email默認都支持,prometheus原生是不支持釘釘的,若是想支持的話,須要找第三方,作這個數據轉換的組件。由於promethes傳入的數據,它與釘釘傳入的數據是不匹配的,全部有中間的程序數據之間進行轉換,如今也有開源的能夠去實現。
基本流程就行這樣的,咱們定義的規則都是在prometheus中
在K8S中部署Alertmanager
這裏是定義誰發送這個告警信息的,誰接收這個郵件
[root@k8s-master prometheus-k8s]# vim alertmanager-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: alertmanager-config namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: EnsureExists data: alertmanager.yml: | global: resolve_timeout: 5m smtp_smarthost: 'smtp.163.com:25' smtp_from: 'baojingtongzhi@163.com' smtp_auth_username: 'baojingtongzhi@163.com' smtp_auth_password: 'liang123' receivers: - name: default-receiver email_configs: - to: "17733661341@163.com" route: group_interval: 1m group_wait: 10s receiver: default-receiver repeat_interval: 1m
[root@k8s-master prometheus-k8s]# cat alertmanager-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: alertmanager namespace: kube-system labels: k8s-app: alertmanager kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile version: v0.14.0 spec: replicas: 1 selector: matchLabels: k8s-app: alertmanager version: v0.14.0 template: metadata: labels: k8s-app: alertmanager version: v0.14.0 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: priorityClassName: system-cluster-critical containers: - name: prometheus-alertmanager image: "prom/alertmanager:v0.14.0" imagePullPolicy: "IfNotPresent" args: - --config.file=/etc/config/alertmanager.yml - --storage.path=/data - --web.external-url=/ ports: - containerPort: 9093 readinessProbe: httpGet: path: /#/status port: 9093 initialDelaySeconds: 30 timeoutSeconds: 30 volumeMounts: - name: config-volume mountPath: /etc/config - name: storage-volume mountPath: "/data" subPath: "" resources: limits: cpu: 10m memory: 50Mi requests: cpu: 10m memory: 50Mi - name: prometheus-alertmanager-configmap-reload image: "jimmidyson/configmap-reload:v0.1" imagePullPolicy: "IfNotPresent" args: - --volume-dir=/etc/config - --webhook-url=http://localhost:9093/-/reload volumeMounts: - name: config-volume mountPath: /etc/config readOnly: true resources: limits: cpu: 10m memory: 10Mi requests: cpu: 10m memory: 10Mi volumes: - name: config-volume configMap: name: alertmanager-config - name: storage-volume persistentVolumeClaim: claimName: alertmanager 查看咱們的pvc這裏也是使用的咱們的自動供給managed-nfs-storage [root@k8s-master prometheus-k8s]# cat alertmanager-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: alertmanager namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: EnsureExists spec: storageClassName: managed-nfs-storage accessModes: - ReadWriteOnce resources: requests: storage: "2Gi"
這裏使用的是類型爲cluster IP
[root@k8s-master prometheus-k8s]# cat alertmanager-service.yaml apiVersion: v1 kind: Service metadata: name: alertmanager namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/name: "Alertmanager" spec: ports: - name: http port: 80 protocol: TCP targetPort: 9093 selector: k8s-app: alertmanager type: "ClusterIP"
而後把咱們的資源都建立好
[root@k8s-master prometheus-k8s]# kubectl create -f alertmanager-configmap.yaml [root@k8s-master prometheus-k8s]# kubectl create -f alertmanager-deployment.yaml [root@k8s-master prometheus-k8s]# kubectl create -f alertmanager-pvc.yaml [root@k8s-master prometheus-k8s]# kubectl create -f alertmanager-service.yaml [root@k8s-master prometheus-k8s]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE alertmanager-5d75d5688f-xw2qg 2/2 Running 0 66s coredns-bccdc95cf-kqxwv 1/1 Running 2 6d coredns-bccdc95cf-nwkbp 1/1 Running 2 6d etcd-k8s-master 1/1 Running 1 6d grafana-0 1/1 Running 0 14h kube-apiserver-k8s-master 1/1 Running 1 6d kube-controller-manager-k8s-master 1/1 Running 2 6d kube-flannel-ds-amd64-dc5z9 1/1 Running 1 5d23h kube-flannel-ds-amd64-jm2jz 1/1 Running 1 5d23h kube-flannel-ds-amd64-z6tt2 1/1 Running 1 6d kube-proxy-9ltx7 1/1 Running 2 6d kube-proxy-lnzrj 1/1 Running 1 5d23h kube-proxy-v7dqm 1/1 Running 1 5d23h kube-scheduler-k8s-master 1/1 Running 2 6d kube-state-metrics-6474469878-lkphv 2/2 Running 0 98m prometheus-0 2/2 Running 0 15h
而後也能夠在咱們的prometheus上看到咱們設置的告警規則
而後咱們測試一下咱們的告警,修改一下咱們的prometheus的rules
把node磁盤資源設置爲>20 就報警
[root@k8s-master prometheus-k8s]# vim prometheus-rules.yaml - alert: NodeFilesystemUsage expr: 100 - (node_filesystem_free_bytes{fstype=~"ext4|xfs"} / node_filesystem_size_bytes{fstype=~"ext4|xfs"} * 100) > 20
重建一下pod,這裏會自動啓動,查看prometheus,已經生效,另外上產環境都是去調用api,發送一個信號給rules,這裏我是重建的,也能夠找一些網上的其餘文章
[root@k8s-master prometheus-k8s]# kubectl delete pod prometheus-0 -n kube-system
查看Alerts,這裏會變顏色,等會會變成紅色,也就是alertmanager它是有一個處理的邏輯的,仍是比較複雜的,它會設計到一個靜默,就是告警收斂這一塊,還有一個分組,還有一個再次等待的的確認,全部不是一觸發就發送
粉紅色其實已經將告警推送給Alertmanager了,也就是這個狀態下才去發送這個告警信息