跳到主要内容

在安全 Hadoop 上

本页面介绍如何在 Kerberos 启用的安全 Hadoop 集群上使用 MySQL 数据库作为 Metastore 来操作 Hive on MR3(完成前置步骤后)。按照以下说明,用户将学习:

  1. 如何在 Kerberos 启用的安全 Hadoop 集群中配置 Hive on MR3
  2. 如何启动和停止 Metastore
  3. 如何启动和停止 HiveServer2
  4. 如何创建 Beeline 连接并向 HiveServer2 发送查询

本场景有三个额外的先决条件:

  • 一个 Kerberos 启用的安全 Hadoop 集群可用。
  • 用户拥有用于保护 Metastore 和 HiveServer2 的服务密钥表文件。
  • 用户拥有用于续订 HDFS 令牌密钥表文件。

检查密钥表文件

在我们的示例中,我们将作为用户 hive 运行 Metastore 和 HiveServer2。我们假设管理员已创建服务密钥表文件 hive.service.keytab 并放置在目录 /etc/security/keytabs 中。

以用户 hive 身份登录。检查与服务密钥表文件关联的服务主体。在我们的示例中,我们使用服务主体 hive/navy0@NAVY,其中 NAVY 是 Kerberos 领域。请注意,服务密钥表文件的权限为 600,仅对用户 hive 可访问。

ls -alt /etc/security/keytabs/hive.service.keytab
-rw------- 1 hive hadoop 672 Jan 26 2025 /etc/security/keytabs/hive.service.keytab
klist -kt /etc/security/keytabs/hive.service.keytab
Keytab name: FILE:/etc/security/keytabs/hive.service.keytab
KVNO Timestamp Principal
---- ------------------- -------------------------------------------------------
2 01/26/2025 14:19:51 hive@NAVY
...
2 01/26/2025 14:19:51 hive/navy0@NAVY...

从服务密钥表文件获取 Kerberos 票据。

kinit -k -t /etc/security/keytabs/hive.service.keytab hive/navy0@NAVY
klist
Ticket cache: FILE:/tmp/krb5cc_1005
Default principal: hive/navy0@NAVY
Valid starting Expires Service principal
03/08/2025 00:14:13 03/09/2025 00:14:13 krbtgt/NAVY@NAVY

我们还假设已为用户 hive 创建了用户密钥表文件 hive.keytab 并放置在主目录中。如果不存在,以用户 root 身份登录并按如下方式创建新文件。首先运行 kadmin.local 并创建新主体 hive@NAVY

kadmin.local
Authenticating as principal root/admin@NAVY with password.
kadmin.local: addprinc hive@NAVY
WARNING: no policy specified for hive@NAVY; defaulting to no policy
Enter password for principal "hive@NAVY":
Re-enter password for principal "hive@NAVY":
add_principal: Principal or policy already exists while creating "hive@NAVY".

为用户 hive 创建密钥表文件 hive.keytab

kadmin.local: xst -k hive.keytab hive
Entry for principal hive with kvno 4, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:hive.keytab.
Entry for principal hive with kvno 4, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:hive.keytab.
Entry for principal hive with kvno 4, encryption type des3-cbc-sha1 added to keytab WRFILE:hive.keytab.
Entry for principal hive with kvno 4, encryption type arcfour-hmac added to keytab WRFILE:hive.keytab.
Entry for principal hive with kvno 4, encryption type des-hmac-sha1 added to keytab WRFILE:hive.keytab.
Entry for principal hive with kvno 4, encryption type des-cbc-md5 added to keytab WRFILE:hive.keytab.

检查与密钥表文件关联的主体。

klist -k -t hive.keytab
Keytab name: FILE:hive.keytab
KVNO Timestamp Principal
---- ------------------- -------------------------------------------------------
4 03/08/2025 03:32:48 hive@NAVY...

将密钥表文件复制到主目录。

cp hive.keytab /home/hive/
chown hive /home/hive/hive.keytab
chmod 600 /home/hive/hive.keytab

