大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

概述

確保 HADOOP_CONF_DIR 或者 YARN_CONF_DIR 指向包含 Hadoop(客戶端)配置文件的目錄。這些配置文件用於寫HDFS和連接YARN ResourceManager。這個目錄下包含的配置文件被分發給YARN集群,這樣application所使用的容器都使用同樣的配置。如果配置引用了Java系統屬性或非YARN管理的環境變量,他們也應該被配置在Spark application的配置中(driver,executors,client 模式下的AM)。

有兩種YARN上的部署模式。cluster模式,Spark driver運行在由YARN管理的一個application master進程內。啟動這個application後,客戶端可以撤離。client模式,driver運行在客戶端進程內,application master僅被用於向YARN請求資源。

和Spark standalone,Mesos不同,部署在YARN上,master的地址由--master指定,ResourceManager的地址從Hadoop配置中獲取。這樣--master配置為”yarn”。

以cluster模式在YARN上運行application

$ ./bin/spark-submit --class path.to.your.Class --master yarn --deploy-mode cluster [options] [app options]

例如:

$ ./bin/spark-submit --class org.apache.spark.examples.SparkPi \\

--master yarn \\

--deploy-mode cluster \\

--driver-memory 4g \\

--executor-memory 2g \\

--executor-cores 1 \\

--queue thequeue \\

lib/spark-examples*.jar \\

10

上面啟動一個 YARN 客戶端程序,這個客戶端程序啟動了默認的 Application Master。SparkPi將作為Application Master的子線程運行。客戶端定期地輪詢Application Master獲得狀態的更新並將在控制檯展示出來。一旦Application 運行完成客戶端就退出。

添加其他的jar

在cluster模式下,driver運行在與客戶端不同的機器上,因此SparkContext.addJar不能使用位於客戶端本地的文件。為了使SparkContext.addJar可以利用客戶端本地文件,通過--jars指定這些文件(jar)。

$ ./bin/spark-submit --class my.main.Class \\

--master yarn \\

--deploy-mode cluster \\

--jars my-other-jar.jar,my-other-other-jar.jar \\

my-main-jar.jar \\

app_arg1 app_arg2

準備工作

在YARN上運行Spark需要YARN 支持的binary distribution of Spark(Spark的二進制分佈式文件),可以下載他:

http://spark.apache.org/downloads.html

為了能夠在YARN上使用Spark運行時jar(Spark runtime jars),需要設置spark.yarn.archive 或spark.yarn.jars,如果沒有指定其中之一,那麼Spark會將$SPARK_HOME/jars下的文件打包為zip文件並上傳到分佈式緩存。

為了省去這個過程,將jar包放到HDFS上,並在程序中設置這個參數:

sparkConf.set("spark.yarn.jar", "hdfs://192.168.106.210:8020/sparkjar/spark-assembly-1.6.0-hadoop2.6.0.jar");

調試應用

在YARN術語中,executors和application masters運行在“containers”中。YARN有兩種處理應用完成後的container日誌的模式。如果啟用日誌聚合(配置yarn.log-aggregation-enable),container日誌會被拷貝到HDFS並將本機日誌刪除。在集群的任何一臺機器上都可以使用yarn logs這個命令查看日誌。

yarn logs -applicationId

打印指定application的全部容器的所有日誌的全部內容。也可以使用HDFS Shell或API查看日誌。通過查看yarn.nodemanager.remote-app-log-dir 和yarn.nodemanager.remote-app-log-dir-suffix可以找到日誌文件的目錄。也可以在Spark Web UI中找到這些日誌,前提是Spark history server和MapReduce history server必須運行,並且配置了yarn-site.xml的yarn.log.server.url屬性。Spark history server的日誌URL會重定向到MapReduce history server以展示聚合信息。

日誌聚合沒有開啟的話,每臺機器生成的日誌仍然保存在本地,存儲路徑通過YARN_APP_LOGS_DIR配置指定,常被指定為/tmp/logs 或$HADOOP_HOME/logs/userlogs,這取決於Hadoop版本和具體的安裝情況。這時查看container日誌要到包含那個container的主機去查。

要想回顧每個container的運行環境,增大yarn.nodemanager.delete.debug-delay-sec的值(如36000),並且通過設置yarn.nodemanager.local-dirs來使用每個在container啟動的節點上

的application緩存。這個目錄包含了啟動腳本,jar和所有用來啟動container的環境變量。這個過程有助於調試路徑問題。注意,啟用此功能需要集群設置的管理員權限並且還要重啟所有node manager,因此這不適用於託管集群。

application master或executor要使用自定義的log4j配置,一些選項如下:

1)使用spark-submit命令,將log4j.properties文件路徑加入--files文件列表,實現上傳log4j.properties。

2)設置spark.driver.extraJavaOptions(對於驅動)或spark.executor.extraJavaOptions(對於executors)為

-Dlog4j.configuration=<location>。如果使用文件,應明確指出file:協議並且這個文件在每個節點都應存在。/<location>

