<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          打造大型分布式監(jiān)控系統(tǒng)

          共 8480字,需瀏覽 17分鐘

           ·

          2021-04-08 10:06

          打造云原生大型分布式監(jiān)控系統(tǒng)

          笑談監(jiān)控系統(tǒng)

          隨著時間的積累,出現(xiàn)故障的風險越來越高,事故的發(fā)生總是出人預料,如果采用人力運維的方式,對于故障定位、故障處理都是很大的挑戰(zhàn)。故障的時間越長,面臨的損失越大,所以在發(fā)展到一定程度的團隊都需要一套完善的監(jiān)控系統(tǒng)

          監(jiān)控大屏

          一套完善的監(jiān)控系統(tǒng)最重要的就是本身永遠不可以故障,即使平臺故障也要確保監(jiān)控可能告警出來,所以監(jiān)控系統(tǒng)本身的高可用,是我們一直在追求的,先來看看一個完備的監(jiān)控系統(tǒng)應該考慮哪些功能

          監(jiān)控系統(tǒng)設計面臨什么問題

          監(jiān)控系統(tǒng)會對很多角色進行監(jiān)控,我把他分為這幾個大類:服務器、容器、服務或應用、網(wǎng)絡、存儲、中間件,根據(jù)業(yè)界的方案,不同的分類使用不同的采集器進行采集

          在功能上要考慮哪些問題?

          • 支持標記不同監(jiān)控指標來源,方便理清楚業(yè)務來源
          • 支持聚合運算,轉(zhuǎn)換指標的含義、組合用來進行計算、匯總、分析
          • 告警、報表、圖形化大屏展示
          • 保存歷史數(shù)據(jù)便于溯源

          在易用性上應該考慮

          • 支持配置增減監(jiān)控項,自定義監(jiān)控

          • 支持配置表達式進行計算

          • 最好有自動發(fā)現(xiàn),在新增服務器或新增pod等資源時自動納入監(jiān)控

          • 支持配置告警策略定義告警范圍與閾值,支持自定義告警

          方案選型

          從以上方面考慮,應該選用哪些開源方案呢?業(yè)界常見的有ElasticsearchNagioszabbixprometheus,其他方案比較小眾不做討論

          方案選型
          • Elasticsearch 是一個實時的分布式搜索和分析引擎,支持分片、搜索速度快,一般和LogstashKibana結(jié)合起來一起用,也就是ELK,更擅長文檔日志的搜索分析

          • Nagios: 優(yōu)點是出錯的服務器、應用和設備會自動重啟,自動日志滾動;配置靈活,可以自定義 shell 腳本,通過分布式監(jiān)控模式;并支持以冗余方式進行主機監(jiān)控,報警設置多樣,以及命令重新加載配置文件無需打擾 Nagios 的運行。缺點是事件控制臺功能很弱,插件易用性差;對性能、流量等指標的處理不給力;看不到歷史數(shù)據(jù),只能看到報警事件,很難追查故障原因;配置復雜,初學者投入的時間、精力和成本比較大。

          • zabbix入門容易、上手簡單、功能強大,容易配置和管理,但是深層次需求需要非常熟悉 zabbix 并進行大量的二次定制開發(fā),二次開發(fā)太多是不可接受的

          • prometheus幾乎支撐了上面所有的需求,可視化展示可以接入grafana,可以用promSQL語言來做聚合查詢,不需要定制;可以使用打tag的方式,對每個指標分類;強大的社區(qū)針對各種應用、網(wǎng)絡、服務器等設備、角色都提供了采集方案以及無侵入式的高可用方案,這個就是今天討論的重點

          根據(jù)上面的種種原因,綜合來看prometheus比較合適

          prometheus與他的缺陷

          prometheus架構(gòu)圖
          • 從上面的架構(gòu)圖可以看出,prometheus是在客戶端部署采集器(exporter)的形式來采集數(shù)據(jù),服務端主動向prometheus通信來拉取數(shù)據(jù)

          • 客戶端也可以通過推送數(shù)據(jù)到PushGateway再交給prometheus拉取

          • prometheus有自動發(fā)現(xiàn)的能力,簡單配置以后就可以主動拉取平臺接口獲取監(jiān)控范圍:azure、consul、openstack等,并針對檢測角色配置tag,如果和業(yè)務強相關,可以定制修改代碼,拉取自己平臺的接口來識別監(jiān)控角色和動態(tài)打tag

          • prometheus也有告警的能力,接入官方提供的AlertManager組件可以檢測產(chǎn)生告警,再使用webhook接入自己的告警郵件/短信通知平臺

            • 這里的問題在于無法通過頁面配置告警策略、也無法存儲告警記錄,可以在AlertManager后面加一些組件來告警收斂、靜默、分組、存儲

            • 告警策略的動態(tài)配置,可以寫程序根據(jù)策略生成告警配置、放到prometheus指定目錄下,并調(diào)用prometheus熱更新接口

          唯一要解決的就是負載量大時出現(xiàn)的性能問題以及高可用問題

          單機prometheus的部署存在的問題

          prometheus的架構(gòu)決定是他更適合單機的部署方案,單機部署在壓力過大時可以通過服務器升配的方式緩解壓力,但是依然會存在共性的問題

          單點prometheus的問題
          • 采集速率會因為cpu/網(wǎng)絡通信限制導致卡頓,采集速度變慢,指標在周期內(nèi)未主動拉取的時候會丟失本次的指標,這里可以把采集周期拉長,后果是粒度變粗,不建議拉太長;另一種方式就是減少無用指標的采集

          • 查詢時也是因為同樣的原因速度會受到限制,數(shù)據(jù)存儲時間范圍過多時,對磁盤會有很大的壓力

          • 單點故障時就完全沒有辦法了,直接服務不可用

          單點高負載考慮什么方案?

          參考前一次的文章,高負載的時候自動水平擴展,并做負載均衡,首先想到的水平擴展方式就是Prometheus提供的分組能力

          分片采集

          相應于把prometheus分片,通過配置的方式各采集部分節(jié)點,這種方式有三個問題

          • 數(shù)據(jù)分散運維困難

          • 要來回切換數(shù)據(jù)源,看不到全局視圖

          解決這個問題,考慮增加一個存儲位置匯總數(shù)據(jù)(remote write)

          分片后匯總

          這里考慮使用TSDB匯總,需要支持擴容的、支持集群保證高可用的TSDB

          但是需要在TSDB上層再加一個查詢組件來做查詢,會喪失原生的查詢語句能力,可以考慮把TSDB替換成prometheus節(jié)點,用聯(lián)邦的形式存儲

          聯(lián)邦

          這種情況可以滿足基本的使用要求,通過prometheus自監(jiān)控來通知運維人員手動擴容修改分組,有沒有更自動一點的方式呢?

          彈性伸縮(自動水平伸縮)

          彈性伸縮的前提有三個

          • 要能監(jiān)控當前節(jié)點負載狀態(tài),預判擴容時機

          • 需要維護服務啟停方式、自動創(chuàng)建服務并放到相應節(jié)點上

          • 同時要能修改prometheus各節(jié)點數(shù)據(jù)采集范圍

          k8s做容器編排是最直接的方案,可以解決創(chuàng)建和銷毀服務的問題,也是可以通過cpu使用率或自定義指標完成橫向擴容的,但解決不了的問題是修改prometheus節(jié)點配置,動態(tài)分配采集范圍,考慮使用以下方案

          調(diào)度器
          • prometheus注意要配置節(jié)點反親和性(k8s配置podAntiAffinity

          • 寫一個調(diào)度器通過k8s api檢測prometheus節(jié)點狀態(tài)

          • 通過k8s檢測節(jié)點故障以及負載情況,使用hash分攤壓力,擴展prometheussd自動發(fā)現(xiàn)功能,帶上自己的hostname來獲取調(diào)度器提供的數(shù)據(jù)范圍

          用這種方式就不需要修改配置文件了,因為是prometheus接口端定時更新監(jiān)控范圍

          • 根據(jù)具體運行情況伸縮prometheus,不需要再配置configmap

          到這里你可能有一個疑問,假如我監(jiān)控服務器用上面的方式,那么多接收端,再加一個redis集群的監(jiān)控,應該放到哪個節(jié)點上呢?答案是可以專門創(chuàng)建獨立于此自動伸縮方案的prometheus來進行少量數(shù)據(jù)監(jiān)控,或者直接放到所有節(jié)點上,在上層再考慮去重的問題,這個我們一會討論。

          到目前為止分片以后分散了壓力,但還沒有解決的問題是數(shù)據(jù)分散無法匯總查詢、單點故障數(shù)據(jù)丟失的問題。

          匯總查詢可能你會想到剛剛說的聯(lián)邦部署,但壓力又匯總到一點上了,不能根本的解決問題;解決單點故障應該使用冗余的形式部署,給每個監(jiān)控范圍分配2個及以上監(jiān)控節(jié)點,但會導致客戶端拉取次數(shù)翻倍,也不建議。

          如何保證單點故障數(shù)據(jù)不丟失

          為了避免無法匯總查詢、單點故障數(shù)據(jù)丟失的問題,這里打算接入一個高可用方案thanos,把prometheus設置為無狀態(tài)應用,并開啟遠程寫把數(shù)據(jù)推送到thanos

          推送到thanos

          這樣的話prometheus本身不存儲數(shù)據(jù),即使掛掉部分節(jié)點,只要保證node夠多也會再自動伸縮出新的節(jié)點,期間讀取到的采集范圍會先負載變大,然后又得到緩解,整個過程在2個周期內(nèi)解決

          PS: ,Prometheus在將采集到的指標寫入遠程存儲之前,會先緩存在內(nèi)存隊列中,然后打包發(fā)送給遠端存儲,以減少連接數(shù)量,要提高寫入速率需要修改配置項queue_config

          簡單介紹下thanosthanos是無侵入式的高可用方案,負責對prometheus產(chǎn)生的數(shù)據(jù)進行匯總、計算、去重、壓縮、存儲、查詢、告警,他實現(xiàn)了prometheus提供的查詢接口,對外部而言查詢prometheus還是查詢thanos的效果完全一樣,是無感知的

          一起來實現(xiàn)分布式高可用監(jiān)控系統(tǒng)

          如何讓我們來實現(xiàn)一個這樣的組件,你會怎么做呢?

          匯總存儲,上層完成其他功能

          把分片數(shù)據(jù)寫入到存儲,其他組件和存儲通信,thanos的主流方案也是這么做的

          thanos架構(gòu)圖

          如上圖所示所有的組件都會與對象存儲通信,完成數(shù)據(jù)存儲或者讀取的功能

          • 使用對象存儲做存儲引擎

          • prometheus節(jié)點一同部署sidecar,每個節(jié)點對應一個,定期放數(shù)據(jù)推送到對象存儲

          • Ruler負責判定告警以及根據(jù)規(guī)則做指標聚合運算

          • Compact負責降準壓縮,一份數(shù)據(jù)變?nèi)荩话闶欠譃?分鐘、5分鐘、1小時寫回存儲,查詢時間粒度越大呈現(xiàn)指標粒度越粗,防止前端數(shù)據(jù)刷爆

          • Query與其他組件通過grpc的方式進行通信讀取數(shù)據(jù),它不和對象存儲直接通信,而是在中間加了一層gateway網(wǎng)關

          • 上圖的方案sidecar不是我這次的架構(gòu),其他是一樣的,sidecar的原理是把采集到的數(shù)據(jù)使用緩存到本地(默認2小時數(shù)據(jù)為熱數(shù)據(jù)),冷數(shù)據(jù)才推送,近期數(shù)據(jù)存儲本地,查詢時再做匯總會有一定的壓力,同時單點故障問題還是沒有解決

          如果是小規(guī)模集群無網(wǎng)絡壓力可以使用sidercar

          不要在接收端存儲

          prometheus部署在一起的sidercar違背了容器中的簡單性原則,也提高存儲壓力,把他們剝離開試試?

          匯總再轉(zhuǎn)存

          我的想法是收集數(shù)據(jù)推送,然后進行存儲,由其他組件完成與存儲的通信

          receive方案

          如上圖,Receive組件實現(xiàn)了remote write接口,Prometheus可以將數(shù)據(jù)實時推送到Receive上;Receive本身實際上相當于一個沒有收集功能的Prometheus,那此時Prometheus就不再需要存儲數(shù)據(jù),之前的方案就可以實施了

          • 對象存儲中的數(shù)據(jù)具有不可修改特性,也就是說一旦寫入就變成只讀了

          • Prometheus本地存儲的原理是接受到的數(shù)據(jù)寫到本地文件存儲里面組成WAL文件列表,Receive也是這么做的,然后超過一定時限后生成block,這些block會上傳到對象存儲

          • Query組件來近期數(shù)據(jù)(默認2小時內(nèi))查詢recevie,過期后使用對象存儲

          • receive使用k8s的dnssrv功能做服務發(fā)現(xiàn),便于下游拉取數(shù)據(jù)而不要使用k8s的service:ip自帶的負載均衡

          • receive自帶了hash算法,可以把上游遠程寫過來的流量均勻分布在各個節(jié)點上,這里可以采用k8s的service自動輪訓,recevie會把請求route到相應節(jié)點上

          為防止prometheus掛掉一個導致的數(shù)據(jù)丟失問題,給prometheus加一個副本,然后在query時去重,主要由query--query.replica-label 參數(shù)和Prometheus 配置的 prometheus_replica參數(shù)來實現(xiàn),如下圖

          概覽

          同樣的其他組件,如ruler也可以配置冗余部署rule_replica就不展開講了

          還好recevie自帶了分布式一致性算法,不然就要自己實現(xiàn)一個了,到此我們解決了

          • 數(shù)據(jù)接收端能應對海量數(shù)據(jù)的壓力均衡

          • 解決了prometheus部署在不同集群上時查詢延遲高的問題

          • 解決了跨節(jié)點數(shù)據(jù)復合運算(ruler

          • 解決了數(shù)據(jù)壓縮降準

          hashring真的是分布式一致性算法嗎

          我們知道分布式一致性算法可以解決下面的問題

          • 在壓力增加時做到自動擴容,壓力減小時自動縮容

          • 擴縮容時必須要保障數(shù)據(jù)不丟失,單點故障時數(shù)據(jù)也不可以丟失

          • 擴縮容時數(shù)據(jù)映射落點要一致,不然會出現(xiàn)數(shù)據(jù)斷連

          但是實際使用過程中,不難發(fā)現(xiàn),還是會發(fā)生數(shù)據(jù)丟失,這引起了我的興趣

          這一塊的官網(wǎng)介紹很少,hashringendpoints參考下面的代碼,你會發(fā)現(xiàn)0 1 2 的方式就是k8sstatefulsetpod 分配的name,所以recevie要以sts的方式部署,并提前把副本數(shù)與配置關系對應起來,3節(jié)點已經(jīng)可以支撐很大數(shù)量的數(shù)據(jù)處理了

          thanos-receive-hashrings.json: |
              [
                {
                  "hashring": "soft-tenants",
                  "endpoints":
                  [
                    "thanos-receive-0.thanos-receive.thanos.svc.cluster.local:10901",
                    "thanos-receive-1.thanos-receive.thanos.svc.cluster.local:10901",
                    "thanos-receive-2.thanos-receive.thanos.svc.cluster.local:10901"
                  ]
                }
              ]

          在源碼里發(fā)現(xiàn),實際上這里并沒有使用分布式一致性算法!!hashring.go函數(shù)里可以看到,這是一個簡單的hash mod,所以hashring是有誤導性的

          func (s simpleHashring) GetN(tenant string, ts *prompb.TimeSeries, n uint64) (string, error) {
           if n >= uint64(len(s)) {
            return "", &insufficientNodesError{have: uint64(len(s)), want: n + 1}
           }
           return s[(hash(tenant, ts)+n)%uint64(len(s))], nil
          }

          提煉出來是這樣的hash算法

          hash(string(tenant_id) + sort(timeseries.labelset).join())
          • tenant_id是指數(shù)據(jù)源帶上租戶,可以給不同租戶分配自己的hash

          • 具體的hash算法使用xxHash 參考文末資料5

          解決的辦法也有了,可以通過配置多副本冗余的方式,把receive的數(shù)據(jù)冗余到其他位置,設置receive.replication-factor配置,然后拉取數(shù)據(jù)的時候因為使用的是服務發(fā)現(xiàn),和所有服務通信的方式,可以在一定程序上保證數(shù)據(jù)不丟失

          PS: 冗余也會有點問題,算法是先選hash mod后的節(jié)點,比如是第n個,然后如果factor是2,就再選n+1n+2,然后發(fā)請求給n,這個時候如果n掛了其實會失敗,相對而言n+1或者n+2節(jié)點掛了的話不會對這部分的數(shù)據(jù)有影響

          當receive出現(xiàn)故障是怎么處理的

          當發(fā)生擴縮容的時候,由于hashring發(fā)生變化,所有的節(jié)點需要將write-ahead-log的數(shù)據(jù)flushTSDB塊并上傳到OSS中(如果配置了的話),因為這些節(jié)點之后將有一個新的分配。之前已存在節(jié)點上的時間序列不需要作調(diào)整,只是后面過來的請求按新的分發(fā)來尋找該去的receiver節(jié)點。

          這個過程不需要重啟receive,代碼里有watch,可以檢測hashring的變化

          注意,這種情況發(fā)生的flush可能會產(chǎn)生較小的TSDB塊,但compactor模塊可以將它們優(yōu)化合并,因此不會有什么問題。

          當有receiver節(jié)點發(fā)生故障時,prometheus的遠程寫會在后端目標無響應或503時進行重試,因此,receiver一定時間的服務掛掉是可以容忍的。如果這種掛機時間是不可接受的話,可以將副本數(shù)配置為 3 或以上,這樣即使有一個receiver節(jié)點掛掉,還有其他receiver節(jié)點來接收寫請求

          業(yè)務指標計算問題

          如果有非常復雜的業(yè)務指標,需要從其他地方采集推送,最好的方式是寫成采集器exporter,在ruler進行復合運算,當然也有可能出現(xiàn)表達式寫不出來的尷尬問題

          考慮寫成k8sjob定時任務,把數(shù)據(jù)推送到PushGateway,再交給prometheus去拉取

          PS1: 注意按exporter的開發(fā)標準,不允許出現(xiàn)重復指標哦

          PS2:如果要刪除過期的垃圾數(shù)據(jù)可以調(diào)用PushGatewayhttp://%s/metrics/job/%s/instance/%s/host/接口進行刪除

          告警策略動態(tài)更新/告警記錄儲存的問題

          要動態(tài)生成告警策略,可以寫一個服務接收請求,調(diào)用k8s生成configmap,并通知ruler進行熱更新

          • 更新策略配置文件configmap(同步更新到pod里會有一定的延遲,使用subPath是無法熱更新的,注意configMapAndSecretChangeDetectionStrategy: Watch參數(shù)必須為默認參數(shù)Watch
          • 把configmap掛載相應的ruler上面

          全景視圖

          全景視圖

          最后

          當然對于一個成熟的監(jiān)控系統(tǒng)來說,除了發(fā)現(xiàn)故障及時告警以外,還應該有更多的功能,這不是本次討論的范圍,如果有時間未來會寫寫

          • 運營故障報表和資源日報周報月報等用于趨勢分析
          • 低負載報表用于分析服務器利用率,防止資源浪費
          • 有了故障趨勢和更多的重要指標覆蓋,可以結(jié)合AI進行故障預測,在故障發(fā)生前提前預測

          最后的最后

          針對全k8s的集群監(jiān)控來說,還有更簡單的方式來監(jiān)控,那就是Prometheus Operator,可以非常簡單的創(chuàng)建k8s的資源,比如收集器Prometheus、采集器的抽象ServiceMonitorAlertManager等,要監(jiān)控什么數(shù)據(jù)就變成直接操作k8s集群的資源對象了

          監(jiān)控可能為其他應用的水平伸縮服務服務,使用Prometheus Adpater來自定義監(jiān)控某些指標,來達到自動擴縮容的目的

          監(jiān)控還可以為運維平臺服務,提供故障自動修復

          一句話,只要監(jiān)控運維平臺做得足夠好,運維人員都得失業(yè)

          引用與拓展資料

          • 1、7 款你不得不了解的開源云監(jiān)控工具

          • 2、Thanos在TKEStack中的實踐 - Even - A super concise theme for Hugo

          • 3、Prometheus Remote Write配置 - 時序數(shù)據(jù)庫 TSDB - 阿里云

          • 4、Thanos - Highly available Prometheus setup with long term storage capabilities

          • 5、xxHash - Extremely fast non-cryptographic hash algorithm

          —————END—————

          推薦閱讀:


          最近面試BAT,整理一份面試資料Java面試BAT通關手冊,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
          獲取方式:關注公眾號并回復 java 領取,更多內(nèi)容陸續(xù)奉上。
          明天見(??ω??)??
          瀏覽 71
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  鲁一鲁久久 | 日韩中文视频 | 青草网络青 | 超pen个人公开视频久久 | 操逼大片 |