我应该在hadoop的每个动作之前调用ugi.checkTGTAndReloginFromKeytab()吗?

在我的服务器应用程序中,我从我的Java应用程序连接到Kerberos安全的Hadoop集群。 我正在使用各种组件,如HDFS文件系统,Oozie,Hive等。在应用程序启动时,我打电话

UserGroupInformation.loginUserFromKeytabAndReturnUGI( ... ); 

这将返回我UserGroupInformation实例,我保持它的应用程序的生命周期。 做特权行动时,我用ugi.doAs(action)启动它们。

这工作正常,但我想知道是否和何时更新UserGroupInformation Kerberos票? 我发现了一个方法UserGroupInformation.checkTGTAndReloginFromKeytab() ,它似乎在接近到期时进行票证续订。 我也发现这个方法正在被各种Hadoop工具调用,比如WebHdfsFileSystem

现在,如果我想要我的服务器应用程序(可能运行几个月甚至几年),永远不会遇到票证过期什么是最好的方法? 提供具体的问题:

  1. 我可以依赖他们在需要时调用checkTGTAndReloginFromKeytab的各种Hadoop客户端吗?
  2. 我应该在自己的代码中自己调用checkTGTAndReloginFromKeytab吗?
  3. 如果是这样,我应该在每次调用ugi.doAs(...)之前这样做,或者更确切地说,设置一个计时器并定期(多频繁地)调用它。

Hadoop提交者在这里! 这是一个很好的问题。

不幸的是,如果不深入研究应用程序的特定使用模式,就很难给出明确的答案。 相反,我可以提供一般准则,并描述何时Hadoop会自动处理票据更新或从密钥表中重新login,以及何时不会。

Hadoop生态系统中Kerberos身份validation的主要用例是Hadoop的RPC框架,它使用SASL进行身份validation。 Hadoop生态系统中的大多数守护进程通过在进程启动时对UserGroupInformation#loginUserFromKeytab进行一次一次调用来处理这个问题。 这样的例子包括HDFS DataNode,它必须authentication其对NameNode的RPC调用,以及YARN NodeManager,它必须authentication其对ResourceManager的调用。 像DataNode这样的守护进程如何在进程启动时进行一次性login,然后继续运行好几个月,就像典型的过期时间一样?

由于这是一个常见的用例,Hadoop在RPC客户端层直接实现了自动重新login机制。 此代码在RPC Client#handleSaslConnectionFailure方法中可见:

  // try re-login if (UserGroupInformation.isLoginKeytabBased()) { UserGroupInformation.getLoginUser().reloginFromKeytab(); } else if (UserGroupInformation.isLoginTicketBased()) { UserGroupInformation.getLoginUser().reloginFromTicketCache(); } 

你可以把这看作是重新login的“懒惰评价”。 它只是重新执行login以响应尝试的RPC连接的身份validation失败。

知道这一点,我们可以给出部分答案。 如果您的应用程序的使用模式是从密钥表login,然后执行典型的Hadoop RPC调用,那么您可能不需要推出自己的重新login代码。 RPC客户端层将为您完成。 “典型的Hadoop RPC”是指绝大多数与Hadoop交互的Java API,包括HDFS FileSystem API, YarnClient和MapReduce Job提交。

但是,一些应用程序使用模式完全不涉及Hadoop RPC。 一个例子就是只与Hadoop的REST API(如WebHDFS或YARN REST API)交互的应用程序。 在这种情况下,身份validation模型将通过SPNEGO使用Kerberos,如Hadoop HTTP身份validation文档中所述。

知道这一点,我们可以添加更多的答案。 如果您的应用程序的使用模式根本不使用Hadoop RPC,而是完全依赖于REST API,那么您必须推出自己的重新login逻辑。 这正是WebHdfsFileSystem调用UserGroupInformation#checkTGTAndReloginFromkeytab ,就像你注意到的一样。 WebHdfsFileSystemselect在每个操作之前进行调用。 这是一个很好的策略,因为UserGroupInformation#checkTGTAndReloginFromkeytab只有在票证“closures”到期时才会更新票证。 否则,这个电话是无效的。

作为最终用例,让我们考虑一个交互式进程,而不是从keytablogin,而是要求用户在启动应用程序之前在外部运行kinit 。 在绝大多数情况下,这些将是短期运行的应用程序,例如Hadoop CLI命令。 但是,在某些情况下,这些可能是更长时间运行的过程。 为了支持运行时间更长的进程,Hadoop启动一个后台线程来将Kerberos票证“close”更新为过期。 这个逻辑在UserGroupInformation#spawnAutoRenewalThreadForUserCreds是可见的。 与RPC层提供的自动重login逻辑相比,这里有一个重要的区别。 在这种情况下,Hadoop只能够更新票证并延长其使用期限。 按照Kerberos基础设施的规定,票据具有最长的可更新时间。 之后,门票将不再可用。 在这种情况下重新login实际上是不可能的,因为这意味着重新提示用户input密码,并且他们可能离开terminal。 这意味着,如果进程继续运行,而不会超过票证,则无法再进行身份validation。

再次,我们可以使用这些信息来通知我们的整体答案。 如果您在启动应用程序之前依靠用户通过kinit以交互方式login,并且如果您确信应用程序的运行时间不会超过Kerberos票据的最长可用生命周期,那么您可以依赖Hadoop内部机制来为您定期更新。

如果您使用基于keytab的login,而您不确定您的应用程序的使用模式是否可以依赖于Hadoop RPC层的自动重新login,那么保守的方法就是自行开发。 @SamsonScharfrichter在这里给出了一个很好的答案。

HBase Kerberos连接更新策略

最后,我应该添加关于API稳定性的说明。 Apache Hadoop Compatibility准则详细讨论了Hadoop开发社区向后兼容的承诺。 UserGroupInformation的接口注释了LimitedPrivateEvolving 。 从技术上讲,这意味着UserGroupInformation的API不被视为公共的,并且可能以不相容的方式进化。 实际上,根据UserGroupInformation的接口,已经有很多代码了,所以我们做一个突破性的改变根本是不可行的。 当然,在目前的2.x发行版中,我不会担心方法签名会从你的下面改变出来并破坏你的代码。

现在我们已经掌握了所有这些背景信息,让我们重新回顾一下您的具体问题。

我可以依赖他们在需要时调用checkTGTAndReloginFromKeytab的各种Hadoop客户端吗?

如果您的应用程序的使用模式是调用Hadoop客户端,而Hadoop客户端又使用Hadoop的RPC框架,那么您可以依靠这一点。 如果您的应用程序的使用模式只调用Hadoop REST API,则不能依赖此。

我应该在自己的代码中自己调用checkTGTAndReloginFromKeytab吗?

如果应用程序的使用模式仅用于调用Hadoop REST API而不是Hadoop RPC调用,则可能需要执行此操作。 你不会得到在Hadoop的RPC客户端中实现的自动重新login的好处。

如果是这样,我应该在每次调用ugi.doAs(…)之前这样做,或者更确切地说,设置一个计时器并定期(多频繁地)调用它。

在需要进行身份validation的每个操作之前调用UserGroupInformation#checkTGTAndReloginFromKeytab就可以了。 如果票据没有到期,那么该方法将是空的。 如果您怀疑您的Kerberos基础架构不稳定,并且您不希望客户端操作支付重新login的延迟成本,那么这将成为在单独的后台线程中执行此操作的原因。 只要确保在票证的实际到期时间之前保持一点点。 您可以借用UserGroupInformation的逻辑来确定票证是否“过期”。 在实践中,我从来没有亲眼见过重新login的延迟是有问题的。