在我的服务器应用程序中,我正在从我的
java应用程序连接到Kerberos安全的Hadoop集群.我正在使用像HDFS文件系统,Oozie,Hive等各种组件.在应用程序启动时,我打电话
UserGroupInformation.loginUserFromKeytabAndReturnUGI( ... );
这返回我的UsereGroupInformation实例,我保留它的应用程序的生命周期.在做特权行动时,我发起他们ugi.doAs(动作).
这很好,但是我想知道如何和何时应该在UserGroupInformation中续订kerberos机票?我发现一个方法UserGroupInformation.checkTGTAndReloginFromKeytab(),似乎在接近到期时进行更新.我也发现这个方法正在被诸如WebHdfsFileSystem之类的各种Hadoop工具所调用.
现在如果我想要我的服务器应用程序(可能运行几个月甚至几年)永远不会体验票证到期什么是最好的方法?提出具体问题:
>我可以依靠他们称之为checkTGTAndReloginFromKeytab的各种Hadoop客户端吗?
我应该在我的代码中调用checkTGTAndReloginFromKeytab吗?
>如果是这样,请在每次调用ugi.doAs(…)之前,或者设置一个定时器并定期调用它(多久)?
解决方法
Hadoop提交者在这里!这是一个很好的问题.
不幸的是,如果没有深入了解应用程序的特定使用模式,很难给出一个明确的答案.相反,我可以提供一般的指导方针,并描述何时Hadoop会为您自动处理更新或重新登录密码匙,何时不会.
Hadoop生态系统中Kerberos认证的主要用例是Hadoop的RPC框架,它使用SASL进行认证. Hadoop生态系统中的大多数守护进程通过在进程启动时对UserGroupInformation#loginUserFromKeytab执行一次一次性调用来处理此问题.其示例包括必须验证其对NameNode的RPC调用的HDFS DataNode以及必须验证其对ResourceManager的调用的YARN NodeManager.如何像DataNode这样的守护进程可以在进程启动时进行一次性登录,然后继续运行几个月,很久以前的典型票证过期时间?
由于这是一个常见的用例,Hadoop在RPC客户端层内直接实现了自动重新登录机制.该代码在RPC Client#handleSaslConnectionFailure
方法中可见:
// try re-login if (UserGroupInformation.isLoginKeytabBased()) { UserGroupInformation.getLoginUser().reloginFromKeytab(); } else if (UserGroupInformation.isLoginTicketBased()) { UserGroupInformation.getLoginUser().reloginFromTicketCache(); }
您可以将此视为重新登录的“懒惰评估”.它仅在尝试的RPC连接上重新执行登录以响应身份验证失败.
知道这一点,我们可以给出部分答案.如果您的应用程序的使用模式是从密钥表登录,然后执行典型的Hadoop RPC调用,则可能不需要滚动您自己的重新登录代码. RPC客户端层将为您做. “典型的Hadoop RPC”意味着与Hadoop交互的绝大多数Java API,包括HDFS FileSystem
API,YarnClient
和MapReduce Job
提交.
然而,一些应用程序使用模式根本不涉及Hadoop RPC.一个例子是与Hadoop的REST API(例如WebHDFS或YARN REST APIs)完全交互的应用程序.在这种情况下,认证模型通过SPNEGO使用Kerberos,如Hadoop HTTP Authentication文档中所述.
知道这一点,我们可以添加更多的答案.如果您的应用程序的使用模式根本不使用Hadoop RPC,而是单独使用REST API,那么您必须滚动您自己的重新登录逻辑.这正是07007的原因,就像你注意到的那样. WebHdfsFileSystem选择在每个操作之前进行通话.这是一个很好的策略,因为UserGroupInformation#checkTGTAndReloginFromkeytab
only renews the ticket if it’s “close” to expiration.否则,这个呼叫是无效的.
作为最终用例,让我们考虑一个交互过程,而不是从keytab登录,而是要求用户在启动应用程序之前在外部运行kinit.在绝大多数情况下,这些将是短期运行的应用程序,例如Hadoop CLI命令.然而,在某些情况下,这些可以是更长时间运行的过程.为了支持更长时间运行的进程,Hadoop启动后台线程以将Kerberos故障单“关闭”更新到到期.这个逻辑在UserGroupInformation#spawnAutoRenewalThreadForUserCreds
是可见的.与RPC层提供的自动重新登录逻辑相比,这里有一个重要的区别.在这种情况下,Hadoop只能够更新机票并延长其使用寿命.门票具有最大的可再生生命周期,如Kerberos基础设施所规定.之后,票不再可用了.在这种情况下重新登录实际上是不可能的,因为这将意味着重新提示用户输入密码,并且可能会离开终端.这意味着如果进程在票证到期之后持续运行,那么它将无法再进行身份验证.
再次,我们可以使用这些信息来告知我们的整体答案.如果您依靠用户在启动应用程序之前通过kinit进行交互式登录,并且如果您确信应用程序的运行时间不会超过Kerberos机票的最长可再生生命周期,那么您可以依靠Hadoop内部部件来为您定期更新.
如果您正在使用基于键盘的登录,而您只是不确定应用程序的使用模式是否可以依赖于Hadoop RPC层的自动重新登录,那么保守的方法就是滚动自己的. @SamsonScharfrichter在这里给出了一个很好的答案,就是滚动自己的.
HBase Kerberos connection renewal strategy
最后,我应该添加一个关于API稳定性的注释. Apache Hadoop Compatibility
指南详细讨论了Hadoop开发社区对向后兼容性的承诺. UserGroupInformation的界面注释为“有限私有”和“演进”.在技术上,这意味着UserGroupInformation的API不被视为公共的,它可能会以向后不兼容的方式发展.实际上,有很多代码已经取决于UserGroupInformation的接口,所以我们根本不可能做出突破性的改变.当然,在当前的2.x发行版本中,我不会担心方法签名从你下面改变而破坏你的代码.
现在我们拥有所有这些背景信息,让我们回顾一下你的具体问题.
Can I rely on the various Hadoop clients they call checkTGTAndReloginFromKeytab whenever it’s needed?
如果您的应用程序的使用模式是调用Hadoop客户端,这反过来又利用Hadoop的RPC框架,您可以依赖这一点.如果您的应用程序的使用模式仅调用Hadoop REST API,则无法依赖此.
Should I call ever checkTGTAndReloginFromKeytab myself in my code?
如果应用程序的使用模式仅用于调用Hadoop REST API而不是Hadoop RPC调用,则可能需要执行此操作.您不会在Hadoop的RPC客户端中实现自动重新登录的好处.
If so should I do that before every single call to ugi.doAs(…) or rather setup a timer and call it periodically (how often)?
在需要验证的每个操作之前调用UserGroupInformation#checkTGTAndReloginFromKeytab是很好的.如果票不接近到期,那么该方法将是无效的.如果您怀疑Kerberos基础架构不稳定,并且您不希望客户端操作支付重新登录的延迟成本,那么这将是在单独的后台线程中执行此操作的一个原因.只要确保在票的实际到期时间之前留一点点.您可以借用UserGroupInformation内的逻辑来确定票据是否“关闭”到期.实际上,我从来没有亲眼看到重新登录的延迟是有问题的.