配置 Metastore

在我们的示例中,我们假设 MySQL 用户 hivemr3(在节点 navy0 上)可以访问具有所有权限的 MySQL 服务器。稍后我们将配置 Metastore,以便使用用户名 hivemr3 连接到 MySQL 服务器。MySQL 服务器可以在任意节点上运行,不一定是 Metastore 或 HiveServer2 将运行的节点。在我们的示例中,它运行在同一节点上。

mysql -h navy0 -u hivemr3 -p
...
mysql> SHOW GRANTS FOR 'hivemr3'@'navy0';
+--------------------------------------------------+
| Grants for hivemr3@navy0 |
+--------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'hivemr3'@'navy0' |
+--------------------------------------------------+
1 row in set (0.00 sec)

打开 env.sh 并设置以下环境变量。

vi env.sh
HIVE_METASTORE_DB_TYPE=mysql
HIVE_DATABASE_HOST=$HOSTNAME
HIVE_DATABASE_NAME=hivemr3
HIVE_MYSQL_DRIVER=/usr/share/java/mysql-connector-java-8.0.12.jar
  • HIVE_METASTORE_DB_TYPE 应设置为 mysql
  • HIVE_DATABASE_HOST 指定运行 MySQL 服务器的节点。
  • HIVE_DATABASE_NAME 指定在 MySQL 中为 Metastore 创建的新数据库的名称。在我们的示例中,我们使用 hivemr3
  • HIVE_MYSQL_DRIVER 应指向 MySQL 连接器 jar 文件。

由于我们使用 --tpcds 选项,打开 conf/tpcds/hive-site.xml 并更新以下配置键。将 javax.jdo.option.ConnectionUserName 设置为 MySQL 用户名,将 javax.jdo.option.ConnectionPassword 设置为密码。

vi conf/tpcds/hive-site.xml
<property>
<name>hive.metastore.db.type</name>
<value>MYSQL</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://${hive.database.host}/${hive.database.name}?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hivemr3</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>password</value>
</property>

配置安全

打开 env.sh,将 SECURE_MODE 设置为 true,将 HIVE_SERVER2_AUTHENTICATION 设置为 KERBEROS 以启用安全。设置以下三个 Kerberos 主体及其对应的密钥表文件。

  • HIVE_METASTORE_KERBEROS_PRINCIPAL 指定 Metastore 的服务主体。
  • HIVE_SERVER2_KERBEROS_PRINCIPAL 指定 HiveServer2 的服务主体。
  • USER_PRINCIPAL 指定用于续订 HDFS 令牌的主体。

在我们的示例中,我们使用 hive.service.keytab 作为 Metastore 和 HiveServer2,使用 hive.keytab 作为续订 HDFS 令牌。为了自动续订 HDFS 令牌,将 TOKEN_RENEWAL_HDFS_ENABLED 设置为 true。

vi env.sh
SECURE_MODE=true
HIVE_METASTORE_KERBEROS_PRINCIPAL=hive/_HOST@NAVY
HIVE_METASTORE_KERBEROS_KEYTAB=/etc/security/keytabs/hive.service.keytab
HIVE_SERVER2_AUTHENTICATION=KERBEROS
HIVE_SERVER2_KERBEROS_PRINCIPAL=hive/_HOST@NAVY
HIVE_SERVER2_KERBEROS_KEYTAB=/etc/security/keytabs/hive.service.keytab
USER_PRINCIPAL=hive@NAVY
USER_KEYTAB=/home/hive/hive.keytab
TOKEN_RENEWAL_HDFS_ENABLED=true

启动 Metastore

使用 --tpcds 选项运行 Metastore,并使用 --init-schema 选项初始化数据库模式。

hive/metastore-service.sh start --tpcds --init-schema

用户首次运行 Metastore 时应使用 --init-schema 初始化数据库模式。没有 --init-schema,脚本会失败并显示以下错误消息。

