Kerberos安全认证之配置和访问Kerberos安全认证的Hive集群学习笔记

文章目录

前言

个人介绍

博主介绍:✌目前全网粉丝3W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。

涵盖技术内容:Java后端、大数据、算法、分布式微服务、中间件、前端、运维等。

博主所有博客文件目录索引:博客目录索引(持续更新)

视频平台:b站-Coder长路

当前博客相关内容介绍

学习kerberos主要原因是目前部门里会有测试kerberos连通性的问题bug,所以以此来系统学习下kerberos安全认证,主要是学习在kerberos安全配置下如何去访问各个大数据组件。

Kerberos安全认证系列学习教程(B站):https://www.bilibili.com/video/BV1rr421t7Zt【马士兵的系列课程】

学习配套源码(Gitee):https://gitee.com/changluJava/demo-exer/tree/master/bigdata/kerberos/kerberosAuth


一、远程hive连接进行kerberos安全认证

Hive底层数据存储在HDFS中,HQL执行默认会转换成MR执行在Yarn中,当HDFS配置了Kerberos安全认证时,只对HDFS进行认证是不够的,因为Hive作为数据仓库基础架构也需要访问HDFS上的数据。因此,为了确保整个大数据环境的安全性,Hive也需要配置Kerberos安全认证,这样可以控制对Hive和底层HDFS数据的访问权限,防止未经授权的访问和操作,确保数据的安全性。

目前对HDFS进行了Kerberos安全认证后,在Hive 客户端 虽然进行了用户主体认证,但在操作Hive时也不能正常操作Hive,需要对Hive进行kerberos安全认证。

#在node1启动Hive metastore
hive --service metastore &

目前hdfs已经开启了kerberos认证,我们在【node3】节点执行hive就会报安全认证错误:

hive

image-20240707123658931

在【node3】节点上进行安全认证

# 切换到zhangsan
su zhangsan

# 密码:123456
kinit zhangsan

# 启动命令行
hive

# 查询表
show tables;

image-20240707124001833


二、Hive配置Kerberos

Hive配置Kerberos的前提是Hadoop需要配置Kerberos,这里已经在Hadoop集群中配置了Kerberos。按照如下步骤进行Hive使用Kerberos配置即可。

1、创建 hive 用户并设置组

在Hadoop集群中操作不同的服务有不同的用户,这里使用hive用户操作hive。在node1~node5所有hadoop节点上创建hive用户(非hive服务端和客户端也需要创建),后续执行HQL时会转换成MR任务执行于各个NodeManager节点,所以这里在所有集群节点中创建hive用户并设置所属组为hadoop。

#node1~node5所有节点执行命令创建hive用户,设置密码为123456
useradd hive -g hadoop
passwd hive

注意:创建hive用户以后,最好重启下HDFS集群,否则后续使用hive用户执行SQL时没有操作目录的权限。

2、创建Hive 服务的 Princial 主体

在kerberos 服务端执行如下命令,创建Hive服务的kerberos Princial主体,然后将服务主体写入keytab文件。

#在kerberos 服务端【node1】节点执行如下命令
kadmin.local -q "addprinc -pw 123456 hive/node1"

#【node1】将hive服务主体写入keytab文件
 kadmin.local -q "ktadd -norandkey -kt /home/keytabs/hive.service.keytab hive/node1@EXAMPLE.COM"

以上命令执行后,可以在node1节点的/home/keytabs目录下看到生成对应的hive.server.keytab文件。

image-20240707154602817

3、分发 keytab 文件并修改所属用户和组

将生成的hive服务对应的keytab密钥文件发送到hive服务端和客户端,这里【node1】为hive服务端,只需要发送到hive客户端node3节点即可。

#【node1】发送keytab 到node3节点
scp /home/keytabs/hive.service.keytab node3:/home/keytabs/

#在node1、node3两个节点修改keytab所属用户和组
chown root:hadoop /home/keytabs/hive.service.keytab 
chmod 770 /home/keytabs/hive.service.keytab

