最近在提交 spark
程序到 yarn
消费 kerberos
认证方式的 kafka
数据。由于配置文件 相对/绝对路径不正确配置
遇到了报错,这里整理并记录一下。
先提前说下问题的最终原因:由于 spark-submit
提交任务命令 kafka_client_jaas.conf配置文件 相对/绝对路径 不合理导致
的。那么我原来的提交命令是什么
我们来重新复现下这个问题。之前用的错误的spark-submit
命令如下
spark-submit
命令行spark-submit --class com.test.SparkTest \
--principal "test@TEST.COM" \
--keytab "/user/test/test.keytab" \
--files "/etc/krb5.conf,/user/test/kafka_client_jaas.conf" \
--conf "spark.driver.extraJavaOptions=-Djava.security.auth.login.config=kafka_client_jaas.conf" \
--conf "spark.executor.extraJavaOptions=-Djava.security.auth.login.config=kafka_client_jaas.conf" \
--conf "spark.driver.memoryOverhead=1024" \
--conf "spark.executor.memoryOverhead=1024" \
--master yarn \
--deploy-mode cluster \
--name SparkTestDemo \
--driver-cores 1 \
--driver-memory 1G \
--executor-cores 1 \
--executor-memory 1G \
--queue test \
--num-executors 1 \
test-etl.jar
这里我用到如下几个配置文件:
并且这几个配置文件需要在 driver
节点和 executor
节点上都需要有。
kafka_client_jaas.conf
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="/user/test/test.keytab"
storeKey=true
useTicketCache=false
serviceName="kafka"
principal="test@TEST.COM";
};
ERROR Fatal error during KafkaServer startup. Prepare to shutdown (kafka.server.KafkaServer)
org.apache.kafka.common.KafkaException: javax.security.auth.login.LoginException: Could not login: the client is being asked for a password, but the Kafka client code does not currently support obtaining a password from the user. not available to garner authentication information from the user
at org.apache.kafka.common.network.SaslChannelBuilder.configure(SaslChannelBuilder.java:160)
at org.apache.kafka.common.network.ChannelBuilders.create(ChannelBuilders.java:146)
at org.apache.kafka.common.network.ChannelBuilders.serverChannelBuilder(ChannelBuilders.java:85)
at kafka.network.Processor.<init>(SocketServer.scala:726)
at kafka.network.SocketServer.newProcessor(SocketServer.scala:367)
at kafka.network.SocketServer.$anonfun$addDataPlaneProcessors$1(SocketServer.scala:261)
at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:158)
at kafka.network.SocketServer.addDataPlaneProcessors(SocketServer.scala:260)
at kafka.network.SocketServer.$anonfun$createDataPlaneAcceptorsAndProcessors$1(SocketServer.scala:223)
at kafka.network.SocketServer.$anonfun$createDataPlaneAcceptorsAndProcessors$1$adapted(SocketServer.scala:220)
at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:62)
at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:55)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:49)
at kafka.network.SocketServer.createDataPlaneAcceptorsAndProcessors(SocketServer.scala:220)
at kafka.network.SocketServer.startup(SocketServer.scala:120)
at kafka.server.KafkaServer.startup(KafkaServer.scala:255)
at kafka.server.KafkaServerStartable.startup(KafkaServerStartable.scala:38)
at kafka.Kafka$.main(Kafka.scala:84)
at kafka.Kafka.main(Kafka.scala)
我们使用 spark on yarn-cluster
任务无法执行,于是我们将任务改为 spark local[*]
模式,发现就没问题。
经过问题定位终于发现是 kafka_client_jaas.conf
中 keyTab="/user/test/test.keytab"
这一行的绝对路径导致的。
因为:
keytab文件
和配置文件
是使用 YARN 资源分发。这些配置文件最终将位于 执行Spark YARN 容器的目录中,因此改行的内容应指定为相对路径 也就是./test.keytab
另外如下的几个配置也需要改成相对路径
--conf "spark.driver.extraJavaOptions=-Djava.security.auth.login.config=./kafka_client_jaas.conf"
--conf "spark.executor.extraJavaOptions=-Djava.security.auth.login.config=./kafka_client_jaas.conf"
spark.driver.extraJavaOptions
和spark.executor.extraJavaOptions
都需要改成相对路径。
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
keyTab="./test.keytab"
storeKey=true
useTicketCache=false
serviceName="kafka"
principal="test@TEST.COM";
};
这里我们以为问题已经解决了,结果还是不行,后面经过查询我们还需要将keytab 文件
也传递给 Yarn
服务。
spark-submit \
--class com.test.SparkTest \
--principal "test@TEST.COM" \
--keytab "/user/test/k-test.keytab" \
--files "/etc/krb5.conf,/user/test/kafka_client_jaas.conf,/user/test/test.keytab" \
--conf "spark.driver.extraJavaOptions=-Djava.security.auth.login.config=./kafka_client_jaas.conf -Djava.security.krb5.conf=/etc/krb5.conf" \
--conf "spark.executor.extraJavaOptions=-Djava.security.auth.login.config=./kafka_client_jaas.conf -Djava.security.krb5.conf=/etc/krb5.conf" \
--conf "spark.driver.memoryOverhead=1024" \
--conf "spark.executor.memoryOverhead=1024" \
--master yarn \
--deploy-mode cluster \
--name SparkTestDemo \
--driver-cores 1 \
--driver-memory 1G \
--executor-cores 1 \
--executor-memory 1G \
--num-executors 1 \
--queue test \
test-etl.jar
为了方便阅读,这里我将不同的地方贴出
--keytab "/user/test/k-test.keytab"
--files "/etc/krb5.conf,/user/test/kafka_client_jaas.conf"
--keytab "/user/test/k-test.keytab"
--files "/etc/krb5.conf,/user/rwms/kafka_client_jaas.conf,/user/test/test.keytab"
注意:新的命令行 keytab “/user/test/k-test.keytab” 这个地方特别注意下,文件名字是不同的,但是文件内容是一致的,为什么要这么改,是因为当同时配置 --keytab “/user/test/test.keytab” 和 – files “/user/test/test.keytab” 会造成程序的异常退出。为了避免冲突,我们引入一个不同名但同根的keytab 文件即:k-test.keytab 和 test.keytab 但其实这俩文件没什么区别。
举个例子:
当spark提交任务时,yarn会将--keytab
后面的keytab文件
与--files
里的文件先后上传,即 hdfs.keytab
与rwms.keytab
均会被上传,spark
与kafka
各取所需,即可正常工作。
当spark与kafka要使用相同的keytab文件时,比如都用rwms.keytab
,那么yarn会先后上传两次rwms.keytab
,在spark正使用的时候更新了keytab,造成异常退出。
下面列一下几种模式的不同:
spark locol 模式
在本地模式下,配置文件的相对/绝对路径,对程序没什么影响。
spark-yarn-client 模式
client 模式下,因为driver 端时在本地,本地的配置文件都有,所以spark.driver.extraJavaOptions
中的配置文件路径 相对/绝对 影响不大,spark.executor.extraJavaOptions
需要写成相对路径。
spark-yarn-cluster 模式
cluster模式下,driver 和 executor
节点都不在本地,所以配置文件都不存在,所以spark.driver.extraJavaOptions
需要写成相对路径,
spark.executor.extraJavaOptions
需要写成相对路径。
以上的问题,说白了就是在任务真正的执行节点,并没有成功从 绝对路径
中加载到对应的配置文件。
我们在生产中将 jaas 配置文件和 keytab 作为本地资源文件传递。将 jaas
配置文件选项添加到为驱动程序和执行程序指定的 JVM
选项中
因为别的节点并没有这些配置文件。所以需要用 --flies
将我们需要用到的配置都加载到yarn
服务上,然后 yarn
来将这些配置问价分发到真正执行任务的目录上。
我们生产上使用的一些参数中指定的配置也最好写成相对路径
。如:spark.driver.extraJavaOptions
和 spark.executor.extraJavaOptions
。