hive 访问控制异常:使用配置单元仓库时,客户端无法通过[TOKEN,KERBEROS]进行身份验证

gojuced7  于 2022-11-05  发布在  Hive
关注(0)|答案(1)|浏览(615)

我们最近在Spark集群上启用了Kerberos身份验证,但是我们发现当我们在集群模式下提交Spark作业时,代码无法连接到Hive。我们是否应该使用Kerberos来验证Hive,如果是,如何验证?如下所述,我认为我们必须指定keytab和principal,但我不知道具体是什么。
这是我们得到的异常:

Traceback (most recent call last):
  File "/mnt/resource/hadoop/yarn/local/usercache/sa-etl/appcache/application_1649255698304_0003/container_e01_1649255698304_0003_01_000001/__pyfiles__/utils.py", line 222, in use_db
    spark.sql("CREATE DATABASE IF NOT EXISTS `{db}`".format(db=db))
  File "/usr/hdp/current/spark3-client/python/pyspark/sql/session.py", line 723, in sql
    return DataFrame(self._jsparkSession.sql(sqlQuery), self._wrapped)
  File "/usr/hdp/current/spark3-client/python/lib/py4j-0.10.9-src.zip/py4j/java_gateway.py", line 1305, in __call__
  File "/usr/hdp/current/spark3-client/python/pyspark/sql/utils.py", line 117, in deco
    raise converted from None
pyspark.sql.utils.AnalysisException: java.lang.RuntimeException: java.io.IOException: DestHost:destPort hn1-pt-dev.MYREALM:8020 , LocalHost:localPort wn1-pt-dev/10.208.3.12:0. Failed on local exception: java.io.IOException: org.apache.hadoop.security.AccessControlException: Client cannot authenticate via:[TOKEN, KERBEROS]

此外,我还看到了以下异常:

org.apache.hadoop.security.AccessControlException: Client cannot authenticate via:[TOKEN, KERBEROS], while invoking ClientNamenodeProtocolTranslatorPB.getFileInfo over hn0-pt-dev.myrealm/10.208.3.15:8020

这是产生异常的脚本,如您所见,它发生在CREATE DATABASE上:

from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('Test').enableHiveSupport().getOrCreate()
spark.sql("CREATE DATABASE IF NOT EXISTS TestDb")

环境及相关信息

我们在Azure中有一个启用ESP的HDInsight群集,它位于虚拟网络内。AADDS可以正常登录到群集。该群集连接到存储帐户,通过ABFS与它通信,并在那里存储Hive仓库。我们使用Yarn。我们希望使用Azure数据工厂中的PySpark执行Spark作业,该工厂使用Livy、但如果我们能让它与spark-submit cli一起工作,那么它也有希望与Livy一起工作。
只有在使用spark-submit --deploy-mode cluster时才会出现异常,而在使用客户端模式时则不会出现异常并创建数据库。
当我们删除.enableHiveSupport时,异常也消失了,所以它显然与对Hive的身份验证有关。但我们确实需要Hive仓库,因为我们需要从多个Spark会话中访问表,所以它们需要被持久化。
我们可以访问HDFS,也可以在集群模式下访问,因为sc.textFile('/example/data/fruits.txt').collect()工作正常。

类似的问题和可能的解决方案

在异常中,我看到是工作节点试图访问头节点。端口是8020,我认为这是namenode端口,所以这听起来确实与HDFS相关--除了据我所知,我们可以访问HDFS,但不能访问Hive。

  • https://spark.apache.org/docs/latest/running-on-yarn.html#kerberos它建议显式指定主体和keytab文件,因此我找到了keytab文件klist -k,并将其添加到spark-submit命令行--principal myusername@MYREALM --keytab /etc/krb5.keytab,它与下面链接的问题之一中的keytab文件相同,但我得到了
Exception in thread "main" org.apache.hadoop.security.KerberosAuthException: failure to login: for principal: myusername@MYREALM from keytab /etc/krb5.keytab javax.security.auth.login.LoginException: Unable to obtain password from user

也许我有错误的keytab文件,因为当我klist -k /etc/krb5.keytab文件,我只得到像HN0-PT-DEV@MYREALMhost/hn0-pt-dev.myrealm@MYREALM的条目插槽。如果我在/etc/security/keytabs中查找hdfs/hive的keytab,我也只看到hdfs/hive用户的条目。
当我尝试添加How to use Apache Spark to query Hive table with Kerberos?中指定的所有extraJavaOptions但不指定principal/keytab时,即使/etc/krb5.conf中的默认领域是正确的,我也会得到KrbException: Cannot locate default realm
在Ambari,我可以看到设置spark.yarn.keytab={{hive_kerberos_keytab}}spark.yarn.principal={{hive_kerberos_principal}}

  • https://learn.microsoft.com/en-us/azure/hdinsight/hdinsight-faq#how-do-i-create-a-keytab-for-an-hdinsight-esp-cluster-我为我的用户创建了一个keytab,并指定了该文件,但这没有帮助。

