容器監控實踐—K8S經常使用指標分析

[TOC]html

基於 RED方法USE 方法 對如下四類指標進行分析:node

  • cadvisor 指標分析
  • node-exporter 指標分析
  • etcd 指標分析
  • apiserver 指標分析

advisor 指標分析

在Kubernetes中,cAdvisor嵌入到kubelet中,本文使用 USE 方法對容器的指標進行分析。linux

USE方法表明golang

  • 利用率
  • 飽和度
  • 錯誤

cAdvisor提供的「容器」指標最終是底層Linux cgroup提供的。就像節點指標同樣,不少很詳細。可是咱們通常對CPU,內存,網絡和磁盤感興趣數據庫

CPU

利用率

對於CPU利用率,Kubernetes僅爲咱們提供了每一個容器的三個指標api

  • container_cpu_user_seconds_total —「用戶」時間的總數(即不在內核中花費的時間)
  • container_cpu_system_seconds_total —「系統」時間的總數(即在內核中花費的時間)
  • container_cpu_usage_seconds_total—以上總和

全部這些指標都是couter類型,須要對其rate算出使用率嗎.緩存

下面的查詢展現每一個容器正在使用的CPU:bash

sum(
    rate(container_cpu_usage_seconds_total [5m]))
by(container_name)

飽和率

若是您定義了CPU的 limit 值,計算飽和度將變得容易得多。服務器

當容器超出其CPU限制時,Linux運行時將「限制」該容器並在container_cpu_cfs_throttled_seconds_total指標中記錄其被限制的時間網絡

sum(
    rate(container_cpu_cfs_throttled_seconds_total[5m])) 
by (container_name)

錯誤數

就像node_exporter同樣,cAdvisor不會暴露CPU錯誤。

內存

cAdvisor中提供的內存指標是從node_exporter公開的43個內存指標的子集。如下是容器內存指標:

  • container_memory_cache-頁面緩存的字節數。
  • container_memory_rss -RSS的大小(以字節爲單位)。
  • container_memory_swap-容器交換使用量(以字節爲單位)。
  • container_memory_usage_bytes-當前內存使用狀況(以字節爲單位,包括全部內存,不管什麼時候訪問。)
  • container_memory_max_usage_bytes- 以字節爲單位記錄的最大內存使用量。
  • container_memory_working_set_bytes-當前工做集(以字節爲單位)。
  • container_memory_failcnt-內存使用次數達到限制。
  • container_memory_failures_total-內存 分配失敗的累積計數。

利用率

你可能認爲使用container_memory_usage_bytes來計算內存使用率,可是這個指標還包括了文件系統緩存,是不許確的。更準確的是container_memory_working_set_bytes,他是 OOM 所關心的指標

sum(container_memory_working_set_bytes {name!〜「 POD」})by name

在上面的查詢中,咱們須要排除名稱包含「 POD」的容器。這是此容器的父級cgroup,將跟蹤pod中全部容器的統計信息。

飽和度

和 CPU 的飽和度計算類似,可是和 CPU 不一樣,沒法直接使用指標,由於 OOM 後 container 會被殺掉,可使用以下查詢:

sum(container_memory_working_set_bytes) by (container_name) / sum(label_join(kube_pod_container_resource_limits_memory_bytes,
    "container_name", "", "container")) by (container_name)

這裏使用label_join組合了 kube-state-metrics 的指標

錯誤數

kubelet不會暴露內存錯誤。

磁盤

利用率

在處理磁盤I / O時,咱們首先經過查找和讀寫來跟蹤全部磁盤利用率。

cAdvisor有如下指標:

  • container_fs_io_time_seconds_total
  • container_fs_io_time_weighted_seconds_total

最基本的磁盤I / O利用率是讀/寫的字節數:

sum(rate(container_fs_writes_bytes_total[5m])) by (container_name,device)
sum(rate(container_fs_reads_bytes_total[5m])) by (container_name,device)

對這些求和,以得到每一個容器的整體磁盤I / O利用率。

