Promethus搭建 K8S 集群节点资源监控系统
對于集群的監控一般我們需要考慮以下幾個方面:
-
Kubernetes 節點的監控:比如節點的 cpu、load、disk、memory 等指標
-
內部系統組件的狀態:比如 kube-scheduler、kube-controller-manager、kubedns/coredns 等組件的詳細運行狀態
-
編排級的 metrics:比如 Deployment 的狀態、資源請求、調度和 API 延遲等數據指標
監控方案
Kubernetes 集群的監控方案目前主要有以下集中方案:
-
Heapster:Heapster 是一個集群范圍的監控和數據聚合工具,以 Pod 的形式運行在集群中。除了 Kubelet/cAdvisor 之外,我們還可以向 Heapster 添加其他指標源數據,比如 kube-state-metrics,我們會在下面和大家講解的
需要注意的是 Heapster 已經被廢棄了,后續版本中會使用 metrics-server 代替。
-
cAdvisor:cAdvisor是Google開源的容器資源監控和性能分析工具,它是專門為容器而生,本身也支持 Docker 容器,在 Kubernetes 中,我們不需要單獨去安裝,cAdvisor 作為 kubelet 內置的一部分程序可以直接使用。
-
Kube-state-metrics:kube-state-metrics通過監聽 API Server 生成有關資源對象的狀態指標,比如 Deployment、Node、Pod,需要注意的是 kube-state-metrics 只是簡單提供一個 metrics 數據,并不會存儲這些指標數據,所以我們可以使用 Prometheus 來抓取這些數據然后存儲。
-
metrics-server:metrics-server 也是一個集群范圍內的資源數據聚合工具,是 Heapster 的替代品,同樣的,metrics-server 也只是顯示數據,并不提供數據存儲服務。
不過 kube-state-metrics 和 metrics-server 之間還是有很大不同的,二者的主要區別如下:
-
kube-state-metrics 主要關注的是業務相關的一些元數據,比如 Deployment、Pod、副本狀態等
-
metrics-server 主要關注的是資源度量 API?的實現,比如 CPU、文件描述符、內存、請求延時等指標。
監控集群節點
現在我們就來開始我們集群的監控工作,首先來監控我們集群的節點,要監控節點其實我們已經有很多非常成熟的方案了,比如 Nagios、zabbix,甚至我們自己來收集數據也可以,我們這里通過 Prometheus 來采集節點的監控指標數據,可以通過node_exporter來獲取,顧名思義,node_exporter 抓喲就是用于采集服務器節點的各種運行指標的,目前 node_exporter 支持幾乎所有常見的監控點,比如 conntrack,cpu,diskstats,filesystem,loadavg,meminfo,netstat等,詳細的監控點列表可以參考其Github repo。
我們可以通過 DaemonSet 控制器來部署該服務,這樣每一個節點都會自動運行一個這樣的 Pod,如果我們從集群中刪除或者添加節點后,也會進行自動擴展。
在部署 node-exporter 的時候有一些細節需要注意,如下資源清單文件:(prome-node-exporter.yaml)? ?
Kubernetes版本:1.18 ,首先要創建命名空間:?kubectl create namespace kube-ops
Daemonset 官方文檔:https://kubernetes.io/zh/docs/concepts/workloads/controllers/daemonset/
apiVersion: apps/v1 kind: DaemonSet metadata:name: node-exporternamespace: kube-opslabels:name: node-exporter spec:selector:matchLabels:name: node-exportertemplate:metadata:labels:name: node-exporterspec:hostPID: truehostIPC: truehostNetwork: truecontainers:- name: node-exporterimage: prom/node-exporter:v0.16.0ports:- containerPort: 9100resources:requests:cpu: 0.15securityContext:privileged: trueargs:- --path.procfs- /host/proc- --path.sysfs- /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: /rootfstolerations:- key: "node-role.kubernetes.io/master"operator: "Exists"effect: "NoSchedule"volumes:- name: prochostPath:path: /proc- name: devhostPath:path: /dev- name: syshostPath:path: /sys- name: rootfshostPath:path: /由于我們要獲取到的數據是主機的監控指標數據,而我們的 node-exporter 是運行在容器中的,所以我們在 Pod 中需要配置一些 Pod 的安全策略,這里我們就添加了hostPID: true、hostIPC: true、hostNetwork: true3個策略,用來使用主機的 PID namespace、IPC namespace 以及主機網絡,這些 namespace 就是用于容器隔離的關鍵技術,要注意這里的 namespace 和集群中的 namespace 是兩個完全不相同的概念。
另外我們還將主機的/dev、/proc、/sys這些目錄掛載到容器中,這些因為我們采集的很多節點數據都是通過這些文件夾下面的文件來獲取到的,比如我們在使用top命令可以查看當前cpu使用情況,數據就來源于文件/proc/stat,使用free命令可以查看當前內存使用情況,其數據來源是來自/proc/meminfo文件。
另外由于我們集群使用的是 kubeadm 搭建的,所以如果希望 master 節點也一起被監控,則需要添加響應的容忍,對于污點和容忍還不是很熟悉的同學可以在前面的章節中回顧下。
然后直接創建上面的資源對象即可:
$ kubectl create -f prome-node-exporter.yaml daemonset.extensions "node-exporter" created $ kubectl get pods -n kube-ops -o wide NAME READY STATUS RESTARTS AGE IP NODE node-exporter-jfwfv 1/1 Running 0 30m 10.151.30.63 node02 node-exporter-kr8rt 1/1 Running 0 30m 10.151.30.64 node03 node-exporter-whb7n 1/1 Running 0 20m 10.151.30.57 master prometheus-8566cd9699-gt9wh 1/1 Running 0 4d 10.244.4.39 node02 redis-544b6c8c54-8xd2g 2/2 Running 0 23h 10.244.2.87 node03部署完成后,我們可以看到在3個節點上都運行了一個 Pod,有的同學可能會說我們這里不需要創建一個 Service 嗎?我們應該怎樣去獲取/metrics數據呢?我們上面是不是指定了hostNetwork=true,所以在每個節點上就會綁定一個端口 9100,我們可以通過這個端口去獲取到監控指標數據:
$ curl 127.0.0.1:9100/metrics ... node_filesystem_device_error{device="shm",fstype="tmpfs",mountpoint="/rootfs/var/lib/docker/containers/aefe8b1b63c3aa5f27766053ec817415faf8f6f417bb210d266fef0c2da64674/shm"} 1 node_filesystem_device_error{device="shm",fstype="tmpfs",mountpoint="/rootfs/var/lib/docker/containers/c8652ca72230496038a07e4fe4ee47046abb5f88d9d2440f0c8a923d5f3e133c/shm"} 1 node_filesystem_device_error{device="tmpfs",fstype="tmpfs",mountpoint="/dev"} 0 node_filesystem_device_error{device="tmpfs",fstype="tmpfs",mountpoint="/dev/shm"} 0 ...當然如果你覺得上面的手動安裝方式比較麻煩,我們也可以使用 Helm 的方式來安裝:
$ helm install --name node-exporter stable/prometheus-node-exporter --namespace kube-ops服務發現
由于我們這里3個節點上面都運行了 node-exporter 程序,如果我們通過一個 Service 來將數據收集到一起用靜態配置的方式配置到 Prometheus 去中,就只會顯示一條數據,我們得自己在指標數據中去過濾每個節點的數據,那么有沒有一種方式可以讓 Prometheus 去自動發現我們節點的 node-exporter 程序,并且按節點進行分組呢?是有的,就是我們前面和大家提到過的服務發現。
在 Kubernetes 下,Promethues 通過與 Kubernetes API 集成,目前主要支持5中服務發現模式,分別是:Node、Service、Pod、Endpoints、Ingress。
我們通過 kubectl 命令可以很方便的獲取到當前集群中的所有節點信息:
$ kubectl get nodes NAME STATUS ROLES AGE VERSION master Ready master 165d v1.10.0 node02 Ready <none> 85d v1.10.0 node03 Ready <none> 145d v1.10.0但是要讓 Prometheus 也能夠獲取到當前集群中的所有節點信息的話,我們就需要利用 Node 的服務發現模式,同樣的,在 prometheus.yml 文件中配置如下的 job 任務即可:
- job_name: 'kubernetes-nodes'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: node通過指定kubernetes_sd_configs的模式為node,Prometheus 就會自動從 Kubernetes 中發現所有的 node 節點并作為當前 job 監控的目標實例,發現的節點/metrics接口是默認的 kubelet 的 HTTP 接口,另外這里還需要指定用于訪問 Kubernetes API 的 ca 以及 token 文件路徑,ca 證書和 token 文件都是 Pod 啟動后集群自動注入到 Pod 中的文件。
prometheus 的 ConfigMap 更新完成后,同樣的我們執行 reload 操作,讓配置生效:
$ kubectl delete -f prome-cm.yaml configmap "prometheus-config" deleted $ kubectl create -f prome-cm.yaml configmap "prometheus-config" created # 隔一會兒再執行下面的 reload 操作 $ kubectl get svc -n kube-ops NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE prometheus NodePort 10.102.74.90 <none> 9090:30358/TCP 5d ...... $ curl -X POST "http://10.102.74.90:9090/-/reload"配置生效后,我們再去 prometheus 的 dashboard 中查看 Targets 是否能夠正常抓取數據,訪問任意節點IP:30358:
prometheus nodes target
我們可以看到上面的kubernetes-nodes這個 job 任務已經自動發現了我們3個 node 節點,但是在獲取數據的時候失敗了,出現了類似于下面的錯誤信息:
Get http://10.151.30.57:10250/metrics: net/http: HTTP/1.x transport connection broken: malformed HTTP response "\x15\x03\x01\x00\x02\x02"這個是因為 prometheus 去發現 Node 模式的服務的時候,訪問的端口默認是10250,而現在該端口下面已經沒有了/metrics指標數據了,現在 kubelet 只讀的數據接口統一通過10255端口進行暴露了,所以我們應該去替換掉這里的端口,但是我們是要替換成10255端口嗎?不是的,因為我們是要去配置上面通過node-exporter抓取到的節點指標數據,而我們上面是不是指定了hostNetwork=true,所以在每個節點上就會綁定一個端口9100,所以我們應該將這里的10250替換成9100,但是應該怎樣替換呢?
這里我們就需要使用到 Prometheus 提供的relabel_configs中的replace能力了,relabel 可以在 Prometheus 采集數據之前,通過Target 實例的 Metadata 信息,動態重新寫入 Label 的值。除此之外,我們還能根據 Target 實例的 Metadata 信息選擇是否采集或者忽略該 Target 實例。比如我們這里就可以去匹配__address__這個 Label 標簽,然后替換掉其中的端口:
- job_name: 'kubernetes-nodes'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: noderelabel_configs:- source_labels: [__address__]regex: '(.*):10250'replacement: '${1}:9100'target_label: __address__action: replace這里就是一個正則表達式,去匹配__address__,然后將 host 部分保留下來,port 替換成了9100,現在我們重新更新配置文件,執行 reload 操作,然后再去看 Prometheus 的 Dashboard 的 Targets 路徑下面 kubernetes-nodes 這個 job 任務是否正常了:
prometheus nodes target2
我們可以看到現在已經正常了,但是還有一個問題就是我們采集的指標數據 Label 標簽就只有一個節點的 hostname,這對于我們在進行監控分組分類查詢的時候帶來了很多不方便的地方,要是我們能夠將集群中 Node 節點的 Label 標簽也能獲取到就很好了。
這里我們可以通過labelmap這個屬性來將 Kubernetes 的 Label 標簽添加為 Prometheus 的指標標簽:
- job_name: 'kubernetes-nodes'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: noderelabel_configs:- source_labels: [__address__]regex: '(.*):10250'replacement: '${1}:9100'target_label: __address__action: replace- action: labelmapregex: __meta_kubernetes_node_label_(.+)添加了一個 action 為labelmap,正則表達式是__meta_kubernetes_node_label_(.+)的配置,這里的意思就是表達式中匹配都的數據也添加到指標數據的 Label 標簽中去。
對于 kubernetes_sd_configs 下面可用的標簽如下:?可用元標簽:
-
__meta_kubernetes_node_name:節點對象的名稱
-
__meta_kubernetes_nodelabel
:節點對象中的每個標簽 -
__meta_kubernetes_nodeannotation
:來自節點對象的每個注釋 -
__meta_kubernetes_nodeaddress
:每個節點地址類型的第一個地址(如果存在)
關于 kubernets_sd_configs 更多信息可以查看官方文檔:kubernetes_sd_config
另外由于 kubelet 也自帶了一些監控指標數據,就上面我們提到的10255端口,所以我們這里也把 kubelet 的監控任務也一并配置上:
- job_name: 'kubernetes-nodes'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_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-kubelet'tls_config:ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crtbearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/tokenkubernetes_sd_configs:- role: noderelabel_configs:- source_labels: [__address__]regex: '(.*):10250'replacement: '${1}:10255'target_label: __address__action: replace- action: labelmapregex: __meta_kubernetes_node_label_(.+)現在我們再去更新下配置文件,執行 reload 操作,讓配置生效,然后訪問 Prometheus 的 Dashboard 查看 Targets 路徑:
prometheus node targets
現在可以看到我們上面添加的kubernetes-kubelet和kubernetes-nodes這兩個 job 任務都已經配置成功了,而且二者的 Labels 標簽都和集群的 node 節點標簽保持一致了。
現在我們就可以切換到 Graph 路徑下面查看采集的一些指標數據了,比如查詢 node_load1 指標:
prometheus nodes graph1
我們可以看到將3個 node 節點對應的 node_load1 指標數據都查詢出來了,同樣的,我們還可以使用 PromQL 語句來進行更復雜的一些聚合查詢操作,還可以根據我們的 Labels 標簽對指標數據進行聚合,比如我們這里只查詢 node03 節點的數據,可以使用表達式node_load1{instance="node03"}來進行查詢:
prometheus nodes graph2
到這里我們就把 Kubernetes 集群節點的使用 Prometheus 監控起來了,下節課我們再來和大家學習怎樣監控 Pod 或者 Service 之類的資源對象。
?
任何程序錯誤,以及技術疑問或需要解答的,請掃碼添加作者VX
?
總結
以上是生活随笔為你收集整理的Promethus搭建 K8S 集群节点资源监控系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里云服务器Debian11系统安装Li
- 下一篇: forth编程语言