4、修改 hive-site.xml 配置文件

在hive服务端【node1】和客户端【node3】配置hive-site.xml,向该配置中追加如下配置:

vim $HIVE_HOME/conf/hive-site.xml

追加内容如下:

 <!-- hiveserver2 支持kerberos认证 -->
 <property>
  <name>hive.server2.authentication</name>
  <value>KERBEROS</value>
 </property>
 
 <!--  hiveserver2 kerberos主体 -->
 <property>
  <name>hive.server2.authentication.kerberos.principal</name>
  <value>hive/node1@EXAMPLE.COM</value>
 </property>
  
 <!-- hiveserver2 keytab密钥文件路径 -->
 <property>
  <name>hive.server2.authentication.kerberos.keytab</name>
  <value>/home/keytabs/hive.service.keytab</value>
 </property>
 
 <!-- hivemetastore 开启kerberos认证 -->
 <property>
  <name>hive.metastore.sasl.enabled</name>
  <value>true</value>
 </property>
 
 <!-- metastore kerberos主体 -->
 <property>
  <name>hive.metastore.kerberos.principal</name>
  <value>hive/node1@EXAMPLE.COM</value>
 </property>
 
 <!-- metastore keytab密钥文件路径 -->
 <property>
  <name>hive.metastore.kerberos.keytab.file</name>
  <value>/home/keytabs/hive.service.keytab</value>
 </property>

5、修改 Hadoop core-site.xml

【node1】中修改core-site.xml中相关代理配置为hive代理用户,【node1~node5】节点core-site.xml中修改如下配置项:

# 即/opt/server/hadoop-3.3.4/etc/hadoop
vim $HADOOP_HOME/etc/hadoop/core-site.xml

追加配置内容如下:

    <!-- 允许hive用户在任意主机节点代理任意用户和任意组 -->
    <property>
        <name>hadoop.proxyuser.hive.hosts</name>
        <value>*</value>
    </property>
    <property>
        <name>hadoop.proxyuser.hive.users</name>
        <value>*</value>
    </property>
    <property>   
        <name>hadoop.proxyuser.hive.groups</name>  
        <value>*</value> 
    </property>

以上配置【node1】执行分发到Hadoop各个集群节点后, 需要重新启动HDFS 。

# 分发配置文件到所有节点中
xsync $HADOOP_HOME/etc/hadoop/core-site.xml

6、准备core-site.xml 和 hdfs-site.xml

【node1】节点将hadoop的两个配置文件放置到对应hive目录下:

cp $HADOOP_HOME/etc/hadoop/core-site.xml $HIVE_HOME/conf/
cp $HADOOP_HOME/etc/hadoop/hdfs-site.xml $HIVE_HOME/conf/

【node1】节点进行分发文件到【node3】节点上:

cd $HIVE_HOME/conf/

# 分发到指定文件目录
scp core-site.xml hdfs-site.xml node3:`pwd`

接着我们重启HDFS。

# 关闭hadoop服务
stop-all.sh

# 启动hadoop服务
start-dfs.sh
start-yarn.sh

三、Hive Cli使用Kerberos

使用Hive Client操作Kerberos需要首先启动HDFS,然后在Hive服务端启动Hive Metastore,操作如下:

# 启动zookeeper及HDFS
[root@node3 ~]# zkServer.sh start
[root@node4 ~]# zkServer.sh start
[root@node5 ~]# zkServer.sh start
[root@node1 ~]# start-all.sh 

# 在Hive服务端node1节点启动Hive Metastore,这里可以切换成Hive用户,也可以不切换
[root@node1 ~]# su hive
[hive@node1 ~]$ hive --service metastore &

查看hive对应的报错日志也可以查看hadoop对应的日志:

cd /opt/server/hadoop-3.3.4/logs

# 查看日志
tail -f ./hadoop-hdfs-datanode-node3.log

在Hive客户端【node3】节点上登录hive客户端:

