在我的服务器应用程序中,我从我的Java应用程序连接到Kerberos安全的Hadoop集群.我正在使用各种组件,如HDFS文件系统,Oozie,Hive等.在应用程序启动时,我打电话
UserGroupInformation.loginUserFromKeytabAndReturnUGI( ... );
这将返回我的UserGroupInformation
实例,并将其保留为应用程序生命周期.在执行特权操作时,我将其启动ugi.doAs(action)
.
这工作正常,但我想知道是否以及何时更新kerberos票UserGroupInformation
?我找到了一种方法UserGroupInformation.checkTGTAndReloginFromKeytab()
,似乎只要它接近到期就会更新机票.我还发现这种方法正在被各种Hadoop工具调用WebHdfsFileSystem
,例如.
现在,如果我希望我的服务器应用程序(可能运行数月甚至数年)永远不会体验票证过期,那么最佳方法是什么?提出具体问题:
我可以依赖他们checkTGTAndReloginFromKeytab
在需要时调用的各种Hadoop客户端吗?
我应该checkTGTAndReloginFromKeytab
在我的代码中自己打电话吗?
如果是这样,我应该在每次打电话ugi.doAs(...)
或者更确切地设置定时器之前这样做并定期调用它(多久一次)?
Chris Naurot.. 67
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 API.在这种情况下,身份验证模型通过SPNEGO使用Kerberos,如Hadoop HTTP身份验证文档中所述.
了解这一点,我们可以为我们的答案添加更多内容.如果您的应用程序的使用模式根本不使用Hadoop RPC,而是仅仅依赖于REST API,那么您必须使用自己的重新登录逻辑.就像你注意到的那样,这正是WebHdfsFileSystem
电话会议的UserGroupInformation#checkTGTAndReloginFromkeytab
原因. WebHdfsFileSystem
选择在每次操作之前拨打电话.这是一个很好的策略,因为UserGroupInformation#checkTGTAndReloginFromkeytab
只有在票证"关闭"到期时才更新票证. 否则,呼叫是无操作.
作为最终用例,让我们考虑一个交互式过程,而不是从keytab登录,而是要求用户kinit
在启动应用程序之前在外部运行.在绝大多数情况下,这些将是短期运行的应用程序,例如Hadoop CLI命令.但是,在某些情况下,这些可能是运行时间较长的过程.为了支持更长时间运行的进程,Hadoop启动后台线程以将Kerberos票证更新为"关闭"到期.这个逻辑可见UserGroupInformation#spawnAutoRenewalThreadForUserCreds
.与RPC层中提供的自动重新登录逻辑相比,这里有一个重要的区别.在这种情况下,Hadoop只能续订票证并延长其使用寿命.根据Kerberos基础设施的规定,票证具有最大可续订生命周期.之后,票证将不再可用.在这种情况下重新登录几乎是不可能的,因为它意味着重新提示用户输入密码,并且他们可能会离开终端.这意味着如果进程持续运行超过故障单到期,它将无法再进行身份验证.
同样,我们可以使用此信息来告知我们的总体答案.如果您kinit
在启动应用程序之前依赖用户以交互方式登录,并且如果您确信应用程序的运行时间不会超过Kerberos票证的最长可续订生命周期,那么您可以依赖Hadoop内部来为您定期续订.
如果您正在使用基于keytab的登录,并且您只是不确定您的应用程序的使用模式是否可以依赖于Hadoop RPC层的自动重新登录,那么保守的方法就是使用自己的方法.@SamsonScharfrichter在这里给出了一个关于滚动自己的优秀答案.
HBase Kerberos连接更新策略
最后,我应该添加一个关于API稳定性的说明.该Apache Hadoop Compatibility
指南讨论了Hadoop开发社区对完全详细的向后兼容性的承诺.接口UserGroupInformation
是注释LimitedPrivate
和Evolving
.从技术上讲,这意味着API UserGroupInformation
不被认为是公开的,它可能以向后兼容的方式发展.实际上,有许多代码已经取决于接口UserGroupInformation
,因此我们根本不可能进行重大改变.当然在当前的2.x版本行中,我不会担心方法签名会从您身下更改并破坏您的代码.
现在我们已经掌握了所有这些背景信息,让我们重新审视您的具体问题.
我可以依赖他们在需要时调用checkTGTAndReloginFromKeytab的各种Hadoop客户端吗?
如果您的应用程序的使用模式是调用Hadoop客户端,那么您可以依赖于此,而Hadoop客户端又使用Hadoop的RPC框架.如果应用程序的使用模式仅调用Hadoop REST API,则不能依赖于此.
我应该在我的代码中自己调用checkTGTAndReloginFromKeytab吗?
如果应用程序的使用模式仅用于调用Hadoop REST API而不是Hadoop RPC调用,则可能需要执行此操作.您无法获得在Hadoop的RPC客户端中实现的自动重新登录的好处.
如果是这样,我应该在每次调用ugi.doAs(...)之前这样做,或者更确切地说是设置一个定时器并定期调用它(多久一次)?
UserGroupInformation#checkTGTAndReloginFromKeytab
在每个需要进行身份验证的操作之前调用它是完好的.如果票证未接近到期,则该方法将是无操作.如果您怀疑您的Kerberos基础架构缓慢,并且您不希望客户端操作支付重新登录的延迟成本,那么这将是在单独的后台线程中执行此操作的原因.请务必保持在票证的实际到期时间之前.您可以借用内部逻辑UserGroupInformation
来确定故障单是否"过期"到期.在实践中,我从未亲眼看到重新登录的延迟是有问题的.
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 API.在这种情况下,身份验证模型通过SPNEGO使用Kerberos,如Hadoop HTTP身份验证文档中所述.
了解这一点,我们可以为我们的答案添加更多内容.如果您的应用程序的使用模式根本不使用Hadoop RPC,而是仅仅依赖于REST API,那么您必须使用自己的重新登录逻辑.就像你注意到的那样,这正是WebHdfsFileSystem
电话会议的UserGroupInformation#checkTGTAndReloginFromkeytab
原因. WebHdfsFileSystem
选择在每次操作之前拨打电话.这是一个很好的策略,因为UserGroupInformation#checkTGTAndReloginFromkeytab
只有在票证"关闭"到期时才更新票证. 否则,呼叫是无操作.
作为最终用例,让我们考虑一个交互式过程,而不是从keytab登录,而是要求用户kinit
在启动应用程序之前在外部运行.在绝大多数情况下,这些将是短期运行的应用程序,例如Hadoop CLI命令.但是,在某些情况下,这些可能是运行时间较长的过程.为了支持更长时间运行的进程,Hadoop启动后台线程以将Kerberos票证更新为"关闭"到期.这个逻辑可见UserGroupInformation#spawnAutoRenewalThreadForUserCreds
.与RPC层中提供的自动重新登录逻辑相比,这里有一个重要的区别.在这种情况下,Hadoop只能续订票证并延长其使用寿命.根据Kerberos基础设施的规定,票证具有最大可续订生命周期.之后,票证将不再可用.在这种情况下重新登录几乎是不可能的,因为它意味着重新提示用户输入密码,并且他们可能会离开终端.这意味着如果进程持续运行超过故障单到期,它将无法再进行身份验证.
同样,我们可以使用此信息来告知我们的总体答案.如果您kinit
在启动应用程序之前依赖用户以交互方式登录,并且如果您确信应用程序的运行时间不会超过Kerberos票证的最长可续订生命周期,那么您可以依赖Hadoop内部来为您定期续订.
如果您正在使用基于keytab的登录,并且您只是不确定您的应用程序的使用模式是否可以依赖于Hadoop RPC层的自动重新登录,那么保守的方法就是使用自己的方法.@SamsonScharfrichter在这里给出了一个关于滚动自己的优秀答案.
HBase Kerberos连接更新策略
最后,我应该添加一个关于API稳定性的说明.该Apache Hadoop Compatibility
指南讨论了Hadoop开发社区对完全详细的向后兼容性的承诺.接口UserGroupInformation
是注释LimitedPrivate
和Evolving
.从技术上讲,这意味着API UserGroupInformation
不被认为是公开的,它可能以向后兼容的方式发展.实际上,有许多代码已经取决于接口UserGroupInformation
,因此我们根本不可能进行重大改变.当然在当前的2.x版本行中,我不会担心方法签名会从您身下更改并破坏您的代码.
现在我们已经掌握了所有这些背景信息,让我们重新审视您的具体问题.
我可以依赖他们在需要时调用checkTGTAndReloginFromKeytab的各种Hadoop客户端吗?
如果您的应用程序的使用模式是调用Hadoop客户端,那么您可以依赖于此,而Hadoop客户端又使用Hadoop的RPC框架.如果应用程序的使用模式仅调用Hadoop REST API,则不能依赖于此.
我应该在我的代码中自己调用checkTGTAndReloginFromKeytab吗?
如果应用程序的使用模式仅用于调用Hadoop REST API而不是Hadoop RPC调用,则可能需要执行此操作.您无法获得在Hadoop的RPC客户端中实现的自动重新登录的好处.
如果是这样,我应该在每次调用ugi.doAs(...)之前这样做,或者更确切地说是设置一个定时器并定期调用它(多久一次)?
UserGroupInformation#checkTGTAndReloginFromKeytab
在每个需要进行身份验证的操作之前调用它是完好的.如果票证未接近到期,则该方法将是无操作.如果您怀疑您的Kerberos基础架构缓慢,并且您不希望客户端操作支付重新登录的延迟成本,那么这将是在单独的后台线程中执行此操作的原因.请务必保持在票证的实际到期时间之前.您可以借用内部逻辑UserGroupInformation
来确定故障单是否"过期"到期.在实践中,我从未亲眼看到重新登录的延迟是有问题的.