K8S 集群優(yōu)化之監(jiān)控平臺的建立之運維進階
本文轉(zhuǎn)載自微信公眾號「 twt企業(yè)IT社區(qū)」,作者twt社區(qū) 。轉(zhuǎn)載本文請聯(lián)系twt企業(yè)IT社區(qū)公眾號。
優(yōu)化首先需要建立起一個目標,到底優(yōu)化要達到一個什么樣的目標,期望滿足什么樣的需求,解決業(yè)務增加過程中發(fā)生的什么問題。監(jiān)控平臺的建立是為Kubernetes集群及運行的業(yè)務系統(tǒng)得出系統(tǒng)的真實性能,有了現(xiàn)有系統(tǒng)當前的真實性能就可以設定合理的優(yōu)化指標,基本基線指標才能合理評估當前Kubernetes容器及業(yè)務系統(tǒng)的性能。本文介紹了如何建立有效的監(jiān)控平臺。
1. 監(jiān)控平臺建設
所有的優(yōu)化指標都是建立在對系統(tǒng)的充分了解上的,常規(guī)基于Kubernetes的監(jiān)控方案有以下大概有3種,我們就采用比較主流的方案,也降低部署成本和后期集成復雜度。
主流也是我們選取的方案是Prometheus +Grafana +cAdvisor +(要部署:Prometheus-operator, met-ric-server),通過Prometheus提供相關(guān)數(shù)據(jù),Prometheus定期獲取數(shù)據(jù)并用Grafana展示,異常告警使用AlertManager進行告警。實際部署過程中實施也可以考慮使用Kube-prometheus項目(參見注釋1)整體部署節(jié)省大量工作,以下是官方架構(gòu)圖,涉及到組件如下:
- Prometheus Operator
- Prometheus
- Alertmanager
- Prometheus node-exporter
- Prometheus Adapter for KubernetesMetrics APIs
- kube-state-metrics
- Grafana
上圖中的Service和ServiceMonitor都是Kubernetes的資源,一個ServiceMonitor可以通過labelSelector的方式去匹配一類Service,Prometheus也可以通過labelSelector去匹配多個ServiceMonitor。
主要監(jiān)控范圍分為:資源監(jiān)控,性能監(jiān)控,任務監(jiān)控,事件告警監(jiān)控等,因為本篇主要講的是性能優(yōu)化,所以側(cè)重點放在性能監(jiān)控上,但是優(yōu)化是全方位的工作所以也會涉及到資源,健康度,事件,日志等,另外就針對每種監(jiān)控類型的告警管理。
*注釋1:項目地址如下,就部署方式可參見項目介紹在此就不贅述:
https://github.com/coreos/kube-prometheus
2.數(shù)據(jù)采集
各維度的數(shù)據(jù)采集主要通過以下方式:
- 部署cAdvisor(參見注釋2)采集容器相關(guān)的性能指標數(shù)據(jù),并通過metrics接口用Prometheus抓取;
- 也可根據(jù)需求可將各種監(jiān)控,日志采集的Agent部署在獨立的容器中,跟隨Pod 中的容器一起啟動監(jiān)督采集各種數(shù)據(jù),具體可根據(jù)實際需求;
- 通過Prometheus-node-exporter采集主機的性能指標數(shù)據(jù),并通過暴露的metrics接口用Prometheus抓取
- 通過exporter采集應用的網(wǎng)絡性能(Http、Tcp等)數(shù)據(jù),并通過暴露的metrics接口用Prometheus抓取
- 通過kube-state-metrics采集k8S資源對象的狀態(tài)指標數(shù)據(jù),并通過暴露的metrics接口用Prometheus抓取
- 通過etcd、kubelet、kube-apiserver、kube-controller-manager、kube-scheduler自身暴露的metrics獲取節(jié)點上與k8S集群相關(guān)的一些特征指標數(shù)據(jù)。
*注釋2:
node-exporter:負責采集主機的信息和操作系統(tǒng)的信息,以容器的方式運行在監(jiān)控主機上。
cAdvisor:負責采集容器的信息,以容器的方式運行在監(jiān)控主機上。
3. 資源監(jiān)控說明
資源監(jiān)控主要分為這幾大類:如:CPU,內(nèi)存,網(wǎng)絡,磁盤等信息的監(jiān)控(其它還有對GPU等監(jiān)控),另外就是對各種組件服務的資源使用情況,自定義告警閾值等(簡單的告警獲可以沿用內(nèi)部已有的,復雜的告警指標需自己根據(jù)集群和業(yè)務特征通過獲取參數(shù)進行計算或撰寫PromQL獲取),建立全方位的監(jiān)控指標(主要監(jiān)控指標項可參見Kube-prometheus部署后的相關(guān)信息,在此就不贅述),主要監(jiān)控項如下;
- 容器 CPU,Mem,Disk, Network等資源占用等情況;
- Node、Pod相關(guān)的性能指標數(shù)據(jù);
- 容器內(nèi)進程自己主動暴露的各項指標數(shù)據(jù);
- 各個組件的性能指標涉及組件如:ECTD,API Server, Controller Manager, Scheduler, Kubelet等;
4. 主要指標監(jiān)控
主要的監(jiān)控指標,是依據(jù)Google提出的四個指標:延遲(Latency)、流量(Traffic)、錯誤數(shù)(Errors)、飽和度(Saturation)。實際操作中可以使用USE或RED(詳見注釋3和4)方法作為衡量方法,USE用于資源,RED用于服務,它們在不同的監(jiān)控場景有不同維度描述,相結(jié)合能夠描述大部分監(jiān)控場景指標,合理的使用以下監(jiān)控指標,有助用戶判斷當前K8S集群的實際運行情況,可根據(jù)指標變化反復優(yōu)化各個參數(shù)和服務,使其達到更加的狀態(tài),更詳細的監(jiān)控指標信息,可參見Kube-prometheus相關(guān)監(jiān)控信息。
4.1 Cadvisor指標采集
cAdvisor(詳見參考1)提供的Container指標最終是底層Linux cgroup提供的。就像Node指標一樣,但是我們最關(guān)心的是CPU/內(nèi)存/網(wǎng)絡/磁盤。
1.CPU(利用率)
對于Container CPU利用率,K8S提供了每個容器的多個指標:
#過去10秒容器CPU的平均負載
container_cpu_load_average_10s
#累計用戶消耗CPU時間(即不在內(nèi)核中花費的時間)
container_cpu_user_seconds_total
#累計系統(tǒng)CPU消耗的時間(即在內(nèi)核中花費的時間)
container_cpu_system_seconds_total
#累計CPU消耗時間
container_cpu_usage_seconds_total
#容器的CPU份額
container_spec_cpu_quota
#容器的CPU配額
container_spec_cpu_shares
#查詢展示每個容器正在使用的CPU
sum(
rate(container_cpu_usage_seconds_total [5m]))
by(container_name)
# 過去10秒內(nèi)容器CPU的平均負載值
container_cpu_load_average_10s{container="",id="/",image="",name="",namespace="",pod=""}
#累計系統(tǒng)CPU消耗時間
sum(rate(container_cpu_usage_seconds_total{name=~".+"}[1m])) by (name) * 100
#全部容器的CPU使用率總和,將各個CPU使用率進行累加后相除
sum(rate(container_cpu_usage_seconds_total{container_name="webapp",pod_name="webapp-rc-rxli1"}[1m])) / (sum(container_spec_cpu_quota{container_name="webapp",pod_name="webapp-rc-rxli1"}/100000))
2.CPU(飽和度)
sum(
rate(container_cpu_cfs_throttled_seconds_total[5m]))
by (container_name)
3.內(nèi)存
cAdvisor中提供的內(nèi)存指標是從可參見官方網(wǎng)站,以下是內(nèi)存指標(如無特殊說明均以字節(jié)位單位):
#高速緩存(Cache)的使用量
container_memory_cache
# RSS內(nèi)存,即常駐內(nèi)存集,是分配給進程使用實際物理內(nèi)存,而不是磁盤上緩存的虛擬內(nèi)存。RSS內(nèi)存包括所有分配的棧內(nèi)存和堆內(nèi)存,以及加載到物理內(nèi)存中的共享庫占用的內(nèi)存空間,但不包括進入交換分區(qū)的內(nèi)存
container_memory_rss
#容器虛擬內(nèi)存使用量。虛擬內(nèi)存(swap)指的是用磁盤來模擬內(nèi)存使用。當物理內(nèi)存快要使用完或者達到一定比例,就可以把部分不用的內(nèi)存數(shù)據(jù)交換到硬盤保存,需要使用時再調(diào)入物理內(nèi)存
container_memory_swap
#當前內(nèi)存使用情況,包括所有使用的內(nèi)存,不管是否被訪問 (包括 cache, rss, swap等)
container_memory_usage_bytes
#最大內(nèi)存使用量
container_memory_max_usage_bytes
#當前內(nèi)存工作集(working set)使用量
container_memory_working_set_bytes
#內(nèi)存使用次數(shù)達到限制
container_memory_failcnt
#內(nèi)存分配失敗的累積數(shù)量
container_memory_failures_total
#內(nèi)存分配失敗次數(shù)
container_memory_failcnt
4.內(nèi)存(利用率)
通過PromQL特定條件查詢?nèi)萜鲀?nèi)job內(nèi)存使用情況:
container_memory_usage_bytes{instance="10.10.2.200:3002",job="panamax", name="PMX_UI"}18
kubelet 通過container_memory_working_set_bytes 來判斷是否OOM, 所以用 working set來評價容器內(nèi)存使用量更合理,以下查詢中我們需要通過過濾“POD”容器,它是此容器的父級cgroup,將跟蹤pod中所有容器的統(tǒng)計信息。
sum(container_memory_working_set_bytes {name!~“ POD”})by name
5.內(nèi)存(飽和度)
OOM的異常獲取沒有直接的指標項,因為OOM后Container會被殺掉,可以使用如下查詢來變通獲取,這里使用label_join組合了 kube-state-metrics 的指標:
sum(container_memory_working_set_bytes) by (container_name) / sum(label_join(kube_pod_con-tainer_resource_limits_memory_bytes,"container_name", "", "container")) by (container_name)
6.磁盤(利用率)
在處理磁盤I/O時,我們通過查找和讀寫來跟蹤所有磁盤利用率,Cadvisor有以下指標可以做位基本指標:
#容器磁盤執(zhí)行I/O的累計秒數(shù)
container_fs_io_time_seconds_total
#容器磁盤累計加權(quán)I/O時間
container_fs_io_time_weighted_seconds_total
#查詢?nèi)萜魑募到y(tǒng)讀取速率(字節(jié)/秒)
sum(rate(container_fs_writes_bytes_total{image!=""}[1m]))without (device)
#查詢?nèi)萜魑募到y(tǒng)寫入速率(字節(jié)/秒)
sum(rate(container_fs_writes_bytes_total{image!=""}[1m]))without (device)
最基本的磁盤I/O利用率是讀/寫的字節(jié)數(shù), 對這些結(jié)果求和,以獲得每個容器的總體磁盤I/O利用率:
sum(rate(container_fs_reads_bytes_total[5m])) by (container_name,device)
7.網(wǎng)絡(利用率)
容器的網(wǎng)絡利用率,可以選擇以字節(jié)為單位還是以數(shù)據(jù)包為單位。網(wǎng)絡的指標有些不同,因為所有網(wǎng)絡請求都在Pod級別上進行,而不是在容器上進行以下的查詢將按pod名稱顯示每個pod的網(wǎng)絡利用率:
#接收時丟包累計計數(shù)
container_network_receive_bytes_total
#發(fā)送時丟包的累計計數(shù)
container_network_transmit_packets_dropped_total
#接收字節(jié)(1m)
sum(rate(container_network_receive_bytes_total{id="/"}[1m])) by (id)
#上傳字節(jié)(1m)
sum(rate(container_network_transmit_bytes_total{id="/"}[1m])) by (id)
8.網(wǎng)絡(飽和度)
在無法得知準確的網(wǎng)絡帶寬是多少的情況下,網(wǎng)絡的飽和度無法明確定義,可以考慮使用丟棄的數(shù)據(jù)包代替,表示當前已經(jīng)飽和,參見以下參數(shù):
#接收時丟包累計計數(shù)
container_network_receive_packets_dropped_total
#發(fā)送時丟包的累計計數(shù)
container_network_transmit_packets_dropped_total
*注釋3:
在對于cAdvisor 容器資源,USE方法指標相對簡單如下:
Utilization:利用率
Saturation:飽和度
Error:錯誤
*注釋4:
USE 方法的定義:
Resource:所有服務器功能組件(CPU,Disk,Services等)
Utilization:資源忙于服務工作的平均時間
Saturation:需要排隊無法提供服務的時間
Errors:錯誤事件的計數(shù)
RED 方法的解釋:
Rate:每秒的請求數(shù)。
Errors:失敗的那些請求的數(shù)量。
參考 1:
更詳細關(guān)于cAdvisor的參數(shù)信息大家可以一下地址獲取,也可以自己組合更加適用于自己集群的監(jiān)控指標:
https://github.com/google/cadvisor/blob/master/docs/storage/prometheus.md
參考2:
關(guān)于Node_exporter,大家有興趣可以參考Prometheus項目中關(guān)于Node_exporter里面說明如下:
https://github.com/prometheus/node_exporter
5. 事件告警監(jiān)控
監(jiān)控Event 轉(zhuǎn)換過程種的變化信息,以下只是部份告警信息,Kube-Prometheus項目中有大部分告警指標,也可以從第三方導入相關(guān)告警事件:
#存在執(zhí)行失敗的Job:
kube_job_status_failed{job=”kubernetes-service-endpoints”,k8s_app=”kube-state-metrics”}==1
#集群節(jié)點狀態(tài)錯誤:
kube_node_status_condition{condition=”Ready”,status!=”true”}==1
#集群節(jié)點內(nèi)存或磁盤資源短缺:
kube_node_status_condition{condition=~”OutOfDisk|MemoryPressure|DiskPressure”,status!=”false”}==1
#集群中存在失敗的PVC:
kube_persistentvolumeclaim_status_phase{phase=”Failed”}==1
#集群中存在啟動失敗的Pod:
kube_pod_status_phase{phase=~”Failed|Unknown”}==1
#最近30分鐘內(nèi)有Pod容器重啟:
changes(kube_pod_container_status_restarts[30m])>0
6. 日志監(jiān)控
日志也是K8S集群和容器/應用服務的很重要的數(shù)據(jù)來源,日志中也能獲取各種指標和信息,主流的方式采用常駐的Agent采集日志信息,將相關(guān)發(fā)送到Kafka集群最后寫入ES,也通過Grafana進行統(tǒng)一展示各項指標。
6.1 日志采集
- 一種方式將各個容器的日志都寫入宿主機的磁盤,容器掛載宿主機本地Volume,采用Agent(Filebeat或Fluentd )采集這個部署在宿主機上所有容器轉(zhuǎn)存的日志,發(fā)送到遠端ES集群進行加工處理;
- 另一種是對于業(yè)務組(或者說Pod)采集容器內(nèi)部日志,系統(tǒng)/業(yè)務日志可以存儲在獨立的Volume中,可以采用Sidecar模式獨立部署日志采集容器,來對進行日志采集,對于DaemonSet和Sidecar這兩種日志采集模式,大家可以根據(jù)實際需要選擇部署;
- 通過部署在每個Node上的Agent進行日志采集,Agent會把數(shù)據(jù)匯集到Logstash Server集群,再由Logstash加工清洗完成后發(fā)送到Kafka集群,再將數(shù)據(jù)存儲到Elasticsearch,后期可通過Grafana或者Kibana做展現(xiàn),這也是比較主流的一個做法。
6.2 日志場景
主要需要采集的各種日志分為以下場景:
1.主機系統(tǒng)內(nèi)核日志采集:
- 一方面是主機系統(tǒng)內(nèi)核日志,主機內(nèi)核日志可以協(xié)助開發(fā)/運維進行一些常見的問題分析診斷,如:Linux Kernel Panic涉及的(Attempted to kill the idle task,Attempted to kill init,killing interrupt handler)其它致命異常,這些情況要求導致其發(fā)生的程序或任務關(guān)閉,通常異常可能是任何意想不到的情況;
- 另一方面是各種Driver 驅(qū)動異常,比如:Driver內(nèi)核對象出現(xiàn)異常或者說使用GPU的一些場景,各種硬件的驅(qū)動異??赡苁潜容^常見的錯誤;
- 再就是文件系統(tǒng)異常,一些特定場景(如:虛機化,特定文件格式),實際上是會經(jīng)常出現(xiàn)問題的。在這些出現(xiàn)問題后,開發(fā)者是沒有太好的辦法來去進行監(jiān)控和診斷的。這一部分,其實是可以主機內(nèi)核日志里面來查看到一些異常。
2.組件日志采集:
K8S集群中各種組件是集群非常重要的部份,既有內(nèi)部組件也有外部的如:API Server, Controller-man-ger,Kubelet , ECTD等, 它們會產(chǎn)生大量日志可用于各種錯誤分析和性能優(yōu)化,也能幫助用戶很好分析K8S集群各個組件資源使用情況分析,異常情況分析;還有各種第三方插件的日志(尤其是一些廠商貢獻的網(wǎng)絡插件或算法),也是優(yōu)化分析的重點;
3.業(yè)務日志采集:
業(yè)務日志分析也是優(yōu)化的很重要的環(huán)節(jié),業(yè)務系統(tǒng)自身的特性(如:web類,微服務類,API 接口類,基礎組件類)都需要日志來分析,結(jié)合后面的資源預測和業(yè)務部署章節(jié)能否更好把握業(yè)務特性,創(chuàng)建合理的發(fā)布配置和Pod配置,根據(jù)日志分析業(yè)務訪問量,活動周期,業(yè)務峰值,調(diào)用關(guān)系等優(yōu)化整個過程。