做者:徐亞鬆 原文:http://www.xuyasong.com/?p=1921
監控系統的歷史悠久,是一個很成熟的方向,而 Prometheus 做爲新生代的開源監控系統,慢慢成爲了雲原生體系的事實標準,也證實了其設計很受歡迎。node
本文主要分享在 Prometheus 實踐中遇到的一些問題和思考,若是你對 K8S 監控體系或 Prometheus 的設計還不太瞭解,能夠先看下容器監控系列。mysql
幾點原則:nginx
Prometheus 當前最新版本爲 2.16,Prometheus 還在不斷迭代,所以儘可能用最新版,1.X版本就不用考慮了。git
2.16 版本上有一套實驗 UI,能夠查看 TSDB 的狀態,包括Top 10的 Label、Metric.github
Prometheus 屬於 CNCF 項目,擁有完整的開源生態,與 Zabbix 這種傳統 agent 監控不一樣,它提供了豐富的 exporter 來知足你的各類需求。你能夠在這裏看到官方、非官方的 exporter。若是仍是沒知足你的需求,你還能夠本身編寫 exporter,簡單方便、自由開放,這是優勢。sql
可是過於開放就會帶來選型、試錯成本。以前只須要在 zabbix agent裏面幾行配置就能完成的事,如今你會須要不少 exporter 搭配才能完成。還要對全部 exporter 維護、監控。尤爲是升級 exporter 版本時,很痛苦。非官方exporter 還會有很多 bug。這是使用上的不足,固然也是 Prometheus 的設計原則。docker
K8S 生態的組件都會提供/metric接口以提供自監控,這裏列下咱們正在使用的:數據庫
還有各類場景下的自定義 exporter,如日誌提取後面會再作介紹。segmentfault
k8s 集羣運行中須要關注核心組件的狀態、性能。如 kubelet、apiserver 等,基於上面提到的 exporter 的指標,能夠在 Grafana 中繪製以下圖表:後端
模板能夠參考dashboards-for-kubernetes-administrators,根據運行狀況不斷調整報警閾值。
這裏提一下 Grafana 雖然支持了 templates 能力,能夠很方便地作多級下拉框選擇,可是不支持templates 模式下配置報警規則,相關issue
官方對這個功能解釋了一堆,可最新版本仍然沒有支持。借用 issue 的一句話吐槽下:
It would be grate to add templates support in alerts. Otherwise the feature looks useless a bit.
Prometheus 體系中 Exporter 都是獨立的,每一個組件各司其職,如機器資源用 Node-Exporter,Gpu 有Nvidia Exporter等等。可是 Exporter 越多,運維壓力越大,尤爲是對 Agent作資源控制、版本升級。咱們嘗試對一些Exporter進行組合,方案有二:
另外,Node-Exporter 不支持進程監控,能夠加一個Process-Exporter,也能夠用上邊提到的Telegraf,使用 procstat 的 input來採集進程指標。
採集的指標有不少,咱們應該關注哪些?Google 在「Sre Handbook」中提出了「四個黃金信號」:延遲、流量、錯誤數、飽和度。實際操做中可使用 Use 或 Red 方法做爲指導,Use 用於資源,Red 用於服務。
Prometheus 採集中常見的服務分三種:
對 Use 和 Red 的實際示例能夠參考容器監控實踐—K8S經常使用指標分析這篇文章。
在 K8S 1.16版本,Cadvisor 的指標去掉了 pod_Name 和 container_name 的 label,替換爲了pod 和 container。若是你以前用這兩個 label 作查詢或者 Grafana 繪圖,須要更改下 Sql 了。由於咱們一直支持多個 K8S 版本,就經過 relabel配置繼續保留了原來的**_name。
metric_relabel_configs: - source_labels: [container\] regex: (.+) target_label: container_name replacement: $1 action: replace - source_labels: [pod] regex: (.+) target_label: pod_name replacement: $1 action: replace
注意要用 metric_relabel_configs,不是 relabel_configs,採集後作的replace。
Prometheus 若是部署在K8S集羣內採集是很方便的,用官方給的Yaml就能夠,但咱們由於權限和網絡須要部署在集羣外,二進制運行,採集多個 K8S 集羣。
以 Pod 方式運行在集羣內是不須要證書的(In-Cluster 模式),但集羣外須要聲明 token之類的證書,並替換address,即便用 Apiserver Proxy採集,以 Cadvisor採集爲例,Job 配置爲:
- job_name: cluster-cadvisor honor_timestamps: true scrape_interval: 30s scrape_timeout: 10s metrics_path: /metrics scheme: https kubernetes_sd_configs: - api_server: https://xx:6443 role: node bearer_token_file: token/cluster.token tls_config: insecure_skip_verify: true bearer_token_file: token/cluster.token tls_config: insecure_skip_verify: true relabel_configs: - separator: ; regex: __meta_kubernetes_node_label_(.+) replacement: $1 action: labelmap - separator: ; regex: (.*) target_label: __address__ replacement: xx:6443 action: replace - source_labels: [__meta_kubernetes_node_name] separator: ; regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor action: replace metric_relabel_configs: - source_labels: [container] separator: ; regex: (.+) target_label: container_name replacement: $1 action: replace - source_labels: [pod] separator: ; regex: (.+) target_label: pod_name replacement: $1 action: replace
bearer_token_file 須要提早生成,這個參考官方文檔便可。記得 base64 解碼。
對於 cadvisor 來講,__metrics_path__
能夠轉換爲/api/v1/nodes/{1}/proxy/metrics/cadvisor
,表明Apiserver proxy 到 Kubelet,若是網絡能通,其實也能夠直接把 Kubelet 的10255做爲 target,能夠直接寫爲:{1}:10255/metrics/cadvisor,表明直接請求Kubelet,規模大的時候還減輕了 Apiserver 的壓力,即服務發現使用 Apiserver,採集不走 Apiserver
由於 cadvisor 是暴露主機端口,配置相對簡單,若是是 kube-state-metric 這種 Deployment,以 endpoint 形式暴露,寫法應該是:
- job_name: cluster-service-endpoints honor_timestamps: true scrape_interval: 30s scrape_timeout: 10s metrics_path: /metrics scheme: https kubernetes_sd_configs: - api_server: https://xxx:6443 role: endpoints bearer_token_file: token/cluster.token tls_config: insecure_skip_verify: true bearer_token_file: token/cluster.token tls_config: insecure_skip_verify: true relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] separator: ; regex: "true" replacement: $1 action: keep - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] separator: ; regex: (https?) target_label: __scheme__ replacement: $1 action: replace - separator: ; regex: (.*) target_label: __address__ replacement: xxx:6443 action: replace - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_endpoints_name, __meta_kubernetes_service_annotation_prometheus_io_port] separator: ; regex: (.+);(.+);(.*) target_label: __metrics_path__ replacement: /api/v1/namespaces/${1}/services/${2}:${3}/proxy/metrics action: replace - separator: ; regex: __meta_kubernetes_service_label_(.+) replacement: $1 action: labelmap - source_labels: [__meta_kubernetes_namespace] separator: ; regex: (.*) target_label: kubernetes_namespace replacement: $1 action: replace - source_labels: [__meta_kubernetes_service_name] separator: ; regex: (.*) target_label: kubernetes_name replacement: $1 action: replace
對於 endpoint 類型,須要轉換__metrics_path__
爲/api/v1/namespaces/{1}/services/{2}:${3}/proxy/metrics,須要替換 namespace、svc 名稱端口等,這裏的寫法只適合接口爲/metrics的exporter,若是你的 exporter 不是/metrics接口,須要替換這個路徑。或者像咱們同樣統一約束都使用這個地址。
這裏的__meta_kubernetes_service_annotation_prometheus_io_port來源就是 exporter 部署時寫的那個 annotation,大多數文章中只提到prometheus.io/scrape: ‘true’,但也能夠定義端口、路徑、協議。以方便在採集時作替換處理。
其餘的一些 relabel 如kubernetes_namespace 是爲了保留原始信息,方便作 promql 查詢時的篩選條件。
若是是多集羣,一樣的配置多寫幾遍就能夠了,通常一個集羣能夠配置三類job:
nvidia-smi能夠查看機器上的 GPU 資源,而Cadvisor 其實暴露了Metric來表示容器使用 GPU 狀況,
container_accelerator_duty_cycle container_accelerator_memory_total_bytes container_accelerator_memory_used_bytes
若是要更詳細的 GPU 數據,能夠安裝dcgm exporter,不過K8S 1.13 才能支持。
Prometheus 爲避免時區混亂,在全部組件中專門使用 Unix Time 和 Utc 進行顯示。不支持在配置文件中設置時區,也不能讀取本機 /etc/timezone 時區。
其實這個限制是不影響使用的:
關於 timezone 的討論,能夠看這個issue。
假如你有一個負載均衡 LB,但網絡上 Prometheus 只能訪問到 LB 自己,訪問不到後面的 RS,應該如何採集 RS 暴露的 Metric?
隨着規模變大,Prometheus 須要的 CPU 和內存都會升高,內存通常先達到瓶頸,這個時候要麼加內存,要麼集羣分片減小單機指標。這裏咱們先討論單機版 Prometheus 的內存問題。
緣由:
這裏面有必定的優化空間。
個人指標須要多少內存:
以咱們的一個 Prometheus Server爲例,本地只保留 2 小時數據,95 萬 Series,大概佔用的內存以下:
有什麼優化方案:
2.14 以上能夠看 Tsdb 狀態
Prometheus 內存佔用分析:
相關 issue:
容量規劃除了上邊說的內存,還有磁盤存儲規劃,這和你的 Prometheus 的架構方案有關。
Prometheus 每2小時將已緩衝在內存中的數據壓縮到磁盤上的塊中。包括Chunks、Indexes、Tombstones、Metadata,這些佔用了一部分存儲空間。通常狀況下,Prometheus 中存儲的每個樣本大概佔用1-2字節大小(1.7Byte)。能夠經過Promql來查看每一個樣本平均佔用多少空間:
rate(prometheus_tsdb_compaction_chunk_size_bytes_sum[1h])/ rate(prometheus_tsdb_compaction_chunk_samples_sum[1h]){instance="0.0.0.0:8890", job="prometheus"} 1.252747585939941
若是大體估算本地磁盤大小,能夠經過如下公式:
磁盤大小=保留時間*每秒獲取樣本數*樣本大小
保留時間(retention_time_seconds)和樣本大小(bytes_per_sample)不變的狀況下,若是想減小本地磁盤的容量需求,只能經過減小每秒獲取樣本數(ingested_samples_per_second)的方式。
查看當前每秒獲取的樣本數:
rate(prometheus_tsdb_head_samples_appended_total[1h])
有兩種手段,一是減小時間序列的數量,二是增長採集樣本的時間間隔。考慮到 Prometheus 會對時間序列進行壓縮,所以減小時間序列的數量效果更明顯。
舉例說明:
採集頻率 30s,機器數量1000,Metric種類6000,1000600026024 約 200 億,30G 左右磁盤。
只採集須要的指標,如 match[], 或者統計下最常使用的指標,性能最差的指標。
以上磁盤容量並無把 wal 文件算進去,wal 文件(Raw Data)在 Prometheus 官方文檔中說明至少會保存3個 Write-Ahead Log Files,每個最大爲128M(實際運行發現數量會更多)。
由於咱們使用了 Thanos 的方案,因此本地磁盤只保留2H 熱數據。Wal 每2小時生成一份Block文件,Block文件每2小時上傳對象存儲,本地磁盤基本沒有壓力。
關於 Prometheus 存儲機制,能夠看這篇。
若是你的 Prometheus 使用了 kubernetes_sd_config 作服務發現,請求通常會通過集羣的 Apiserver,隨着規模的變大,須要評估下對 Apiserver性能的影響,尤爲是Proxy失敗的時候,會致使CPU 升高。固然了,若是單K8S集羣規模太大,通常都是拆分集羣,不過隨時監測下 Apiserver 的進程變化仍是有必要的。
在監控Cadvisor、Docker、Kube-Proxy 的 Metric 時,咱們一開始選擇從 Apiserver Proxy 到節點的對應端口,統一設置比較方便,但後來仍是改成了直接拉取節點,Apiserver 僅作服務發現。
Prometheus 中的 Counter 類型主要是爲了 Rate 而存在的,即計算速率,單純的 Counter 計數意義不大,由於 Counter 一旦重置,總計數就沒有意義了。
Rate 會自動處理 Counter 重置的問題,Counter 通常都是一直變大的,例如一個 Exporter 啓動,而後崩潰了。原本以每秒大約10的速率遞增,但僅運行了半個小時,則速率(x_total [1h])將返回大約每秒5的結果。另外,Counter 的任何減小也會被視爲 Counter 重置。例如,若是時間序列的值爲[5,10,4,6],則將其視爲[5,10,14,16]。
Rate 值不多是精確的。因爲針對不一樣目標的抓取發生在不一樣的時間,所以隨着時間的流逝會發生抖動,query_range 計算時不多會與抓取時間完美匹配,而且抓取有可能失敗。面對這樣的挑戰,Rate 的設計必須是健壯的。
Rate 並不是想要捕獲每一個增量,由於有時候增量會丟失,例如實例在抓取間隔中掛掉。若是 Counter 的變化速度很慢,例如每小時僅增長几回,則可能會致使【假象】。好比出現一個 Counter 時間序列,值爲100,Rate 就不知道這些增量是如今的值,仍是目標已經運行了好幾年而且纔剛剛開始返回。
建議將 Rate 計算的範圍向量的時間至少設爲抓取間隔的四倍。這將確保即便抓取速度緩慢,且發生了一次抓取故障,您也始終可使用兩個樣本。此類問題在實踐中常常出現,所以保持這種彈性很是重要。例如,對於1分鐘的抓取間隔,您可使用4分鐘的 Rate 計算,可是一般將其四捨五入爲5分鐘。
若是 Rate 的時間區間內有數據缺失,他會基於趨勢進行推測,好比:
若有錯誤或其它問題,歡迎小夥伴留言評論、指正。若有幫助,歡迎點贊+轉發分享。
歡迎你們關注民工哥的公衆號:民工哥技術之路