3)更新$SPARK_CONF_DIR/log4j.properties並且這個配置文件會和其他配置一起上傳到集群。如果指定了多個選項,那麼上兩個選項的優先權比此項高。

注意,對於第一個選項,所有的driver和executor將共享相同的log4j配置文件,如果這些driver和executor都運行在一個節點上就會有問題(日誌都寫到一個文件裡)。

如果你需要一個引用,指向YARN上的正確位置來放置日誌文件,以便YARN能夠正確地展示和聚合他們,那麼在log4j.properties中配置spark.yarn.app.container.log.dir。例如log4j.appender.file_appender.File=${spark.yarn.app.container.log.dir}/spark.log。對於streaming application,配置RollingFileAppender並且將文件路徑設置為YARN的日誌目錄,這樣可以避免大日誌文件引起磁盤溢出,並且YARN日誌工具可以訪問這些日誌文件。

為了使用application master和executor的自定義度量屬性,更新$SPARK_CONF_DIR/metrics.properties文件。這個文件連同其他配置一起被上傳,這樣你就不用使用--files來指定他。

Spark Properties(Spark屬性)

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

大數據計算框架Spark之使用Hadoop YARN

註釋

1)調度描述中的核心請求是否會執行取決於使用的調度器(scheduler )和如何配置他。

2)在cluster模式在,Spark executors和Spark driver使用的本地目錄

是YARN上配置的本地目錄(Hadoop YARN 的配yarn.nodemanager.local-dirs)

如果用戶指定了spark.local.dir,他會被忽略。在client模式中,Spark executors會使用YARN上配置的本地目錄,然而Spark driver會使用spark.local.dir。這是因為client模式下Spark driver不會在YARN集群上運行,只有Spark executors在YARN集群上運行。

3)--files和--archives選項支持以#指定的文件名,這與hadoop類似。例如可以指定:--files localtest.txt#appSees.txt,會將本地名為localtest.txt的文件上傳到HDFS上,但會使用appSees.txt來連接,當應用運行在YARN上時,要使用appSees.txt來引用這個文件。

4)如果模式為cluster,--jars選項使用本地文件,那麼他使SparkContext.addJar這個方法起作用。如果使用HDFS, HTTP, HTTPS, 或FTP,那麼不必使用--jars。

在一個安全的集群上運行

在安全的Hadoop集群上使用Kerberos來認證與服務端和客戶端相關聯的主體。這樣客戶端就能向已認證的服務端發起請求。服務端為已認證的主體賦予權限。

Hadoop服務發行hadoop tokens來授予訪問服務和獲得數據的權限。客戶端必須先獲得與要訪問服務相關的tokens,然後連同application一起發生給YARN集群。

Spark application與Hadoop文件系統(HDFS,webhdfs),HBase,Hive等交互,他必須獲得相關的tokens,這個tokens使用提交application的用戶的Kerberos憑據,這樣這個身份的主體就成為了提交Spark application的主體。

一般在提交應用的時候,Spark自動從集群的默認hadoop文件系統獲得一個token,有可能是HBase或Hive。

如果HBase在classpath中,一個HBase token將被獲得。HBase配置聲明瞭application是安全的(例如hbase-site.xml設置hbase.security.authentication為kerberos),並且spark.yarn.security.credentials.hbase.enabled設置為true。

相似地,如果Hive在classpath中,Hive token將被獲得。他的配置包含了存儲元數據的URI(hive.metastore.uris),並且spark.yarn.security.credentials.hive.enabled設置為true。

如果application需要和其他的安全的hadoop文件系統交互,那麼要使用這些token訪問集群,就必須在調用時明確地指出,可通過spark.yarn.access.hadoopFileSystems這個屬性列出來集群

spark.yarn.access.hadoopFileSystems hdfs://ireland.example.org:8020/,webhdfs://frankfurt.example.org:50070/

Spark支持通過Java Services機制與安全感知系統交互(參見java.util.ServiceLoader)。為了實現這一功能,org.apache.spark.deploy.yarn.security.ServiceCredentialProvider的實現可用於Spark,通過在jar的META-INF/services路徑中的相應的文件列出他們的名字,可以配置spark.yarn.security.credentials.{service}.enabled為false來禁用這個插件,{service}是憑據提供者的名字。

配置外部的Shuffle服務

在每個NodeManager上啟動Spark Shuffle Service,請遵照以下指令:

1)構建Spark,如果使用構建好的,跳過此步驟。

2)找到spark-<version>-yarn-shuffle.jar。如果自己構建Spark,那麼應該放在$SPARK_HOME/common/network-yarn/target/scala-<version>目錄下,如果使用分發版本,應該放在YARN下。/<version>/<version>

3)把這個jar放到集群的所有的NodeManager下。

4)在每個節點的yarn-site.xml文件中,添加spark_shuffle到yarn.nodemanager.aux-services,設置yarn.nodemanager.aux-services.spark_shuffle.class為org.apache.spark.network.yarn.YarnShuffleService