su hive

# 认证:123456
kinit hive/node1

#登录hive,建表、插入数据及查询
[hive@node3 ~]$ hive
hive> create table person (id int,name string,age int) row format delimited fields terminated by '\t';
OK
Time taken: 0.236 seconds
hive> insert into person values (1,'zs',18);
...
hive> select * from person;
OK
1	zs	18

#在node3节点准备如下文件及数据
[hive@node3 ~]$ vim /home/hive/person.txt 
2	ls	19
3	ww	20

#在hive客户端将以上文件数据加载到hive person表中,操作如下
hive> load data local inpath '/home/hive/person.txt' into table person;
hive> select * from person;
OK
1	zs	18
2	ls	19
3	ww	20

执行insert的时候,可以在hadoop的yarn上看到提交了任务:

image-20240707163344433

导入数据之后查询的结果如下:

image-20240707163609492


四、Hive beeline使用Kerberos

除了在hive客户端操作Hive外,还可以通过beeline方式操作Hive,具体步骤如下:

1、在 Hive 服务端启动 hiveserver2

【node1】节点启动:

hiveserver2

2、在 Hive 客户端执行 beeline 登录 hive

【node3】节点登录,注意除了这个hive/node1其他无法通过认证,会报错:

#在hive 客户端通过beeline登录hive
[hive@node3 ~]$ beeline 
beeline> !connect jdbc:hive2://node1:10000/default;principal=hive/node1@EXAMPLE.COM 

0: jdbc:hive2://node1:10000/default> select * from person;
+------------+--------------+-------------+
| person.id  | person.name  | person.age  |
+------------+--------------+-------------+
| 1          | zs           | 18          |
| 2          | ls           | 19          |
| 3          | ww           | 20          |
+------------+--------------+-------------+

#也可以通过以下方式通过beeline直接操作hive(一条命令执行)
[hive@node3 ~]$ beeline -u "jdbc:hive2://node1:10000/default;principal=hive/node1@EXAMPLE.COM"

注意:提前要使用hive/node1来进行认证kerberos之后执行,如6.3。

**额外说明:**无论使用哪种方式通过beeline连接hive,针对kerberos认证的hive都需要指定principal参数。


五、JDBC访问Kerberos认证Hive

在IDEA中使用JDBC方式读取Kerberos认证Hive时需要指定krb5.conf文件、Principal主体、keytab密钥文件,然后在代码中进行设置即可JDBC方式访问Kerberos认证的Hive。具体操作步骤如下:【可见5.4在服务器获取】

image-20240707165311703

1、准备 krb5.conf 及 keytab 文件

在node1 kerberos服务端将/etc/krb5.conf文件放在window固定路径中,同时将hive主体对应的keytab密钥文件放在windows固定路径中。

重新下载hive的指定keytab文件:

cd /home/keytabs

image-20240707164730047

对于krb5.conf以及hadoop的三个配置文件件5.4获取方式即可。

2、启动 HiveServer2

需要在Hive服务端启动HiveServer2服务:

#在Hive服务端node1节点执行如下命令
[root@node1 ~]# su hive
[hive@node1 root]$ hiveserver2

3、编写JDBC 访问 Hive 代码

添加hive依赖:

<dependency>
  <groupId>org.apache.hive</groupId>
  <artifactId>hive-jdbc</artifactId>
  <version>3.1.3</version>
</dependency>

编写代码:

package com.changlu.hive;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;

import java.io.IOException;
import java.sql.*;

/**
 * 通过JDBC方式读取Kerberos认证Hive的数据
 */
public class JDBCReadAuthHive {
    // Kerberos主体
    static final String principal = "hive/node1@EXAMPLE.COM";

    // Kerberos配置文件路径
    static final String krb5FilePath = "E:\\自学历程\\Gitee仓库\\demo-exer\\bigdata\\kerberos\\kerberosAuth\\kerberosAuth\\src\\main\\resources\\krb5.conf";

