大家好,我是Linux運維工程師 Linke 。技術過硬,從不挖坑~
這篇文檔來記錄一下我新部署的監控軟體Prometheus ,grafana 和 alatermanager 放在下一篇文章中~~
記得剛剛上了 k8s 時,我還是用的老套筒式監控,當時不知道有prometheus這個東西,2017年的時候,prometheus大概還不為業内所用,是以不知道。。。好吧,這是我不知道的理由~
當時pod狀态、副本數等都是python寫的監控插件,因為當時主監控服務用的小米監控——open-falcon 。 open-falcon 總體還是不錯的,用的也可以,我個人感覺比zabbix 、 nagios 強多了,但是監控 k8s 就有些吃力了,大部分監控都要自己再開發。我也就這麼一直晃悠的用,維護起來很操蛋的。而且容器中跑java應用的話,jvm用小米的那套重量太大,是以幹脆我就不監控 jvm 了,pod 因為 OOM 挂了我就加記憶體。直到有一天,有個應用不管怎麼加都挂,于是就和同桌研究怎麼監控 JVM ,然後他看到有人用 prometheus 監控 k8s ,而且能拿到 jvm ,然後我們就研究使用這個。上線後,k8s 各名額監控完美抓取,媽媽再也不用擔心我的學習了。
下面開始進入部署環節,還是老樣子,不扯原理,無非就是資料從哪裡來,到哪裡去,沒啥好說的,用兩把就都知道了。
不監控 k8s 的話,感覺還是 open-falcon 使的友善,因為我到現在還沒時間看如何回調接口。也沒找到。自定義監控倒是研究明白了,因為 prometheus沒有端口監控,草不操蛋,然後我自己寫了個,看這個文檔:
https://blog.csdn.net/qq_31547771/article/details/103263288
本文介紹在 k8s 上部署 prometheus ,源碼安裝的俺也沒試過。
前提先要有個 kubernates 叢集,當然能撸到這篇文檔的同行們我相信早已擁有了自己的 k8s 叢集。沒有也沒關系,兄弟我提供一條龍服務,請看文檔:
https://blog.csdn.net/qq_31547771/article/details/100699573
伺服器劃分
k8s叢集角色 | ip | 排程 |
---|---|---|
master101 | 192.168.7.101 | 不跑業務應用 |
master102 | 192.168.7.102 | 不跑業務應用 |
master103 | 192.168.7.103 | 不跑業務應用 |
node104 | 192.168.7.104 | 排程 prometheus 到此節點,不跑其他應用 |
node105 | 192.168.7.105 | 跑其他業務應用 |
其餘節點都如 node105 ,跑業務應用
另外本例中還加入了一組 es 的監控
192.168.7.41
192.168.7.42
192.168.7.43
k8s操作節點配置prometheus的yaml檔案
我把用來操作 k8s 的系統叫做 k8s 操作節點,這裡我用的是 192.168.7.101 ,生産環境不建議使用 master 節點做操作節點,建議單獨弄一個系統,裝了 kubelet ,使用 k8s 的秘鑰檔案連接配接 k8s 。
下面所有的檔案都放在 /home/scripts/prometheus 路徑下
先編輯第一個主要檔案: configmap.yaml
這個檔案是 prometheus 主服務要使用的,監控規則、監控分組等都寫在這個檔案中了。
如果閑報警規則和監控組寫到一個檔案太多,可以把 rules.yaml 檔案移出去,加一個 rule_files: - “/etc/prometheus/prometheus.rules.yml” ,指定到一個檔案。但要記得挂載進去。本例中,我是寫到一起的、
cat > configmap.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitor
data:
#被引用到/etc/prometheus/prometheus.yml
prometheus.yml: |
global:
#每15s采集一次資料和15s做一次告警檢測
scrape_interval: 15s
evaluation_interval: 15s
#指定加載的告警規則檔案
rule_files:
- /etc/prometheus/rules.yml
#将報警送至何地進行報警
alerting:
alertmanagers:
- static_configs:
- targets: ["192.168.7.107:9093"]
#指定prometheus要監控的目标
scrape_configs:
- job_name: 'k8s-node'
scrape_interval: 10s
static_configs:
- targets:
- '192.168.7.101:31672'
- '192.168.7.102:31672'
- '192.168.7.103:31672'
- '192.168.7.104:31672'
- '192.168.7.105:31672'
- job_name: 'es-node'
scrape_interval: 10s
static_configs:
- targets:
- '192.168.7.41:31672'
- '192.168.7.42:31672'
- '192.168.7.43:31672'
#自定義擷取監控資料,每個 job_name 都是獨立的,以下的文法難的一逼,可能隻有老天爺知道
- job_name: 'tomcat-pods'
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape, __meta_kubernetes_service_annotation_prometheus_io_jvm_scrape]
regex: true;true
action: keep
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_app_metrics_patn]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__meta_kubernetes_pod_ip, __meta_kubernetes_service_annotation_prometheus_io_app_metrics_port]
action: replace
target_label: __address__
regex: (.+);(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_pod_host_ip]
action: replace
target_label: kubernetes_host_ip
- job_name: 'kubernetes-apiservers'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- action: labelmap
regex: __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
- job_name: 'kubernetes-cadvisor'
kubernetes_sd_configs:
- role: node
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- action: labelmap
regex: __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-service-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
- job_name: 'kubernetes-services'
kubernetes_sd_configs:
- role: service
metrics_path: /probe
params:
module: [http_2xx]
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
action: keep
regex: true
- source_labels: [__address__]
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter.example.com:9115
- 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-ingresses'
kubernetes_sd_configs:
- role: ingress
relabel_configs:
- source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe]
action: keep
regex: true
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
regex: (.+);(.+);(.+)
replacement: ${1}://${2}${3}
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter.example.com:9115
- source_labels: [__param_target]
target_label: instance
- action: labelmap
regex: __meta_kubernetes_ingress_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_ingress_name]
target_label: kubernetes_name
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
# 監控規則檔案,被引用到/etc/prometheus/rules.yml
rules.yml: |
groups:
- name: test-rule
rules:
############# k8s-Node監控 #############
- alert: k8s-node狀态異常
expr: up{job="k8s-node"} != 1
for: 3m
labels:
severity: 非常嚴重
annotations:
summary: "k8s節點可能宕了"
description: "{{$labels.instance}}: Node節點狀态異常"
- alert: k8s-node節點CPU使用率
expr: (1 - avg(irate(node_cpu_seconds_total{job="k8s-node",mode="idle"}[1m])) by (instance)) * 100 > 95
for: 3m
labels:
severity: 一般
annotations:
summary: "Node節點CPU使用率超過95%"
description: "{{$labels.instance}}: Node節點目前CPU使用率為: {{ $value }}"
- alert: k8s-node節點根磁盤使用率
expr: (node_filesystem_size_bytes{mountpoint="/",job="k8s-node"} - node_filesystem_avail_bytes{mountpoint="/",job="k8s-node"}) / node_filesystem_size_bytes{mountpoint="/",job="k8s-node"} * 100 > 70
for: 3m
labels:
team: k8s-node
annotations:
summary: "根磁盤使用率為: {{ $value }}"
description: "Node伺服器[[ {{$labels.instance}} ]] 的 {{$labels.mountpoint}} 磁盤空間使用率超過70%,超過85%後pod将遷移,請盡快處理"
- alert: k8s-node節點記憶體使用率
expr: (node_memory_MemTotal_bytes{job="k8s-node"} - (node_memory_Buffers_bytes{job="k8s-node"} + node_memory_Cached_bytes{job="k8s-node"} + node_memory_MemFree_bytes{job="k8s-node"})) / node_memory_MemTotal_bytes{job="k8s-node"} * 100 > 95
for: 3m
labels:
team: k8s-node
annotations:
summary: "目前記憶體使用率超過95%"
description: "Node伺服器[[ {{$labels.instance}} ]] 記憶體使用率為: {{ $value }}"
############# es-Node監控 #############
- alert: es-node狀态異常
expr: up{job="es-node"} != 1
for: 3m
labels:
severity: 非常嚴重
annotations:
summary: "elasticsearch節點可能宕了"
description: "{{$labels.instance}}: elasticsearch節點狀态異常"
- alert: es-node節點資料磁盤使用率
expr: (node_filesystem_size_bytes{mountpoint="/data",job="es-node"} - node_filesystem_avail_bytes{mountpoint="/data",job="es-node"}) / node_filesystem_size_bytes{mountpoint="/data",job="es-node"} * 100 > 70
for: 3m
labels:
severity: 嚴重
annotations:
summary: "/data 磁盤使用率為: {{ $value }}"
description: "Node伺服器[[ {{$labels.instance}} ]] 的 {{$labels.mountpoint}} 磁盤空間使用率超過70%,超過85%後pod将遷移,請盡快處理"
EOF
我這麼負責,這裡要說一下某些沒加注釋的地方
-
alert: 報警組
expr: 報警規則設定,這裡的資料源在 prometheus 的 UI 界面都能搜尋到,并且在 UI 界面都可以用文法取到想要的值,監控規則必須得在 UI 界面能一樣運作取值,否則無法監控。例如 up{job=“es-node”} 直接在 UI 界面輸入是可以拿到值的。
for:觸發報警後等待時間
labels: 設定報警級别,此處還有别的功能,沒研究
annotations: 報警資訊的描述,這裡可以從報警資訊中過濾想要的内容,使報警内容更加易讀
summary: 翻譯一下,總結; 概括; 概要; 如我上面所寫,你懂得。
description: 翻譯一下,描述,描寫,說明,你懂得。這兩個随便怎麼用都行。
建議報警規則按照各個類型分開,以服務種類劃分,本人跟監控打了三年交道,我覺得越細越好、因為各種服務有各種自己的門檻值,它可以讓磁盤到 90% 再報警,但另一個80%就得報警,是以越細越好。跑題了。。。
rbac 檔案
這個檔案不得了,有了他,就可以連接配接到 k8s master ,擷取到 k8s 的叢集資訊,即獲得 k8s api ,這個檔案不用改,直接拿去用。
cat > rbac-setup.yaml << EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- apiGroups: [""]
resources:
- nodes
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
- apiGroups:
- extensions
resources:
- ingresses
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: monitor
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitor
EOF
pod 的配置檔案 prometheus-deploy.yaml
來吧,下面讓我們一鼓作氣建立完,然後是啟動 pod 的配置檔案 prometheus-deploy.yaml ,有兩點需要注意:
1、修改一下資料目錄的挂在點為自己的路徑,主控端此資料路徑給 777 權限。
2、我給 prometheus 的 pod 加了排程方式,隻能在有 prometheus 标簽的節點上啟動,即下面的這個配置
nodeSelector:
nodetype: prometheus
具體怎麼做,請看這篇文檔:
https://blog.csdn.net/qq_31547771/article/details/100742202
這個檔案。。。能撸到此文的,相信對 k8s 的 yaml 檔案已經相當熟悉了。不熟悉的話,Linke 在這兒有詳解:
https://blog.csdn.net/qq_31547771/article/details/102526403
cat > prometheus-deploy.yaml << EOF
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
labels:
name: prometheus-deployment
name: prometheus
namespace: monitor
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
containers:
- image: prom/prometheus:v2.6.0
name: prometheus
command:
- "/bin/prometheus"
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/home/prometheus"
- "--storage.tsdb.retention=15d"
- "--web.enable-lifecycle"
ports:
- containerPort: 9090
protocol: TCP
volumeMounts:
- mountPath: "/home/prometheus"
name: data
- mountPath: "/etc/prometheus"
name: config-volume
- mountPath: "/etc/localtime"
readOnly: false
name: localtime
resources:
requests:
cpu: 500m
memory: 3180Mi
limits:
cpu: 1000m
memory: 4180Mi
serviceAccountName: prometheus
nodeSelector:
nodetype: prometheus
volumes:
- name: data
hostPath:
path: "/opt/prometheus/data"
- name: config-volume
configMap:
name: prometheus-config
- name: localtime
hostPath:
path: "/etc/localtime"
type: File
EOF
然後是對外(叢集外部通路)用的 service 配置檔案
prometheus-service.yaml ,即使用 nodeport 将端口映射到叢集外,然後用浏覽器通路。
cat > prometheus-service.yaml << EOF
---
kind: Service
apiVersion: v1
metadata:
labels:
app: prometheus
name: prometheus
namespace: monitor
spec:
type: NodePort
ports:
- port: 9090
targetPort: 9090
nodePort: 30003
selector:
app: prometheus
EOF
最後是建立 namespace 的配置檔案 monitor_namespace.yaml
以上 service 和 pod 都規劃到 monitor 命名空間中
cat > monitor_namespace.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
name: monitor
labels:
name: monitor
EOF
然後是。然後prometheus就啟動了。。順序, 先建立命名空間——> 建立 confimap ——> 建立 rbac ——> 啟動 prometheus pod ——> 建立 prometheus service
kubectk create -f monitor_namespace.yaml
kubectk create -f configmap.yaml
kubectk create -f rbac-setup.yaml
kubectk create -f prometheus-deploy.yaml
kubectk create -f prometheus-service.yaml
kubectl get po -n monitor
一頓操作下去,檢視prometheus pod 是否啟動正常。然後浏覽器輸入 192.168.7.104:30003 ,就可以通路 prometheus 的 UI 界面了。在這裡可以搜尋關鍵字,如輸入 pod ,會自動補充,但是下面還要啟動一個 kube-state-metrics 才能抓到 pod 的資料。 是以,接的往下看。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL4NmeONTUU5EeNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL1AzMwQDNzMjM2AjMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
下面這兩個圖是 我現在的,上面的 confimap.yaml 我把多餘的都删了,否則太多。箭頭指出來的,是這個文檔例子中 confimap 會顯示的
點選 Alerts ,就可以看到自己設定的報警規則,可以嘗試觸發一個報警,看看這頁的狀态。
現在已經有了cadvisor、heapster、metric-server,幾乎容器運作的所有名額都能拿到,但是下面這種情況卻無能為力抓不到, k8s 的 pod 資料,還需要啟動一個從k8s中掏資料的元件,即 kube-state-metrics ,這個插件其實就是将 k8s api 中的 pod 資料取出來,然後處理成了 prometheus 監控資料的格式。
直接從 github 把這個項目下載下傳下來:
https://github.com/kubernetes/kube-state-metrics
将一個版本的下載下傳下來,如果有的資料抓不到,或者有問題,就換個版本。我這裡用的是 kube-state-metrics:v1.3.1 ,去年裝的,一直沒時間更新。
将項目下載下傳來了後,解壓開 tar 包後,我們用 k8s 啟動,是以隻需要項目中的 kubernetes 目錄和下面的是以 yaml 檔案就可以了,然後将各個檔案中的 namespace: 的值改成 monitor ,不改也可以 。然後挨個建立一下:
cd kubernetes
for i in *;do kubectk create -f $i ;done
kubectl get po -n monitor
等待一分鐘,此時再重新整理一下浏覽器,然後在Graph 那一頁搜尋: pod ,會補出抓到的pod 資料。如圖,我們選擇 kube_pod_info
然後可以使用 prometheus 的文法将資料縮小範圍,監控也是這個意思,自己多測幾遍就懂了:
未完,請見下面兩篇文章。
Prometheus監控之Grafana——部署篇
https://blog.csdn.net/qq_31547771/article/details/103433097
Prometheus監控之altermanager——部署篇
https://blog.csdn.net/qq_31547771/article/details/103433737