5)在etc/hadoop/yarn-env.sh中,通過設置YARN_HEAPSIZE 增大NodeManager的堆內存,可避免Shuffle過程的垃圾收集問題。

6)重啟所有NodeManager。

shuffle service運行在YARN上時,額外的參數是:

spark.yarn.shuffle.stopOnFailure默認是false,這個參數的含義是當Spark Shuffle Service初始化失敗時,是否停止NodeManager。當Spark Shuffle Service沒有在NodeManager上運行,而NodeManager的container正在運轉,這樣的錯誤可以通過設置上面的參數來阻止。

Kerberos排錯

記錄針對Kerberos操作的額外日誌,設置HADOOP_JAAS_DEBUG這個環境變量

bash export HADOOP_JAAS_DEBUG=true

通過系統屬性sun.security.krb5.debug和sun.security.spnego.debug=true來配置JDK類,即可開啟針對Kerberos和SPNEGO/REST認證的日誌。

-Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true

在Application Master中,可以啟用上面的所有選項

spark.yarn.appMasterEnv.HADOOP_JAAS_DEBUG true spark.yarn.am.extraJavaOptions -Dsun.security.krb5.debug=true -Dsun.security.spnego.debug=true

如果日誌級別org.apache.spark.deploy.yarn.Client被設置為DEBUG,日誌會包含獲得的所有token,以及這些token到期的詳細信息。

使用Spark History Server

應用端設置Spark的配置為spark.yarn.historyServer.allowTracking=true

在Spark History Server,添加org.apache.spark.deploy.yarn.YarnProxyRedirectFilter到spark.ui.filters配置列表。

實踐

在集群中選擇一臺服務器,輸入命令:spark-submit 回車,得到如下命令模式及參數註釋:

大數據計算框架Spark之使用Hadoop YARN

注意:

1)在YARN上運行,那麼master一定是 yarn。

2)deploy-mode值有兩個,一個是cluster,一個是client。在程序中無法指定deploy-mode,只能由spark-submit命令指定。如果在命令中不指定deploy-mode參數,那麼運行方式為client(即默認)。

3)可以通過命令設定master的值,也可以在程序中設置。

4)指定運行應用的用戶賬號。運行spark-submit命令默認以root身份執行命令(即登錄Linux服務器的身份),但是Spark訪問HDFS會遇到權限問題:

18/10/25 08:57:26 INFO yarn.ApplicationMaster: Unregistering ApplicationMaster with FAILED (diag message: User class threw exception: org.apache.hadoop.security.AccessControlException: Permission denied: user=root, access=EXECUTE, inode="/home":hdfs:supergroup:d-wx------
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.check(FSPermissionChecker.java:400)
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.checkTraverse(FSPermissionChecker.java:316)
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.checkPermission(FSPermissionChecker.java:243)
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.checkPermission(FSPermissionChecker.java:194)
at org.apache.hadoop.hdfs.server.namenode.FSDirectory.checkPermission(FSDirectory.java:1846)
at org.apache.hadoop.hdfs.server.namenode.FSDirectory.checkPermission(FSDirectory.java:1830)
at org.apache.hadoop.hdfs.server.namenode.FSDirectory.checkOwner(FSDirectory.java:1775)
at org.apache.hadoop.hdfs.server.namenode.FSDirAttrOp.setPermission(FSDirAttrOp.java:64)
at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.setPermission(FSNamesystem.java:1886)
at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.setPermission(NameNodeRpcServer.java:849)
at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.setPermission(ClientNamenodeProtocolServerSideTranslatorPB.java:509)
at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java)
at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:523)
at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:991)
at org.apache.hadoop.ipc.Server$RpcCall.run(Server.java:869)

這一句:

yarn.ApplicationMaster: Unregistering ApplicationMaster with FAILED (diag message: User class threw exception: org.apache.hadoop.security.AccessControlException: Permission denied: user=root, access=EXECUTE, inode="/home":hdfs:supergroup:d-wx------

充分顯示了問題,即以root用戶訪問/home文件,然而其屬於hdfs這個用戶,那麼要以hdfs用戶身份執行spark-submit命令,使用:

sudo -u hdfs spark-submit --class path.to.your.Class --master yarn --deploy-mode cluster [options] [app options]

有博文說添加:System.setProperty("HADOOP_USER_NAME", "hdfs");然而只能解決以client模式運行的應用,對於cluster模式這種方式不起作用,所以還是指定執行腳本的用戶這種方式最可靠。

例:不指定master和deploy-mode

spark-submit --class net.cnki.xtsj.a_statistical_information.WordRetrievedStatistics \\

/home/a-statistical-information-0.0.1-SNAPSHOT-jar-with-dependencies.jar

在程序中指定master為yarn:

SparkConf sparkConf = new SparkConf().setMaster("yarn").setAppName("write words to mongodb");


分享到:


相關文章: