大數據

Apache Spark 3.0對Prometheus監控的原生支持

一、用Prometheus監控Apache Spark

在使用Apache Spark去做ETL,去做數據分析和處理的過程中,我們肯定都會涉及到監控spark程序這麼一項工作。一般來說,有三種方式去做程序的監控。第一個就是使用Web UI。第二塊主要是日誌。第三種是Metrics。這三個信息,最大的一個問題是說,我們一般是在ETL夯住了或者失敗之後,才會去查看。如果有這麼一個系統能夠幫助我們,在任務性能下降或者失敗之前
就提醒、甚至是自愈,這樣就能避免很多故障的發生。

image.png

在分佈式系統中,比較大的挑戰之一就是如何做到在故障發生之前就能夠有些規避的措施,或者一些提醒的措施。Metrics在一個分佈式系統裡邊是非常關鍵和核心的一個模塊。在spark裡邊,同樣也是有很多的metrics。使用metrics我們能夠發現內存洩露,一些配置錯誤,在性能下降之前的一些監控,以及對於流作業的一些監控等等。

image.png

Prometheus是非常有用的一個metrics監控的系統。它是一個開源的系統,能夠支持監控和報警。它主要有以下四個特點。第一個特點是,它的數據模型是一個多維度的數據模型。第二個特點是,部署和運維是非常方便的。第三個特點是,在採集數據的擴展性這塊,支持得非常好。最後一個特點是,提供了一個非常強大的查詢語言。

image.png

在spark 3.0以前,我們一般怎麼去支持Prometheus。其中第一個方法就是基於java agent的方式。主要主要分為四個步驟,如下圖所示。

image.png

第二種方式,基於GraphiteSink和GraphiteExporter的組合。

image.png

第三種方式,基於Custom sink和Pushgateway server。

image.png

我們來看一下,前面三種方法有哪些好處和壞處。首先說好處,已經有很多用戶通過三種方式實現了跟Prometheus的對接,是一個比較通用的方式。但是它也有壞處,在新環境中它有一些比較繁瑣的setup的工作。另外,第三方插件可能對特定版本會有一些比較強的依賴,這對我們後續的運維和升級會帶來困擾。

image.png

所以在spark 3.0中,就提出了新的目標。主要有兩個需要關注的設計點。一個就是隻使用到新的endpoint,不去跟原先的pipeline耦合,不引入對其他一些組件的依賴。另外一塊就是儘量重新使用已經存在的一些資源,包括端口的資源,等等。

image.png

二、本地化支持Prometheus (Support Prometheus monitoring natively)

接下來,我會介紹一下在spark 3.0中如何實現剛才提到的目標,更好的本地化支持Prometheus。Spark的metrics模塊依賴比較重的是DropWizard這麼一個組件。它在spark 3.0中也做了一次升級,帶來的好處是能夠支持jdk11,但是也存在小的負面點,就是它的數據格式有所變化,如下圖所示。

image.png

第二個增加的組件就是ExecutorMetricsSource。主要是對executor memory相關的一些metrics做了增強。

image.png

為了更好的做一些本地化支持的工作,主要加了兩個組建。一個是PrometheusServlet,它會生成Prometheus兼容的一個格式,它的配置方式跟以前的metrics system配置是一樣的。同時也不會引入其他的一些庫,也不會對特定端口進行依賴。第二個組件是PrometheusResource。針對executor memory metrics相關的信息,提供了這麼一個獨立的endpoint。

image.png

在3.0中增加了spark_info metric,它的作用是針對不同版本的監控和報警。另外,對driver service annotation做了一些增強,能夠實現利用Prometheus service discovery的特性,從而更方便的進行一些metrics的採集和監控。

image.png

三、在K8s集群中監控 (Monitoring in K8s cluster)

在K8s環境下面,怎麼去基於已經集成Prometheus的spark版本,對我們的作業進行監控,主要有三個場景。第一個是對一些批作業的內存的情況進行監控。第二個是對動態調度和動態資源分配的監控。第三個是對流作業的監控。

image.png

我們來看一下這三種場景。首先,對批作業內存的監控場景,主要用到的是Prometheus的service discovery這一個特性。如下圖所示,有四個配置。

image.png

我們來看一個簡單的例子,是基於SparkPi的。假設我們現在通過spark-submit提交一個作業到K8s。主要是把前面提到的幾個配置,也就是下圖這個例子中加粗的部分給配置上就可以了。

image.png

如下圖所示,是一個針對內存的監控。它是executor_id為1的時候,對它的內存使用的監控。可以看到綠色的這條線,我們從driver端拿到這個狀態之後,就可以提前知道已經有OOM的風險,通過Prometheus從driver端採集到監控信息,就可以及時的做一些報警和預處理。

image.png

第二個場景就是動態調度。Spark 3.0支持在K8s上動態調度。主要就是把一些配置打開,如下圖中的黑體部分所示。配置打開之後,在作業提交的時候,就能夠開啟在K8s環境的動態調度。

image.png

然後我們看一下在Prometheus上展示的一個狀態信息圖,每一條線表示有一個executor。我們看到隨著時間推移,線的個數在不斷的變多,然後又變少。隔了一分鐘之後,又進入到第二輪,也是同樣的先變多,再變少。

image.png

最後一種場景,是針對流作業的監控的支持。在spark 3.0中,添加了spark.sql.streaming.metricsEnabled。開啟之後,它會提供6種metrics,如下圖所示。對一個流作業,如果要使用Prometheus監控,最好在一開始就對nameSpace等提前做好設置,避免後續出現數據的不一致。

image.png

前面提到的6種metrics對於流作業都是比較關鍵的,都應該去監控並且做一些報警處理。這裡重點再提兩個。一個就是前面提到的延時,如果latency > micro-batch interval,就可能存在一些性能問題,需要關注。另外一個報警就是States-rowsTotal。如果它無限的增長,可能會導致流作業發生OOM。這個也是需要做好監控和報警的。

image.png

在針對Prometheus的使用方式這塊,社區在3.0建議的是基於federation的模式。如下圖所示,左邊是在namespace1下面對批作業的一個監控。右邊是在namespace2下面對流作業的一個監控。他們都可以同時發送到一個Cluster-wise Prometheus下面,然後通過spark_info等等這些信息做一些數據的細分。

image.png

以上就是spark 3.0對於Prometheus監控的一些支持。目前來說還是處在一個實驗性的階段,所以還存在一些問題。第一個問題就是新的endpoint暴露的metrics是隻包含metrics_或者spark_info開頭的這麼一些信息。第二個問題是,PrometheusServlet目前的命名格式沒有遵循Prometheus的命名風格。第三個問題是,在流作業這塊,如果沒有把namespace做一些很好的配置,可能會導致metrics不斷的的增加,甚至互相影響。

image.png

阿里雲EMR團隊在做的spark on k8s,目前已經對Prometheus監控進行了原生化的支持。目前我們實現的方式是基於javaagent,後續也會計劃去引進更多的原生支持。

image.png


關鍵詞:Spark 3.0,Prometheus,metrics監控,k8s cluster,spark on k8s

Leave a Reply

Your email address will not be published. Required fields are marked *