飽和度

由於沒有磁盤的使用限制,沒法對容器磁盤飽和度作衡量

錯誤數

Kubelet沒有公開足夠的細節,沒法查看錯誤數

網絡

利用率

容器的網絡利用率,能夠選擇以字節爲單位仍是以數據包爲單位。網絡的指標有些不一樣,由於全部網絡請求都在Pod級別上進行,而不是在容器上進行

下面查詢將按pod名稱顯示每一個pod的網絡利用率:

sum(rate(container_network_receive_bytes_total[5m])) by (name)
sum(rate(container_network_transmit_bytes_total[5m])) by (name)

飽和度

一樣,在不知道最大網絡帶寬是多少的狀況下,網絡的飽和度定義不明確。您也許可使用丟棄的數據包代替,表示當前已經飽和。

  • container_network_receive_packets_dropped_total
  • container_network_transmit_packets_dropped_total

錯誤數

cAdvisor提供了

  • container_network_receive_errors_total
  • container_network_transmit_errors_total

node-exporter 指標分析

node-exporter能夠檢查節點的核心指標,從利用率,飽和度和錯誤的角度來看CPU,內存,磁盤和網絡的監控指標

因爲node_exporter提供了近1000個指標,有時很難知道要關心哪些。您的系統有哪些重要指標?分析的方法有多種多樣,咱們能夠簡化和抽象爲如下幾類:四個黃金信號,USE方法和RED方法。

四個黃金信號

Google在「SRE Handbook」中以「四個黃金信號」的概念爲咱們提供了一個論述:

  • Latency — 延遲
  • Traffic — 流量
  • Errors — 錯誤數
  • Saturation — 飽和度

當我第一次嘗試將四個黃金信號應用於系統中的指標時,我常常被其中的一些術語以及它們如何應用於系統中的各個節點和應用程序所絆倒。

CPU的延遲或流量是多少?Kafka主題的飽和度是多少?

要定義應用程序的飽和度,咱們常常須要考慮應用程序使用的基礎資源的飽和度。這些資源是什麼,咱們如何對其進行監控?咱們可使用USE方法

USE 方法

Brendan Gregg在解釋系統資源時如何考慮利用率、飽和度、錯誤方面作得很是出色。

他給出如下定義:

  • Resource:全部服務器功能組件(CPU,磁盤,總線等)
  • Utilization:資源忙於服務工做的平均時間
  • Saturation:須要排隊沒法提供服務的時間
  • Errors:錯誤事件的計數

他建議(但沒有規定)確切地表示在Unix系統的上下文中哪些度量表示利用率,飽和度和錯誤。本文的其他部分,我將USE方法應用於Kubernetes節點中的資源。

儘管USE方法針對的是資源,具備嚴格限制的實際物理資源,可是對於在這些資源上運行的軟件而言,這是不完整的描述。這就是RED方法的用武之地。

RED 方法

Tom Wilkie解釋RED方法爲:

  • Rate:每秒的請求數。
  • Errors:失敗的那些請求的數量。
  • Duration:這些請求所花費的時間。

從表面上看,RED方法彷佛與USE方法和四個黃金信號很是類似。何時使用USE vs RED?

USE方法用於資源,RED方法用於服務  — Tom Wilkie

CPU

利用率

如今,咱們有兩種方法能夠幫助您選擇要注意的指標。這東西是資源仍是應用程序?
集羣中的節點具備資源。您的節點在Kubernetes羣集中提供的最重要資源是CPU,內存,網絡和磁盤。
讓咱們將USE方法應用於全部這些方法。

node_exporter指標node_cpu會跟蹤全部10個CPU mode 在每一個內核上花費的全部CPU時間。這些mode是:user, system, nice, idle, iowait, guest, guest_nice, steal, soft_irq and irq。

要計算您的Kubernetes集羣中主機的cpu利用率,咱們但願對全部mode進行累加, idle, iowait, guest, and guest_nice除外。PromQL看起來像這樣:

