• 【spark】记录一次 spark sparkstreaming 使用命令行提交任务在Yarn集群模式无法正常消费kerberos kafka数据的问题


    前言

    最近在提交 spark 程序到 yarn 消费 kerberos 认证方式的 kafka 数据。由于配置文件 相对/绝对路径不正确配置 遇到了报错,这里整理并记录一下。

    环境信息

    • spark 2.4
    • hadoop 3.0
    • kafka 2.4

    问题原因:

    先提前说下问题的最终原因:由于 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这里我用到如下几个配置文件:

    1. /etc/krb.conf
    2. kafka_client_jaas.conf
    3. test.keytab

    并且这几个配置文件需要在 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";
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    报错内容

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    使用 spark-local 模式

    我们使用 spark on yarn-cluster 任务无法执行,于是我们将任务改为 spark local[*] 模式,发现就没问题。

    问题解决

    经过问题定位终于发现是 kafka_client_jaas.confkeyTab="/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"
    
    • 1
    • 2

    spark.driver.extraJavaOptionsspark.executor.extraJavaOptions 都需要改成相对路径。

    正确的kafka_client_jaas.conf

    KafkaClient {
       com.sun.security.auth.module.Krb5LoginModule required
       useKeyTab=true
       keyTab="./test.keytab"
       storeKey=true
       useTicketCache=false
       serviceName="kafka"
       principal="test@TEST.COM";
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这里我们以为问题已经解决了,结果还是不行,后面经过查询我们还需要将keytab 文件也传递给 Yarn 服务。

    最终的spark-submit命令

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    为了方便阅读,这里我将不同的地方贴出

    旧的命令行
    --keytab "/user/test/k-test.keytab"
    --files "/etc/krb5.conf,/user/test/kafka_client_jaas.conf"
    
    • 1
    • 2
    新的命令行
    --keytab "/user/test/k-test.keytab" 
    --files "/etc/krb5.conf,/user/rwms/kafka_client_jaas.conf,/user/test/test.keytab"
    
    • 1
    • 2

    注意:新的命令行 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.keytabrwms.keytab均会被上传,sparkkafka各取所需,即可正常工作。

    当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.extraJavaOptionsspark.executor.extraJavaOptions

    参考

    • https://docs.cloudera.com/HDPDocuments/HDP2/HDP-2.4.3/bk_spark-guide/content/spark-streaming-kafka-kerb.html
    • https://blog.csdn.net/u012373717/article/details/115401706
  • 相关阅读:
    【运筹优化】结合天际线启发式的蚁群算法求解二维矩形装箱问题 + Java代码实现
    星宿UI V2.1 开源wordpress资源下载小程序,流量主激励视频广告
    【NLP】使用递归神经网络对序列数据进行建模 (Pytorch)
    【图论 单源最短路】100276. 最短路径中的边
    【统计分析和过程改进】上海道宁带来Minitab软件合集,帮助企业和组织发挥数据的价值
    安全防御(第六次作业)
    allatori8.0文档翻译-第十三步:Android Studio整合
    postgres 数据库架构介绍--1
    【角点检测】 基于各向异性高斯方向导数滤波器实现图像角点检测附matlab代码
    兼容并蓄广纳百川,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang复合容器类型的声明和使用EP04
  • 原文地址:https://blog.csdn.net/Mrerlou/article/details/126408647