在安全 Hadoop 上
本页面介绍如何在 Kerberos 启用的安全 Hadoop 集群上使用 MySQL 数据库作为 Metastore 来操作 Hive on MR3(完成前置步骤后)。按照以下说明,用户将学习:
- 如何在 Kerberos 启用的安全 Hadoop 集群中配置 Hive on MR3
- 如何启动和停止 Metastore
- 如何启动和停止 HiveServer2
- 如何创建 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