sum(rate(
         node_cpu{mode!=」idle」,
                  mode!=」iowait」,
                  mode!~」^(?:guest.*)$」
                  }[5m])) BY (instance)

關於此查詢的一些注意事項:

  • 在PromQL中,當同一標籤上有多個修飾符時,它們將被AND在一塊兒。
  • 全部的node_cpu系列均表示爲CPU秒,而且是counter,所以咱們須要使用rate()來計算每秒的時間。最終結果顯示了每一個節點使用的CPU數。
  • 最終結果顯示了每一個節點使用的CPU數。

飽和度

cpu 提供的飽和度,是Unix的平均負載。平均負載是正在運行的進程數加上正在等待運行的進程數。一樣,布倫丹·格雷格(Brendan Greg)在Linux平均負載方面有「很長的論述](http://www.brendangregg.com/b...

node_load1,node_load5和node_load15分別表明一、5和15分鐘的平均負載。該指標是一個gauge,已經爲您進行了平均。做爲一個獨立的指標,知道節點有多少個CPU有些用處。

平均負載是10到底好仍是壞?這視狀況而定。若是將平均負載除以機器擁有的CPU數量,則能夠近似得出系統的CPU飽和度。

node_exporter不會直接公開節點CPU的數量,可是若是僅計算上述一種CPU模式(例如「 system」),則能夠按節點獲取CPU數量:

count(node_cpu{mode="system"}) by (node)

如今,您能夠經過以百分比表示的節點上的CPU數量來規範化node_load1指標:

sum(node_load1) by (node) / count(node_cpu{mode="system"}) by (node) * 100

彷佛咱們的系統之一的CPU飽和度高達250%以上。須要調查一下!

錯誤數

node_exporter不顯示有關CPU錯誤的任何信息。

內存

因爲已知節點上的物理內存量,所以彷佛能夠更容易地推斷出內存利用率和飽和度。可沒有那麼容易!node_exporter爲咱們提供了43個node_memory_ *指標供您使用!

Linux系統上的可用內存量不只僅是報告的「free」內存指標。Unix系統嚴重依賴於應用程序未使用的內存來共享代碼(buffers)和緩存磁盤頁面(cached)。所以可用內存的一種度量是:

sum(node_memory_MemFree + node_memory_Cached + node_memory_Buffers)

較新的Linux內核(3.14以後)公開了更好的可用內存指標node_memory_MemAvailable。

使用率

將其除以節點上可用的總內存,便可獲得可用內存的百分比,而後從1中減去以得出節點內存利用率的度量:

1 - sum(node_memory_MemAvailable) by (node) 
/ sum(node_memory_MemTotal) by (node)

飽和度

內存的飽和度是一個複雜的話題。從理論上講,Unix系統具備無限數量的「虛擬內存」。若是對內存系統的需求過多,則操做系統將最近未使用的內存page返給硬盤「page to disk」。用某種說法,這稱爲「going into swap」。在實踐中您永遠不會想要這個

密切關注節點正在執行的分頁數量能夠是內存飽和度的一種度量。

node_exporter指標node_vmstat_pgpgin和node_vmstat_pgpgout顯示節點的分頁活動量。這是一個不完整的指標,由於對於依賴於Linux shared page cache的任何程序使用,內存分頁都是正常活動。

Kubernetes爲咱們提供了一些其餘工具來限制集羣中使用的內存量。即 limit 限制,容器資源請求和限制(若是實施得當)能夠確保您的節點永遠不會開始交換。我將在之後的文章中解決這些問題。

錯誤數

內存錯誤,在某些硬件上Linux和node_exporter能夠經過EDAC,錯誤檢測和糾正報告ECC內存。若是支持,則指標爲:

node_edac_correctable_errors_total
node_edac_uncorrectable_errors_total
node_edac_csrow_correctable_errors_total
node_edac_csrow_uncorrectable_errors_total

這些指標在個人機器上沒法使用

磁盤

使用率

當咱們談論磁盤利用率和飽和度時,咱們須要考慮另外兩個方面:磁盤容量和磁盤吞吐量。

  • 磁盤容量:磁盤能夠存儲的數據量
  • 磁盤吞吐量:是每秒能夠讀寫磁盤的數量

磁盤容量的飽和度和利用率很是簡單;它僅是對所用字節數的一種度量,以可用百分比表示

sum(node_filesystem_free{mountpoint="/"}) by (node, mountpoint) / sum(node_filesystem_size{mountpoint="/"}) by (node, mountpoint)

磁盤吞吐量的利用率和飽和度尚不清楚。

若是使用旋轉磁盤,固態硬盤,RAID,網絡鏈接的硬盤或網絡塊,則須要注意不一樣的參數。正如咱們將在網絡中看到的那樣,飽和度很難在不知道底層硬件的特性的狀況下進行計算,而底層硬件的特性一般對於內核是不可知的。

每一個設備的node_exporters會公開一些磁盤寫入量之類的指標,還有

  • 運行中的IO操做:node_disk_io_now
  • IO時間:node_disk_io_time_ms
  • 加權的io時間:node_disk_io_weighted。

磁盤吞吐量顯然是一個複雜的問題,您選擇的指標將取決於硬件以及正在運行的工做負載的類型

飽和度

錯誤數

網絡

使用率

咱們要解決的最後一個資源是網絡

根據您的工做量,您可能對發送流量和接收流量比較感興趣。如今我將利用率定義爲已發送和已接收的總和。該查詢將按節點爲您提供全部網絡接口的每秒字節數:

sum(rate(node_network_receive_bytes[5m])) by (node) + sum(rate(node_network_transmit_bytes[5m])) by (node)

飽和度

不知道網絡的容量,飽和度將很難肯定。咱們可使用丟棄的數據包做爲飽和度的側面論證:

sum(rate(node_network_receive_drop[5m])) by (node) + sum(rate(node_network_transmit_drop[5m])) by (node)

錯誤數

  • node_network_receive_errs: 接受的錯誤數
  • node_network_transmit_errs:發送的錯誤數

Apiserver 指標分析

概述

kube-apiserver 是集羣全部請求的入口,指標的分析能夠反應集羣的健康狀態。

Apiserver 的指標能夠分爲如下幾大類:

  • 請求速率和延遲
  • 控制器隊列的性能
  • etcd 的性能
  • 進程狀態:文件系統、內存、CPU
  • golang 程序的狀態:GC、進程、線程

基於 RED 方法,評估 apiserver 服務的一些指標:

  • Rate 速率:每秒的請求數。
  • Error 錯誤:失敗的那些請求的數量。
  • Duration 持續時間:這些請求所花費的時間

請求速率和延遲

Rate 速率

sum(rate(apiserver_request_count[5m])) by (resource, subresource, verb)

該查詢會列出Kubernetes資源各類操做的五分鐘的速率。操做有:WATCH,PUT,POST,PATCH,LIST,GET,DELETE和CONNECT

Error 錯誤

rate(apiserver_request_count{code=~"^(?:5..)$"}[5m]) / rate(apiserver_request_count[5m])

此查詢獲取5分鐘內錯誤率與請求率的比率

Duration 請求時間

histogram_quantile(0.9, sum(rate(apiserver_request_latencies_bucket[5m]))
by (le, resource, subresource, verb) ) / 1e+06

查看 90%狀況下請求的時間分佈

隊列狀況

全部資源的請求都會被 apiserver 中的 controller 處理,controller 維護了隊列,隊列的一些指標能夠反應資源處理的速度等指標

以apiserver_admission_controller爲例:

  • apiserver_admission_controller_admission_duration_seconds:准入控制器的處理時間 以秒爲單位),經過名稱進行標識,並針對每一個操做以及API資源和類型(驗證或准入)進行細分。
  • apiserver_admission_controller_admission_latencies_milliseconds 延遲*

