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

2022-09-01 14:57:14

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

UserGroupInformation.loginUserFromKeytabAndReturnUGI( ... );

这将返回我的实例,并在应用程序生存期内保留它。执行特权操作时,我使用 启动它们。UserGroupInformationugi.doAs(action)

这工作正常,但我想知道是否以及何时应该续订kerberos票证?我发现了一种方法,每当机票接近到期时,它似乎都会进行机票续订。我还发现,这种方法被各种Hadoop工具调用,例如。UserGroupInformationUserGroupInformation.checkTGTAndReloginFromKeytab()WebHdfsFileSystem

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

  1. 我可以在需要时依靠他们调用的各种Hadoop客户端吗?checkTGTAndReloginFromKeytab
  2. 我应该在代码中调用自己吗?checkTGTAndReloginFromKeytab
  3. 如果是这样,我应该在每次调用之前执行此操作,还是设置计时器并定期调用它(多久一次)?ugi.doAs(...)

答案 1

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

不幸的是,如果不深入研究应用程序的特定使用模式,就很难对此给出明确的答案。相反,我可以提供一般指南,并描述Hadoop何时会自动处理票证续订或从keytab重新登录,以及何时不会。

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

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

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

您可以将其视为重新登录的“惰性评估”。它仅在尝试的 RPC 连接上响应身份验证失败时重新执行登录。

知道了这一点,我们可以给出一个部分的答案。如果您的应用程序的使用模式是从 keytab 登录,然后执行典型的 Hadoop RPC 调用,那么您可能不需要滚动自己的重新登录代码。RPC 客户端层将为您完成此操作。“典型的Hadoop RPC”意味着绝大多数用于与Hadoop交互的Java API,包括HDFS FileSystem API,YarnClient和MapReduce Job提交。

但是,某些应用程序使用模式根本不涉及 Hadoop RPC。这方面的一个例子是仅与Hadoop的REST API交互的应用程序,例如WebHDFSYARN REST API。在这种情况下,身份验证模型通过 SPNEGO 使用 Kerberos,如 Hadoop HTTP 身份验证文档中所述。

知道了这一点,我们可以在答案中添加更多内容。如果您的应用程序的使用模式根本不使用Hadoop RPC,而是仅依赖于REST API,那么您必须滚动自己的重新登录逻辑。這正是為什麼WebHdfsFileSystem會稱呼UserGroupInformation#checkTGTAndReloginFromkeytab,就像你注意到的那樣。 选择在每次操作之前进行调用。这是一个很好的策略,因为UserGroupInformation#checkTGTAndReloginFromkeytab仅在票证“接近”到期时才续订票证。否则,该调用为无操作。WebHdfsFileSystem

作为最后一个用例,让我们考虑一个交互式过程,不是从 keytab 登录,而是要求用户在启动应用程序之前在外部运行。在绝大多数情况下,这些将是运行时间较短的应用程序,例如Hadoop CLI命令。但是,在某些情况下,这些进程可能是运行时间较长的进程。为了支持运行时间较长的进程,Hadoop 会启动一个后台线程来续订 Kerberos 票证“接近”到期。此逻辑在 UserGroupInformation#spawnAutoRenewalThreadForUserCreds 中可见。与 RPC 层中提供的自动重新登录逻辑相比,这里有一个重要的区别。在这种情况下,Hadoop只能续订票证并延长其使用寿命。门票具有最长的可再生寿命,这是由Kerberos基础设施决定的。之后,票证将不再可用。在这种情况下,重新登录几乎是不可能的,因为这意味着重新提示用户输入密码,并且他们可能会离开终端。这意味着,如果进程在票证过期后继续运行,它将无法再进行身份验证。kinit

同样,我们可以使用这些信息来告知我们的整体答案。如果您依靠用户在启动应用程序之前通过交互方式登录,并且您确信应用程序的运行时间不会超过Kerberos票证的最大可再生寿命,那么您可以依靠Hadoop内部功能来为您完成定期续订。kinit

如果您使用的是基于 keytab 的登录,并且您只是不确定应用程序的使用模式是否可以依赖于 Hadoop RPC 层的自动重新登录,那么保守的方法是推出自己的模式。@SamsonScharfrichter在这里给出了一个关于滚动自己的答案。

HBase Kerberos 连接续订策略

最后,我应该添加一个关于 API 稳定性的说明。Apache Hadoop兼容性指南详细讨论了Hadoop开发社区对向后兼容性的承诺。的接口带有注释和 。从技术上讲,这意味着 的 API 不被视为公共 API,并且它可能以向后不兼容的方式发展。实际上,根据 的接口,已经有很多代码,因此我们根本不可能进行重大更改。当然,在当前的2.x发行版中,我不会担心方法签名从你下面更改并破坏你的代码。UserGroupInformationLimitedPrivateEvolvingUserGroupInformationUserGroupInformation

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

我可以在需要时依靠他们称之为checkTGTAndReloginFromKeytab的各种Hadoop客户端吗?

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

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

如果您的应用程序的使用模式只是调用 Hadoop REST API 而不是 Hadoop RPC 调用,则可能需要执行此操作。您将无法获得在Hadoop的RPC客户端中实现的自动重新登录的好处。

如果是这样,我应该在每次调用ugi.doAs(...)之前这样做,还是设置一个计时器并定期调用它(多久一次)?

在需要进行身份验证的每个操作之前调用是可以的。如果票证未接近到期,则方法将为 no-op。如果您怀疑 Kerberos 基础结构运行缓慢,并且不希望客户端操作支付重新登录的延迟成本,那么这将是在单独的后台线程中执行此操作的原因。只要确保在机票的实际到期时间之前保持一点。您可以借用其中的逻辑来确定工单是否“接近”到期。在实践中,我个人从未见过重新登录的延迟有问题。UserGroupInformation#checkTGTAndReloginFromKeytabUserGroupInformation


答案 2

推荐