启用Kerberos的Hive1.1.0远程元存储Spark1.6.0 SQL查询异常
解决Spark访问Hive表数据时的
UnknownHostException: xxx-nameservice错误 从你的错误堆栈和代码来看,问题的核心很明确:你的Spark节点无法解析HDFS高可用(HA)集群中的xxx-nameservice标识。
为什么之前能查看库表但查数据失败?
show tables这类操作只需要和Hive Metastore交互,读取元数据信息,不需要访问HDFS;- 而
select * from tab1需要读取实际存储在HDFS上的表数据,这时候Spark必须能识别HDFS HA的nameservice,并找到对应的NameNode节点。
具体解决方案
1. 同步HDFS HA配置文件到Spark节点
Spark需要Hadoop的core-site.xml和hdfs-site.xml来识别HDFS的HA配置,你需要从Hadoop集群的配置目录(通常是$HADOOP_HOME/etc/hadoop)复制这两个文件到Spark的conf目录下($SPARK_HOME/conf)。
关键配置项示例(根据你的实际集群调整):
- core-site.xml中需包含:
<property> <name>fs.defaultFS</name> <value>hdfs://xxx-nameservice</value> </property> - hdfs-site.xml中需包含HA相关配置:
<!-- 定义nameservice名称 --> <property> <name>dfs.nameservices</name> <value>xxx-nameservice</value> </property> <!-- 指定该nameservice下的NameNode节点标识 --> <property> <name>dfs.ha.namenodes.xxx-nameservice</name> <value>nn1,nn2</value> </property> <!-- 每个NameNode的RPC访问地址 --> <property> <name>dfs.namenode.rpc-address.xxx-nameservice.nn1</name> <value>你的nn1主机名:8020</value> </property> <property> <name>dfs.namenode.rpc-address.xxx-nameservice.nn2</name> <value>你的nn2主机名:8020</value> </property> <!-- 故障转移代理类 --> <property> <name>dfs.client.failover.proxy.provider.xxx-nameservice</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property>
2. 确保Spark节点能解析NameNode主机名
复制完配置后,在Spark节点上ping一下配置中的NameNode主机名(比如你的nn1主机名),如果ping不通:
- 直接修改Spark节点的
/etc/hosts文件,添加主机名和对应IP的映射; - 或者确保集群的DNS服务能正确解析这些主机名。
3. Kerberos环境额外配置(如果你的集群启用了Kerberos)
如果是Kerberos认证的集群,还要确保:
- Spark节点已经获取了有效的Kerberos ticket(可以用
kinit命令验证); hdfs-site.xml中包含正确的Kerberos相关配置,比如:<property> <name>dfs.namenode.kerberos.principal</name> <value>hdfs/_HOST@YOUR.REALM</value> </property>
4. 临时方案:代码中直接设置HDFS配置(不推荐长期使用)
如果暂时无法修改配置文件,也可以在代码中直接添加HDFS HA的配置:
val hiveContext = new org.apache.spark.sql.hive.HiveContext(sc) // 添加HDFS HA配置 hiveContext.setConf("fs.defaultFS", "hdfs://xxx-nameservice") hiveContext.setConf("dfs.nameservices", "xxx-nameservice") hiveContext.setConf("dfs.ha.namenodes.xxx-nameservice", "nn1,nn2") hiveContext.setConf("dfs.namenode.rpc-address.xxx-nameservice.nn1", "你的nn1主机名:8020") hiveContext.setConf("dfs.namenode.rpc-address.xxx-nameservice.nn2", "你的nn2主机名:8020") hiveContext.setConf("dfs.client.failover.proxy.provider.xxx-nameservice", "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider") // 原有配置 hiveContext.setConf("hive.metastore.uris", prop.getProperty("hive.metastore.uris")) // ... 其他Hive配置 hiveContext.sql("use abc") hiveContext.sql("show tables").show(4) hiveContext.sql("select * from abc.tab1 limit 10").show(2)
按照以上步骤配置后,应该就能正常读取Hive表的数据了。
内容的提问来源于stack exchange,提问作者Souvik
相关产品推荐
相关产品推荐