ETCD 的指標

API Server對etcd 的讀寫有緩存

  • etcd_helper_cache_entry_count —緩存中的元素數。
  • etcd_helper_cache_hit_count —緩存命中計數。
  • etcd_helper_cache_miss_count —緩存未命中計數。
  • etcd_request_cache_add_latencies_summary —將條目添加到緩存的時間(以微秒爲單位)。

程序指標

apiserver 是 go 程序,目前全部 prometheus 採集的指標都會包含 golang 程序指標,如:

  • go_gc_duration_seconds 程序 GC 的耗時
  • go_gc_duration_seconds_count 程序 GC 的次數
  • go_gc_duration_seconds_quantile 程序 GC 的耗時分佈
  • go_goroutines goroutines信息
  • go_info go環境信息

request

  • apiserver_request 請求信息
  • apiserver_request_count 請求次數
  • apiserver_request_duration_seconds 請求耗時

response

  • apiserver_response_sizes 每一個組,版本,動做,資源,子資源,範圍和組件的響應大小分佈(以字節爲單位)
  • apiserver_response_sizes_bucket 區間分佈
  • apiserver_response_sizes_count 返回的數量

audit

  • apiserver_audit_event: 審計事件
  • apiserver_audit_requests_rejected:審覈拒絕的請求

