我使用的是Spark-2.4,我有一个启用Kerberos的集群,正在尝试通过spark-sql shell运行查询。

简化的设置基本上看起来像这样:spark-sql shell在Yarn群集中的一台主机上运行->运行一台主机的外部hive-metastore-> S3以存储表数据。

当我启动启用了DEBUG日志记录的spark-sql shell时,这就是我在日志中看到的内容:

> bin/spark-sql --proxy-user proxy_user

...
DEBUG HiveDelegationTokenProvider: Getting Hive delegation token for proxy_user against hive/_HOST@REALM.COM at thrift://hive-metastore:9083
DEBUG UserGroupInformation: PrivilegedAction as:spark/spark_host@REALM.COM (auth:KERBEROS) from:org.apache.spark.deploy.security.HiveDelegationTokenProvider.doAsRealUser(HiveDelegationTokenProvider.scala:130)

这意味着Spark进行了调用,以从Hive元存储中获取委托(delegate) token ,然后将其添加到UGI的凭据列表中。在Spark中执行This is the piece of code。我还在metastore日志中验证了是否正在进行get_delegation_token()调用。

现在,当我运行像create table test_table (id int) location "s3://some/prefix";这样的简单查询时,我遇到了AWS凭证错误。我修改了配置单元metastore代码,并在初始化Hadoop中的文件系统(org/apache/hadoop/hive/metastore/Warehouse.java)之前添加了此代码:
 public static FileSystem getFs(Path f, Configuration conf) throws MetaException {
...
    try {
      // get the current user
      UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
      LOG.info("UGI information: " + ugi);
      Collection<Token<? extends TokenIdentifier>> tokens = ugi.getCredentials().getAllTokens();
      // print all the tokens it has
      for(Token token : tokens) {
        LOG.info(token);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
...
}

在metastore日志中,这确实会打印正确的UGI信息:
UGI information: proxy_user (auth:PROXY) via hive/hive-metastore@REALM.COM (auth:KERBEROS)

但UGI中没有 token 。好像Spark code添加了别名hive.server2.delegation.token,但我在UGI中看不到它。这使我怀疑,以某种方式隔离了UGI范围,而不在spark-sql和hive元存储之间共享UGI范围。我该如何解决呢?

最佳答案

Spark不会获取您的Kerberos身份-它要求每个FS发出一些“委托(delegate) token ”,以使调用方可以与该服务以及该服务进行交互。这受到更多限制,因此更加安全。

这里的问题是spark从每个可以发布它们的文件系统中收集委托(delegate) token -并且由于您的S3连接器没有发布任何 token ,因此没有任何问题。

现在,可以将Apache Hadoop 3.3.0的S3A连接器设置为在委派 token 中发布您的AWS凭证,或者,为了获得额外的安全性,请向AWS索取 session 凭证,然后仅将其发送出去。但是(a)您需要具有这些依赖关系的Spark构建,并且(b)Hive需要使用这些凭据与S3进行通信。

09-26 18:25
查看更多