MetaException(message:Version information not found in metastore.)

重启 Metastore 时,不要使用 --init-schema 选项,以便重用现有的 Hive 数据库。例如,用户可以终止 Metastore 并重新启动它,如下所示。

hive/metastore-service.sh stop --tpcds
hive/metastore-service.sh start --tpcds

启动 HiveServer2

使用 --tpcds 选项运行 HiveServer2。不要对 MR3 DAGAppMaster 使用 LocalProcess 模式(带 --amprocess 选项),安全 Hadoop 集群不支持该模式。

hive/hiveserver2-service.sh start --tpcds

创建一个新目录 hive/run-beeline-result 并将其权限设置为 777,以便任何用户都可以从当前工作目录执行 Beeline。

mkdir -p hive/run-beeline-result
chmod 777 hive/run-beeline-result

下载将被另一用户访问的示例数据集。

wget https://github.com/mr3project/mr3/releases/download/v2.0/pokemon.csv

运行 Beeline

用户可以使用任意客户端程序(不一定是 MR3 release 中包含的 Beeline)连接到 HiveServer2。在我们的示例中,我们运行 MR3 release 中包含的 Beeline。

我们以另一用户 gla 的身份运行 Beeline,以向 HiveServer2 发送查询。以用户 gla 身份登录并更改工作目录。

cd /home/hive/mr3/hadoop

确保用户 gla 无法读取密钥表文件。

cat /etc/security/keytabs/hive.service.keytab
cat: /etc/security/keytabs/hive.service.keytab: Permission denied
cat /home/hive/hive.keytab
cat: /home/hive/hive.keytab: Permission denied

为用户 gla 获取 Kerberos 票据(通过执行 kinit 或读取 Kerberos 密钥表文件)。

klist
Ticket cache: FILE:/tmp/krb5cc_1001
Default principal: gla@NAVY
Valid starting Expires Service principal
03/09/2025 02:43:51 03/10/2025 02:43:51 krbtgt/NAVY@NAVY

用户可以使用任意客户端程序连接到 HiveServer2。在我们的示例中,我们运行 MR3 release 中包含的 Beeline。

运行 Beeline。

hive/run-beeline.sh

使用默认数据库。

0: jdbc:hive2://navy0:9842/> use default;

创建一个名为 pokemon 的表。

0: jdbc:hive2://navy0:9842/> CREATE TABLE pokemon (Number Int,Name String,Type1 String,Type2 String,Total Int,HP Int,Attack Int,Defense Int,Sp_Atk Int,Sp_Def Int,Speed Int) row format delimited fields terminated BY ',' lines terminated BY '\n' tblproperties("skip.header.line.count"="1");

导入示例数据集。

0: jdbc:hive2://navy0:9842/> load data local inpath './pokemon.csv' INTO table pokemon;

执行查询。

0: jdbc:hive2://navy0:9842/> select avg(HP) from pokemon;
0: jdbc:hive2://navy0:9842/> create table pokemon1 as select *, IF(HP>160.0,'strong',IF(HP>140.0,'moderate','weak')) AS power_rate from pokemon;
0: jdbc:hive2://navy0:9842/> select COUNT(name), power_rate from pokemon1 group by power_rate;

退出 Beeline。HDFS 上的仓库目录现在有两个子目录,对应上面创建的两个 Hive 表。请注意,子目录由用户 hive 拥有,而不是用户 gla,因为模拟被禁用。

hdfs dfs -ls /user/hive/warehouse
Found 2 items
drwxr-xr-x - hive hdfs 0 2025-03-09 03:29 /user/hive/warehouse/pokemon
drwxr-xr-x - hive hadoop 0 2025-03-09 03:30 /user/hive/warehouse/pokemon1

停止 HiveServer2 和 Metastore

以用户 hive 身份停止 HiveServer2。

hive/hiveserver2-service.sh stop --tpcds

以用户 hive 身份停止 Metastore。

hive/metastore-service.sh stop --tpcds