參考

訪問 apiserver 的 metric 時須要的參數

https://docs.signalfx.com/en/...

https://blog.freshtracks.io/a...

ETCD 指標分析

概述

Kubernetes使用etcd來存儲集羣中組件的全部狀態,它是 Kubernetes數據庫,監視etcd的性能和行爲應該是整個Kubernetes監控計劃的一部分,Etcd是用Go語言編寫的,而且與Kubernetes的其餘服務同樣,都是通過精心設計的,並使用Prometheus格式公開其指標。

由於 Etcd 是數據中心,所以訪問 metrics 時須要配置鑑權,以防數據外泄。

etcd服務器指標分爲幾個主要類別:

  • Leader的存在和Leader變更率
  • 請求已提交/已應用/正在等待/失敗
  • 磁盤寫入性能
  • 入站gRPC統計信息
  • 集羣內gRPC統計信息

Leader 選舉

Etcd是一個分佈式鍵值存儲。它使用 Rafe協議來選主。Leader能夠響應某些事件(例如節點從新啓動)而進行更改,從新在Member中選舉Leader。更換Leader是很正常的,可是過多的Leader變動也是問題的徵兆,多是網絡問題致使的網絡分區等

要確認Leader是否選出,etcd_server_has_leader值必須是1,不然就沒有leader。這是要配置的告警規則:

# alert if any etcd instance has no leader
ALERT NoLeader
IF etcd_server_has_leader{job="etcd"} == 0
FOR 1m
LABELS {
  severity = "critical"
}
ANNOTATIONS {
  summary = "etcd member has no leader",
  description = "etcd member {{ $labels.instance }} has no leader",
}

Leader變動可使用 etcd_server_leader_changes_seen_total指標,能夠經過如下PromQL查詢:

sum(rate(etcd_server_leader_changes_seen_total[5m]))

這個值應該始終爲 0,報警規則應該設置爲:

# alert if there are lots of leader changes
ALERT HighNumberOfLeaderChanges
IF increase(etcd_server_leader_changes_seen_total{job="etcd"}[1h]) > 3
LABELS {
  severity = "warning"
}
ANNOTATIONS {
  summary = "a high number of leader changes within the etcd cluster are happening",
  description = "etcd instance {{ $labels.instance }} has seen {{ $value }} leader changes within the last hour",
}

請求狀況

發送到etcd的寫入和配置更改稱爲投票。Raft 協議確保將其正確提交到集羣中。相關 metric 有:

  • etcd_server_proposals_committed_total
  • etcd_server_proposals_applied_total
  • etcd_server_proposals_pending
  • etcd_server_proposals_failed_total

失敗數目過多應該報警,報警規則應該配置爲:

