对接Kerberos认证Hadoop集群报DockerCredentialTokenIdentifier未找到
问题背景
通过部署在Tomcat上的API对接开启Kerberos认证的Hadoop集群,执行HDFS文件上传操作时触发报错。
初步排查已排除基础配置问题:
- 集群侧keytab文件运行状态正常,可正常执行
kinit命令读取HDFS内文件 krb5.conf配置符合规范要求,默认realm及其他必填配置项均已正确配置
异常堆栈信息
Exception in thread "main" java.util.ServiceConfigurationError: org.apache.hadoop.security.token.TokenIdentifier: Provider org.apache.hadoop.yarn.security.DockerCredentialTokenIdentifier not found at java.util.ServiceLoader.fail(ServiceLoader.java:239) at java.util.ServiceLoader.access$300(ServiceLoader.java:185) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:372) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404) at java.util.ServiceLoader$1.next(ServiceLoader.java:480) at org.apache.hadoop.security.token.Token.getClassForIdentifier(Token.java:117) at org.apache.hadoop.security.token.Token.decodeIdentifier(Token.java:138) at org.apache.spark.deploy.security.HadoopFSDelegationTokenProvider$$anonfun$getTokenRenewalInterval$1$$anonfun$4.apply(HadoopFSDelegationTokenProvider.scala:116) at org.apache.spark.deploy.security.HadoopFSDelegationTokenProvider$$anonfun$getTokenRenewalInterval$1$$anonfun$4.apply(HadoopFSDelegationTokenProvider.scala:116) at scala.collection.TraversableLike$$anonfun$filterImpl$1.apply(TraversableLike.scala:248) at scala.collection.Iterator$class.foreach(Iterator.scala:891) at scala.collection.AbstractIterator.foreach(Iterator.scala:1334) at scala.collection.IterableLike$class.foreach(IterableLike.scala:72) at scala.collection.AbstractIterable.foreach(Iterable.scala:54) at scala.collection.TraversableLike$class.filterImpl(TraversableLike.scala:247) at scala.collection.TraversableLike$class.filter(TraversableLike.scala:259) at scala.collection.AbstractTraversable.filter(Traversable.scala:104) at org.apache.spark.deploy.security.HadoopFSDelegationTokenProvider$$anonfun$getTokenRenewalInterval$1.apply(HadoopFSDelegationTokenProvider.scala:115) at org.apache.spark.deploy.security.HadoopFSDelegationTokenProvider$$anonfun$getTokenRenewalInterval$1.apply(HadoopFSDelegationTokenProvider.scala:111) at scala.Option.flatMap(Option.scala:171) at org.apache.spark.deploy.security.HadoopFSDelegationTokenProvider.getTokenRenewalInterval(HadoopFSDelegationTokenProvider.scala:111) at org.apache.spark.deploy.security.HadoopFSDelegationTokenProvider.obtainDelegationTokens(HadoopFSDelegationTokenProvider.scala:53) at org.apache.spark.deploy.security.HadoopDelegationTokenManager$$anonfun$obtainDelegationTokens$2.apply(HadoopDelegationTokenManager.scala:132) at org.apache.spark.deploy.security.HadoopDelegationTokenManager$$anonfun$obtainDelegationTokens$2.apply(HadoopDelegationTokenManager.scala:130) at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241) at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:241) at scala.collection.Iterator$class.foreach(Iterator.scala:891) at scala.collection.AbstractIterator.foreach(Iterator.scala:1334) at scala.collection.MapLike$DefaultValuesIterable.foreach(MapLike.scala:206) at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:241) at scala.collection.AbstractTraversable.flatMap(Traversable.scala:104) at org.apache.spark.deploy.security.HadoopDelegationTokenManager.obtainDelegationTokens(HadoopDelegationTokenManager.scala:130) at org.apache.spark.deploy.yarn.security.YARNHadoopDelegationTokenManager.obtainDelegationTokens(YARNHadoopDelegationTokenManager.scala:59) at org.apache.spark.deploy.yarn.Client.setupSecurityToken(Client.scala:309) at org.apache.spark.deploy.yarn.Client.createContainerLaunchContext(Client.scala:1013) at org.apache.spark.deploy.yarn.Client.submitApplication(Client.scala:178) at org.apache.spark.deploy.yarn.Client.run(Client.scala:1134) at org.apache.spark.deploy.yarn.YarnClusterApplication.start(Client.scala:1526) at org.apache.spark.deploy.SparkSubmit.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:849) at org.apache.spark.deploy.SparkSubmit.doRunMain$1(SparkSubmit.scala:167) at org.apache.spark.deploy.SparkSubmit.submit(SparkSubmit.scala:195) at org.apache.spark.deploy.SparkSubmit.doSubmit(SparkSubmit.scala:86) at org.apache.spark.deploy.SparkSubmit$$anon$2.doSubmit(SparkSubmit.scala:924) at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:933) at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
根因说明
该报错属于Java SPI服务加载失败,核心原因是Hadoop相关依赖版本不一致/类加载冲突:
JVM通过ServiceLoader加载org.apache.hadoop.security.token.TokenIdentifier的实现类时,扫描到了高版本hadoop-yarn包注册的DockerCredentialTokenIdentifier实现,但当前classpath下不存在该类,直接触发ServiceConfigurationError。
常见触发场景:
- 应用引入的hadoop-common、hadoop-hdfs、hadoop-yarn系列依赖版本不匹配
- Tomcat容器全局lib目录与应用WEB-INF/lib目录下存在多版本Hadoop jar包,类加载时出现版本错乱
- Spark任务使用的内置Hadoop版本与集群实际运行的Hadoop版本不一致
- 打包时将scope为provided的Hadoop依赖打入应用包,和集群环境提供的Hadoop依赖产生版本冲突
修复方案
- 对齐所有Hadoop核心依赖版本,确保
hadoop-common、hadoop-hdfs、hadoop-yarn-api、hadoop-yarn-common等包的版本与集群运行的Hadoop版本完全一致 - Tomcat部署场景排查类加载冲突:删除Tomcat全局lib目录下与应用重复、版本不匹配的Hadoop依赖;Maven/Gradle构建时将集群已提供的Hadoop依赖scope设置为
provided,避免打包时带入不匹配的私有依赖 - Spark任务场景确认Spark编译绑定的Hadoop版本与集群匹配,提交任务时可通过
--jars参数指定和集群版本一致的Hadoop依赖包,优先使用集群提供的Hadoop依赖路径 - 临时验证可排查classpath下
META-INF/services/org.apache.hadoop.security.token.TokenIdentifier服务配置文件,删除其中无对应实现类的org.apache.hadoop.yarn.security.DockerCredentialTokenIdentifier配置行,该方案仅用于临时调试,生产环境必须通过对齐依赖版本解决
内容的提问来源于stack exchange,提问作者Sanjay Ishwar
相关产品推荐
相关产品推荐