    // Keytab文件路径
    static final String keytabFilePath = "E:\\自学历程\\Gitee仓库\\demo-exer\\bigdata\\kerberos\\kerberosAuth\\kerberosAuth\\src\\main\\resources\\hive.service.keytab";

    public static void main(String[] args) throws SQLException, ClassNotFoundException, IOException {
        // 1.加载Kerberos配置文件
        System.setProperty("java.security.krb5.conf", krb5FilePath);
        // 2.设置Kerberos认证
        Configuration configuration = new Configuration();
        configuration.set("hadoop.security.authentication", "kerberos");
        UserGroupInformation.setConfiguration(configuration);
        UserGroupInformation.loginUserFromKeytab(principal, keytabFilePath);
        // 3.JDBC连接字符串
        String jdbcURL = "jdbc:hive2://node1:10000/default;principal=hive/node1@EXAMPLE.COM";
        Class.forName("org.apache.hive.jdbc.HiveDriver");
        try {
            // 4.创建Hive连接
            Connection connection = DriverManager.getConnection(jdbcURL, "", "");
            // 5.执行Hive查询
            Statement statement = connection.createStatement();
            ResultSet rs = statement.executeQuery("SELECT id,name,age FROM person");
            // 6.处理查询结果
            while (rs.next()) {
                System.out.println(rs.getInt(1) + "," +
                        rs.getString(2)+ "," +
                        rs.getInt(3)) ;
            }
            // 7.关闭连接
            rs.close();
            statement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}

image-20240707165245403


六、Spark访问Kerberos认证Hive

这里是通过SparkSQL来读取Kerberos认证Hive中的数据,按照如下步骤配置即可。

1、准备 krb5.conf 及 keytab 文件

在node1 kerberos服务端将/etc/krb5.conf文件放在window固定路径中,同时将hive主体对应的keytab密钥文件放在windows固定路径中。这里项目中已经有了,可以忽略。

2、准备访问 Hive 需要的资源文件

将HDFS中的core-site.xml 、hdfs-site.xml 、yarn-site.xml文件及Hive客户端配置hive-site.xml上传到项目resources资源目录中。

注意:这里额外传的有Hive客户端配置hive-site.xml文件。

cd $HIVE_HOME/conf

image-20240707170748621

3、准备 Maven 项目依赖

在IDEA项目中将hive-jdbc依赖进行注释,该包与SparkSQL读取Hive中的数据的包有冲突,向maven依赖中导入如下依赖包:

<!-- Spark-core -->
<dependency>
  <groupId>org.apache.spark</groupId>
  <artifactId>spark-core_2.12</artifactId>
  <version>3.4.0</version>
</dependency>
<!-- SparkSQL -->
<dependency>
  <groupId>org.apache.spark</groupId>
  <artifactId>spark-sql_2.12</artifactId>
  <version>3.4.0</version>
</dependency>
<!-- SparkSQL  ON  Hive-->
<dependency>
  <groupId>org.apache.spark</groupId>
  <artifactId>spark-hive_2.12</artifactId>
  <version>3.4.0</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>

4、编写 SparkSQL 读取 Hive 代码

package com.changlu.hive;

import org.apache.hadoop.security.UserGroupInformation;
import org.apache.spark.sql.SparkSession;

import java.io.IOException;

/**
 * Spark 读取Kerberos认证Hive的数据
 */
public class SparkReadAuthHive {
    public static void main(String[] args) throws IOException {
        //进行kerberos认证
        System.setProperty("java.security.krb5.conf", "E:\\自学历程\\Gitee仓库\\demo-exer\\bigdata\\kerberos\\kerberosAuth\\kerberosAuth\\src\\main\\resources\\krb5.conf");
        String principal = "hive/node1@EXAMPLE.COM";
        String keytabPath = "E:\\自学历程\\Gitee仓库\\demo-exer\\bigdata\\kerberos\\kerberosAuth\\kerberosAuth\\src\\main\\resources\\hive.service.keytab";
        UserGroupInformation.loginUserFromKeytab(principal, keytabPath);
        //spark进行hive配置,注意hive很多配置服务地址信息在hive-site.xml配置,所以这个配置需要传上来
        SparkSession spark = SparkSession.builder().appName("SparkReadAuthHive")
                .master("local")
//                .config("hive.metastore.uris", "thrift://node1:9083")
                .enableHiveSupport()
                .getOrCreate();
        spark.sql("select * from person").show();
        spark.stop();

    }
}

以上代码编写完成后执行可以查询hive表中对应的数据。

image-20240707171111979


七、Flink访问Kerberos认证Hive

Flink读取Kerberos认证Hive也需要进行认证,这里以FlinkSQL读取Hive中数据为例来演示,步骤如下。

1、准备krb5.conf 及 keytab 文件

在node1 kerberos服务端将/etc/krb5.conf文件放在window固定路径中,同时将hive主体对应的keytab密钥文件放在windows固定路径中。 这里项目中已经有了,可以忽略

2、准备访问 Hive 需要的资源文件【可见6.6】

将HDFS中的core-site.xml 、hdfs-site.xml 、yarn-site.xml文件及Hive客户端配置hive-site.xml上传到项目resources资源目录中。 这里项目中已经有了,可以忽略。

3、准备 Maven 项目依赖

在IDEA项目中引入如下Flink依赖包:

<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-clients</artifactId>
    <version>1.16.0</version>
</dependency>
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-table-common</artifactId>
    <version>1.16.0</version>
</dependency>
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-table-api-java</artifactId>
    <version>1.16.0</version>
</dependency>
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-table-planner_2.12</artifactId>
    <version>1.16.0</version>
</dependency>
<!-- Flink Dependency -->
<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-connector-hive_2.12</artifactId>
    <version>1.16.0</version>
</dependency>

<dependency>
    <groupId>org.apache.flink</groupId>
    <artifactId>flink-table-api-java-bridge</artifactId>
    <version>1.16.0</version>
</dependency>

<!-- Hive Dependency -->
<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-exec</artifactId>
    <version>3.1.3</version>
</dependency>

注意:Spark操作Hive依赖与Flink操作Hive依赖也有冲突,这里由于把代码放在一个项目中,所以执行Spark或者Flink代码时把对方依赖注释掉即可。

4、编写 FlinkSQL 读取 Hive 代码

/**
 * Spark 读取Kerberos认证Hive的数据
 */
public class SparkReadAuthHive {
    public static void main(String[] args) throws IOException {
        //进行kerberos认证
        System.setProperty("java.security.krb5.conf", "D:\\idea_space\\KerberosAuth\\KerberosAuthHDFS\\src\\main\\resources\\krb5.conf");
        String principal = "hive/node1@EXAMPLE.COM";
        String keytabPath = "D:\\idea_space\\KerberosAuth\\KerberosAuthHive\\src\\main\\resources\\hive.service.keytab";
        UserGroupInformation.loginUserFromKeytab(principal, keytabPath);

        SparkSession spark = SparkSession.builder().appName("SparkReadAuthHive")
                .master("local")
//                .config("hive.metastore.uris", "thrift://node1:9083")
                .enableHiveSupport()
                .getOrCreate();
        spark.sql("select * from person").show();
        spark.stop();
  
    }
}

执行若是出现报错:Make sure you have set a valid value for hive.metastore.uris

解决方案:确保在idea中的hive-site.xml中包含有对应的配置项,可见一开始环境搭建时候hive客户端的配置文件,当前IDEA中的补充如下

<property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/opt/server/hive-3.1.3/warehouse</value>
</property>
<property>
    <name>hive.metastore.local</name>
    <value>false</value>
</property>
<property>
    <name>hive.metastore.uris</name>
    <value>thrift://node1:9083</value>
</property>

此时我们再次执行:

image-20240707173408412

评论区请在客户端页面查看