
# Spark如何访问外部集群组件
#### 问题现象
存在两个集群：cluster1和cluster2，如何使用cluster1中的Spark访问cluster2中的HDFS、Hive、HBase和Kafka组件。
#### 处理步骤
1. 可以有条件地实现两个集群间组件互相访问，但是存在以下限制：
   - 仅允许访问一个Hive MetaStore，不支持同时访问cluster1的Hive MetaStore和cluster2的Hive MetaStore。
   
   - 不同集群的用户系统没有同步，因此访问跨集群组件时，用户的权限管理由对端集群的用户配置决定。比如cluster1的userA没有访问本集群HBase meta表权限，但是cluster2的userA有访问该集群HBase meta表权限，则cluster1的userA可以访问cluster2的HBase meta表。
   
   - 跨Manager之间的安全集群间组件互相访问，需要先配置系统互信。
    
2. 以下分别阐述cluster1上使用userA访问cluster2的Hive、HBase、Kafka组件。
   ![](https://support.huaweicloud.com/trouble-mrs/public_sys-resources/note_3.0-zh-cn.png)
   以下操作皆以用户使用FusionInsight客户端提交Spark2x应用为基础，如果用户使用了自己的配置文件目录，则需要修改本应用配置目录中的对应文件，并注意需要将配置文件上传到executor端。
   由于hdfs和hbase客户端访问服务端时，使用hostname配置服务端地址，因此，客户端的/etc/hosts需要保存有所有需要访问节点的hosts配置。用户可预先将对端集群节点的host添加到客户端节点的/etc/hosts文件中。
   - 访问Hive MetaStore：使用cluster2中的Spark2x客户端下"conf"目录下的hive-site.xml文件，替换到cluster1中的Spark2x客户端下"conf"目录下的hive-site.xml文件。 如上操作后可以用sparksql访问hive MetaStore，如需访问hive表数据，需要按照[•同时访问两个集群的HDFS：]的操作步骤配置且指定对端集群nameservice为LOCATION后才能访问表数据。
     
   
   - 访问对端集群的HBase：
     1. 先将cluster2集群的所有Zookeeper节点和HBase节点的IP和主机名配置到cluster1集群的客户端节点的/etc/hosts文件中。
     
     2. 使用cluster2中的Spark2x客户端下"conf"目录的hbase-site.xml文件，替换到cluster1中的Spark2x客户端下"conf"目录hbase-site.xml文件。
      
   
   - 访问Kafka，仅需将应用访问的Kafka Broker地址设置为cluster2中的Kafka Broker地址即可。
   
   - 同时访问两个集群的HDFS：
     - 无法同时获取两个相同nameservice的token，因此两个HDFS的nameservice必须不同，例如：一个为hacluster，一个为test。
       1. 从cluster2的hdfs-site.xml中获取以下配置，添加到cluster1的spark2x客户端conf目录的hdfs-site.xml中 dfs.nameservices.mappings、dfs.nameservices、dfs.namenode.rpc-address.test.\*、dfs.ha.namenodes.test、dfs.client.failover.proxy.provider.test
          参考样例如下：
          ```
          <property>
          <name>dfs.nameservices.mappings</name>
          <value>[{"name":"hacluster","roleInstances":["14","15"]},{"name":"test","roleInstances":["16","17"]}]</value>
          </property>
          <property>
          <name>dfs.nameservices</name>
          <value>hacluster,test</value>
          </property>
          <property>
          <name>dfs.namenode.rpc-address.test.16</name>
          <value>192.168.0.1:8020</value>
          </property>
          <property>
          <name>dfs.namenode.rpc-address.test.17</name>
          <value>192.168.0.2:8020</value>
          </property>
          <property>
          <name>dfs.ha.namenodes.test</name>
          <value>16,17</value>
          </property>
          <property>
          <name>dfs.client.failover.proxy.provider.test</name>
          <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
          </property>
          ```
          
       
       
       
       2. 修改cluster1的spark客户端conf目录下的spark-defaults.conf配置文件中，修改spark.yarn.extra.hadoopFileSystems = hdfs://test，spark.hadoop.hdfs.externalToken.enable = true，如下所示：
          ```
          spark.yarn.extra.hadoopFileSystems = hdfs://test
          spark.hadoop.hdfs.externalToken.enable = true
          ```
          
       
       
       
       3. 应用提交命令中，需要添加--keytab和--principal参数，参数配置为cluster1中提交任务的用户。
       
       4. 使用cluster1的spark客户端提交应用，即可同时访问两个HDFS服务。
        
      
   
   - 同时访问两个集群的HBase：
     1. 修改cluster1的spark客户端conf目录下的spark-defaults.conf配置文件中，修改spark.hadoop.hbase.externalToken.enable = true，如下所示：
        ```
        spark.hadoop.hbase.externalToken.enable = true
        ```
        
     
     2. 用户访问HBase时，需要使用对应集群的配置文件创建Configuration对象，用于创建Connection对象。
     
     3. MRS集群中支持同时获取多个HBase服务的token，以解决Executor中无法访问HBase的问题，使用方式如下： 假设需要访问本集群的HBase和cluster2的HBase，将cluster2的hbase-site.xml文件放到一个压缩包内，压缩包命名为external_hbase_conf\*\*\*，提交命令时，使用--archives指定这些压缩包。
        
      
    
 
