前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >0578-5.15.1-Kerberos环境下Java应用程序认证超时异常分析

0578-5.15.1-Kerberos环境下Java应用程序认证超时异常分析

作者头像
Fayson
发布2019-04-28 18:03:18
2.8K0
发布2019-04-28 18:03:18
举报
文章被收录于专栏:Hadoop实操

作者:谢敏灵/辉少

1

文档编写目的

在Kerberos环境中,我们的应用程序通过Java代码来提交任务需要先进行Kerberos凭证的初始化然后进行应用程序的提交,本文档主要讲述Java应用程序长时间运行作业Kerberos不自动重新认证问题

  • 测试环境

1.CM和CDH版本为5.15.1

2.操作系统版本为RedHat7.2

3.集群已启用Kerberos

2

问题描述

在使用JDK 8时,在Kerberos环境下应用程序在执行的过程中报以下错误:

Failed on local exception: java.io.IOException: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]

3

问题分析

在Kerberos环境下长时间运行的作业会出现认证失败问题,认证失败是由于Ticket过期导致。Ticket过期是由ticket_lifetime和renew_lifetime两个参数控制,具体分析如下:

先了解下krb5.conf里ticket_lifetime和renew_lifetime参数:

代码语言:javascript
复制
ticket_lifetime = 24h
renew_lifetime = 7d

注:这里其实还跟kdc.conf里的ticket_lifetime和renew_lifetime相关,本文不做讨论,假设你配置都是一致的。

每一个Kerberos的ticket,包括TGT,都有一个ticket_lifetime(默认:1天);Ticket可以被延续,但最多只能延续到renew_lifetime(默认:7天),超过7天后无法再延续,此时ticket失效,只能重新login。

如果你的应用程序需要运行很长时间或者需要持续不断地一直运行,就会有一个问题,即:

在应用程序启动时进行Kerberos认证登录后,是否还需要定时renew ticket或在ticket期满失效后使用keytab重新login?例如,是否需要在应用程序代码里,在每个UGI.doAS(...)前调用UGI.checkTGTAndReloginFromKeytab或者使用一个Timer周期性地调用UGI.checkTGTAndReloginFromKeytab?

关于这个问题,首先需要了解在Hadoop系统里是如何进行Kerberos认证的:

Hadoop Kerberos认证的主要使用场景是Hadoop RPC框架(使用SASL进行kerberos认证)。大部分Hadoop daemon进程在启动时会调用UGI(org.apache.hadoop.security.UserGroupInformation),UGI.loginUserFromKeytab做kerberos认证并获取ticket,并在后续每一次RPC调用时使用该ticket认证。比如,DataNode必须认证它对NameNode的RPC调用,NodeManager也必须认证它对ResourceManager的RPC调用。那么,这些daemon进程为什么能在启动后长时间持续运行而不会出现kerberos ticket错误呢(甚至已经超过了renew_lifetime)?这是因为Hadoop在RPC Client层实现了一种自动relogin机制。在Client.handleSaslConnectionFailure(org.apache.hadoop.ipc.Client)方法里有如下代码:

代码语言:javascript
复制
      // try re-login
    if (UserGroupInformation.isLoginKeytabBased()) {
              UserGroupInformation.getLoginUser().reloginFromKeytab();
    } else if (UserGroupInformation.isLoginTicketBased()) {
        UserGroupInformation.getLoginUser().reloginFromTicketCache();
    }

上述代码说明在使用RPC连接时,如果因为ticket失效造成认证失败,会自动relogin。

基于以上认识,可以得出以下结论:

1.如果应用程序的使用模式是从keytab登录后执行典型的Hadoop RPC Java调用(如调用HDFS FileSystem API),那么是不需要在应用层增加renew ticket或relogin代码的,因为RPC Client层已经帮你实现了。

2.如果应用程序的使用模式是不使用Hadoop RPC,而是调用HDFS REST API或YARN REST API(使用SPNEGO进行kerberos认证),那么需要在应用程序里增加relogin代码。具体实现方式是:

Java方式:主Java程序使用keytab调用UGI.loginUserFromKeytab登录,然后在每个UGI.doAS前调用UGI.checkTGTAndReloginFromKeytab方法,或者另启动一个线程周期性调用该方法。

Shell方式:主程序使用kinit登录,然后启动另一个子进程周期性的调用kinit -R去renew ticket或者调用kinit -kt去relogin。

需要注意的是当使用JDK 8时,UGI的relogin存在一个bug,即HADOOP-10786。该bug是因为JDK 8的Krb5LoginModule有些小改动,这些改动会造成UGI的relogin代码认为之前的登录并不是基于keytab登录的。所以,UGI.reloginFromKeytab和UGI.checkTGTAndReloginFromKeytab方法实际上什么都没有做,并没有执行relogin。所以,此时应用程序仍然会报以下错误:

代码语言:javascript
复制
Failed on local exception: java.io.IOException: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]

4

解决办法

对于使用JDK 8应用程序不能正常reloginFromKeytab的 bug,workaround是:

1. 使用JDK 7而不是JDK 8,或者

2. 确保hadoop-common包含了HADOOP-10786补丁。

建议使用CDH5.13.0或者以上版本的包,这些包已经包括了该补丁。如果仍然在IDE开发环境出现了以上问题,可以检查一下IDE依赖的hadoop-common包的版本是否有问题。

参考文档:

https://issues.apache.org/jira/browse/HADOOP-10786

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Hadoop实操 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
专用宿主机
专用宿主机(CVM Dedicated Host,CDH)提供用户独享的物理服务器资源,满足您资源独享、资源物理隔离、安全、合规需求。专用宿主机搭载了腾讯云虚拟化系统,购买之后,您可在其上灵活创建、管理多个自定义规格的云服务器实例,自主规划物理资源的使用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档