# alert if there are several failed proposals within an hour
ALERT HighNumberOfFailedProposals
IF increase(etcd_server_proposals_failed_total{job="etcd"}[1h]) > 5
LABELS {
  severity = "warning"
}
ANNOTATIONS {
  summary = "a high number of proposals within the etcd cluster are failing",
  description = "etcd instance {{ $labels.instance }} has seen {{ $value }} proposal failures within the last hour",
}

磁盤寫入能力

磁盤性能是etcd服務器性能的主要衡量指標,由於在follwer能夠確認Leader的提議以前,必須將提案寫入磁盤並進行同步。

要注意的兩個重要指標是

  • etcd_disk_wal_fsync_duration_seconds_bucket
  • etcd_disk_backend_commit_duration_seconds_bucket
# etcd disk io latency alerts
# ===========================
# alert if 99th percentile of fsync durations is higher than 500ms
ALERT HighFsyncDurations
IF histogram_quantile(0.99, rate(etcd_disk_wal_fsync_duration_seconds_bucket[5m])) > 0.5
FOR 10m
LABELS {
  severity = "warning"
}
ANNOTATIONS {
  summary = "high fsync durations",
  description = "etcd instance {{ $labels.instance }} fync durations are high",
}
# alert if 99th percentile of commit durations is higher than 250ms
ALERT HighCommitDurations
IF histogram_quantile(0.99, rate(etcd_disk_backend_commit_duration_seconds_bucket[5m])) > 0.25
FOR 10m
LABELS {
  severity = "warning"
}
ANNOTATIONS {
  summary = "high commit durations",
  description = "etcd instance {{ $labels.instance }} commit durations are high",
}

GRPC指標

Etcd使用gRPC在集羣中的每一個節點之間進行通訊。最好跟蹤這些請求的性能和錯誤數。

指標etcd_grpc_total表示按方法分類的grpc調用總數。
etc_grpc_requests_failed_total表示失敗次數。

# gRPC request alerts
# ===================
# alert if more than 1% of gRPC method calls have failed within the last 5 minutes
ALERT HighNumberOfFailedGRPCRequests
IF sum by(grpc_method) (rate(etcd_grpc_requests_failed_total{job="etcd"}[5m]))
  / sum by(grpc_method) (rate(etcd_grpc_total{job="etcd"}[5m])) > 0.01
FOR 10m
LABELS {
  severity = "warning"
}
ANNOTATIONS {
  summary = "a high number of gRPC requests are failing",
  description = "{{ $value }}% of requests for {{ $labels.grpc_method }} failed on etcd instance {{ $labels.instance }}",
}
# alert if more than 5% of gRPC method calls have failed within the last 5 minutes
ALERT HighNumberOfFailedGRPCRequests
IF sum by(grpc_method) (rate(etcd_grpc_requests_failed_total{job="etcd"}[5m]))
  / sum by(grpc_method) (rate(etcd_grpc_total{job="etcd"}[5m])) > 0.05
FOR 5m
LABELS {
  severity = "critical"
}
ANNOTATIONS {
  summary = "a high number of gRPC requests are failing",
  description = "{{ $value }}% of requests for {{ $labels.grpc_method }} failed on etcd instance {{ $labels.instance }}",
}
# alert if the 99th percentile of gRPC method calls take more than 150ms
ALERT GRPCRequestsSlow
IF histogram_quantile(0.99, rate(etcd_grpc_unary_requests_duration_seconds_bucket[5m])) > 0.15
FOR 10m
LABELS {
  severity = "critical"
}
ANNOTATIONS {
  summary = "slow gRPC requests",
  description = "on etcd instance {{ $labels.instance }} gRPC requests to {{ $label.grpc_method }} are slow",
}

如何查看 etcd 的讀寫磁盤的 Latency?

能夠經過etcd 的 metrics計算得出:5m 內的磁盤IO 延遲(99%區間)。如大於 500ms 報警

histogram_quantile(0.99, rate(etcd_disk_wal_fsync_duration_seconds_bucket{clusterID=」c-07v3Y2v5」,instanceIP=」100.70.181.251」}[5m])) > 0.5
相關文章
相關標籤/搜索