似乎许多其他答案/网站也建议显式指定principal/keytab:

Spark应用要与HDFS、HBase和Hive交互,必须使用启动应用的用户的Kerberos凭证来获取相关令牌--也就是说,主体的身份将成为启动的Spark应用的身份。在一个安全的集群中,Spark会自动为集群的HDFS文件系统获取一个令牌,可能还会为HBase和Hive获取令牌。
好的,启动应用程序的用户拥有有效的ticket,如klist的输出所示。用户拥有对blob存储的贡献者访问权限(不确定是否真的需要)。我不明白“Spark将自动获得Hive的令牌[在启动时]”是什么意思。我确实重新启动了集群上的所有服务,但这没有帮助。

在yarn-cluster模式下,Spark客户端使用本地Kerberos票证连接Hadoop服务,并检索特殊的auth令牌,然后将这些令牌发送到运行驱动程序的YARN容器;则驱动程序将令牌广播给执行器

更新

以配置单元用户身份登录时:
kinit,然后提供hive密码:

Password for hive/hn0-pt-dev.myrealm@MYREALM: 
kinit: Password incorrect while getting initial credentials

hive@hn0-pt-dev:/tmp$ klist -k /etc/security/keytabs/hive.service.keytab
Keytab name: FILE:/etc/security/keytabs/hive.service.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   0 hive/hn0-pt-dev.myrealm@MYREALM
   0 hive/hn0-pt-dev.myrealm@MYREALM
   0 hive/hn0-pt-dev.myrealm@MYREALM
   0 hive/hn0-pt-dev.myrealm@MYREALM
   0 hive/hn0-pt-dev.myrealm@MYREALM
hive@hn0-pt-dev:/tmp$ kinit -k /etc/security/keytabs/hive.service.keytab
kinit: Client '/etc/security/keytabs/hive.service.keytab@MYREALM' not found in Kerberos database while getting initial credentials
sbdsn5lh

sbdsn5lh1#

一般来说,你必须完成一个[kinit successfully]/[pass a principle/keytab]才能在spark/hive中使用Kerberos。它们的一些设置使hive的使用复杂化了。(模拟)
一般来说,如果你可以kinit并使用hdfs来写入你自己的文件夹,你的keytab就可以工作了:

kinit #enter user info
hdfs dfs -touch /home/myuser/somefile #gurantees you have a home directory... spark needs this

一旦你知道它是工作的,你应该检查你是否可以写到hive:
使用JDBC连接或使用如下连接字符串的直线连接

jdbc:hive2://HiveHost:10001/default;principal=myuser@HOST1.COM;

这有助于找到问题所在。
如果您正在查找与配置单元有关的问题,则需要check impersonation
HiveServer 2模拟重要信息:这不是实现HiveServer 2授权的推荐方法。Cloudera建议您使用Sentry来实现此功能。HiveServer 2模拟允许用户以连接用户而不是超级用户的身份执行查询和访问HDFS文件。访问策略使用ACL中指定的HDFS权限在文件级别应用(访问控制列表)。启用HiveServer 2模拟将绕过Sentry的端到端授权过程。特别是,尽管Sentry对配置单元仓库中的表和视图强制实施访问控制策略,它不控制对表所基于的HDFS文件的访问。这意味着,对仓库中的表没有Sentry权限的用户,只要对支持该表的HDFS文件具有权限,就可以绕过Sentry授权检查,对仓库中的表执行作业和查询。
如果你使用的是windows系统,你应该注意一下ticket缓存。你应该考虑设置你自己的ticket缓存位置,因为windows系统通常会为所有用户使用一个通用的位置。(这会让用户在登录时产生奇怪的错误。)
如果您遇到了hive问题,hive日志本身通常会帮助您了解进程无法工作的原因(但是,只有在某些kerberos成功时,您才会有日志,如果完全不成功,您将看不到任何内容)。
检查Ranger并查看是否存在任何错误。

  • 如果你想使用集群模式并访问Hive仓库,你需要指定keytab和principal来进行spark-submit(这在官方文档中是明确的)

通过为Spark提供一个主体和密钥表(例如,使用带有--principal和--keytab参数的spark-submit),应用程序将维护一个有效的Kerberos登录,该登录可用于无限期地检索委托令牌。
请注意,在集群模式下使用keytab时,它将被复制到运行Spark驱动程序的机器上。对于YARN,这意味着使用HDFS作为keytab的暂存区,因此强烈建议至少对YARN和HDFS进行加密保护。

  • 您需要创建own keytab
  • 创建keytab后,确保正确的用户拥有它的权限,否则您将再次获得Unable to obtain password from user

如果您使用Livy --proxy-user,则会与--principal冲突,但这很容易解决。(用途:livy.模拟.已启用=假)

相关问题