我正在使用 Spark-2.4,我有一个启用 Kerberos 的集群,我正在尝试通过spark-sql
shell 运行查询。
简化的设置基本上如下所示:在 Yarn 集群中的一台主机上运行的 spark-sql shell -> 运行一台主机的外部 hive-metastore -> 用于存储表数据的 S3。
当我在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 元存储中获取委托令牌,然后将其添加到 UGI 的凭据列表中。这是 Spark 中的一段代码。我还在 Metastore 日志中验证了正在进行get_delegation_token()
调用。
现在,当我运行一个简单的查询时,例如create table test_table (id int) location "s3://some/prefix";
遇到 AWS 凭证错误。我修改了配置单元元存储代码,并在初始化 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();
}
...
}
在元存储日志中,这会打印正确的 UGI 信息:
UGI information: proxy_user (auth:PROXY) via hive/hive-metastore@REALM.COM (auth:KERBEROS)
但是 UGI 中没有代币。看起来Spark 代码使用别名添加了它,hive.server2.delegation.token
但我在 UGI 中看不到它。这让我怀疑 UGI 范围以某种方式被隔离并且没有在 spark-sql 和 hive 元存储之间共享。我该如何解决这个问题?