如何在 Amazon EMR 上的 Hive 和 Amazon RDS MySQL 上的元存储之间设置 SSL 连接?

上次更新时间:2020 年 9 月 4 日

我想在 Apache Hive 和 Amazon Relational Database Service (Amazon RDS) MySQL 数据库实例上的元存储之间设置 SSL 连接。该如何操作?

简短描述

使用 SSL 证书在 Hive 和外部元存储之间设置加密连接。您可以在启动新的 Amazon EMR 集群时或集群运行后设置此连接。

解决方法

注意:以下步骤已通过 Amazon EMR 5.18.0 版本和 Amazon RDS MySQL 5.7 版本测试。

在新的 Amazon EMR 集群上设置 SSL 连接

1.     运行类似于以下内容的命令,以创建 Amazon RDS MySQL 数据库实例:将 $RDS_MASTER_USER_NAME$RDS_MASTER_PASSWORD 替换为您的用户名和密码。有关更多信息,请参阅 create-db-instance

注意:如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请确保您使用的是最新的 CLI 版本。

aws rds create-db-instance --db-name hive --db-instance-identifier mysql-hive-meta --db-instance-class db.t2.micro\ 
    --engine mysql --engine-version 5.7.19 --master-username $RDS_MASTER_USER_NAME --master-user-password $RDS_MASTER_PASSWORD\
    --allocated-storage 20 --storage-type gp2 --vpc-security-group-ids $RDS_VPC_SG --publicly-accessible

2.     以主用户身份连接到 Amazon RDS MySQL 数据库实例。然后,为 Hive 元存储创建用户,如以下示例所示。

重要提示:确保将此用户的访问权限限制为在第 1 步中创建的数据库实例。

mysql -h mysql-hive-meta.########.us-east-1.rds.amazonaws.com -P 3306 -u $RDS_MASTER_USER_NAME -p
Enter password: $RDS_MASTER_PASSWORD

CREATE USER 'hive_user'@'%' IDENTIFIED BY 'hive_user_password';
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'hive_user'@'%';
GRANT ALL PRIVILEGES ON hive.* TO 'hive_user'@'%' REQUIRE SSL;
FLUSH PRIVILEGES;

3.     创建类似于以下内容的 JSON 配置文件。将 hive_user 和 hive_user_password 替换为第 2 步中在 JSON 脚本内使用的值。将 JDBC URL 中的终端节点替换为 RDS 数据库实例的终端节点。

您将使用此文件在下一步中启动 Amazon EMR 集群。该文件启用与 RDS 数据库实例的 SSL 连接。有关更多信息,请参阅将 SSL 与 MySQL 数据库实例结合使用

[
    {
        "Classification": "hive-site",
        "Properties": {
            "javax.jdo.option.ConnectionURL": "jdbc:mysql:\/\/mysql-hive-meta.########.us-east-1.rds.amazonaws.com:3306\/hive?createDatabaseIfNotExist=true&useSSL=true&serverSslCert=\/home\/hadoop\/rds-combined-ca-bundle.pem",
            "javax.jdo.option.ConnectionDriverName": "org.mariadb.jdbc.Driver",
            "javax.jdo.option.ConnectionUserName": "hive_user",
            "javax.jdo.option.ConnectionPassword": "hive_user_password"
        }
    }
]

4.     在与 Amazon RDS MySQL 实例关联的安全组中,使用以下参数创建入站规则
对于类型,选择 MYSQL/Aurora (3306)
对于协议,默认情况下选择 TCP (6)
对于端口范围,默认情况下选择 3306
对于,输入与主节点关联的 Amazon EMR 托管安全组的组 ID

此规则允许 Amazon EMR 集群的主节点访问 Amazon RDS 实例。有关更多信息,请参阅 VPC 安全组

5.     运行 create-cluster 命令,使用第 3 步中的 JSON 文件启动 Amazon EMR 集群,并执行引导操作,将 SSL 证书下载到主节点上的 /home/hadoop/。示例:

aws emr create-cluster --applications Name=Hadoop Name=Hive --tags Name="EMR Hive Metastore"\
    --ec2-attributes KeyName=$EC2_KEY_PAIR,InstanceProfile=EMR_EC2_DefaultRole,SubnetId=$EMR_SUBNET,EmrManagedSlaveSecurityGroup=$EMR_CORE_AND_TASK_VPC_SG,EmrManagedMasterSecurityGroup=$EMR_MASTER_VPC_SG\
   
    --service-role EMR_DefaultRole --release-label emr-5.18.0 --log-uri s3://awsdoc-example-bucket/emr-logs-path/ --name "Hive External Metastore RDS MySQL w/ SSL"\
    --instance-groups InstanceGroupType=MASTER,InstanceCount=1,InstanceType=m3.xlarge,Name="Master
    - 1"\ 
    --configurations file://hive-ext-meta-mysql-ssl.json\
    --bootstrap-actions Path=s3://elasticmapreduce/bootstrap-actions/run-if,Args=["instance.isMaster=true","cd /home/hadoop && wget -S -T
    10 -t 5 https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem"]

6.     使用 SSH 连接到主节点

7.     打开主节点上的 hive 会话。然后,创建表。可以是任意表,仅用于测试目的。示例:

hive> create table tb_test (col1 STRING, col2 BIGINT);
OK
Time taken: 2.371 seconds

hive> describe tb_test;
OK
col1                    string
col2                    bigint
Time taken: 0.254 seconds, Fetched: 2 row(s)

8.     使用主节点上的 mysql 客户端连接到 RDS MySQL 元存储。然后,验证元存储中的表元数据。如果元数据与您在上一步中创建的表相对应,则表示 SSL 连接工作正常。示例:

mysql -h mysql-hive-meta.########.us-east-1.rds.amazonaws.com -P 3306 -u $RDS_MASTER_USER_NAME -p
Enter password: $RDS_MASTER_PASSWORD

mysql> use hive;
Database changed

mysql> select t1.OWNER, t1.TBL_NAME, t1.TBL_TYPE, s1.INPUT_FORMAT, s1.OUTPUT_FORMAT, s1.LOCATION from TBLS t1 inner join SDS s1 on s1.SD_ID = t1.SD_ID where t1.TBL_NAME = 'tb_test'\G
*************************** 1. row ***************************
        OWNER: hadoop
     TBL_NAME: tb_test
     TBL_TYPE: MANAGED_TABLE
 INPUT_FORMAT: org.apache.hadoop.mapred.TextInputFormat
OUTPUT_FORMAT: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
     LOCATION: hdfs://ip-xxx-xx-xx-xxx.ec2.internal:8020/user/hive/warehouse/tb_test
1 row in set (0.23 sec)

mysql> select t1.OWNER, t1.TBL_NAME, c1.COLUMN_NAME, c1.TYPE_NAME from TBLS t1 inner join SDS s1 on s1.SD_ID = t1.SD_ID inner join COLUMNS_V2 c1 on c1.CD_ID = s1.CD_ID where t1.TBL_NAME = 'tb_test';
+--------+----------+-------------+-----------+
| OWNER  | TBL_NAME | COLUMN_NAME | TYPE_NAME |
+--------+----------+-------------+-----------+
| hadoop | tb_test  | col1        | string    |
| hadoop | tb_test  | col2        | bigint    |
+--------+----------+-------------+-----------+
2 rows in set (0.22 sec)

在运行的 Amazon EMR 集群上设置 SSL 连接

注意:以下步骤假定您有一个 Amazon RDS MySQL 数据库实例。

1.     使用 SSH 连接到主节点

2.     运行以下命令将 SSL 证书下载到主节点上的 /home/hadoop/

cd /home/hadoop && wget -S -T 10 -t 5 https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem

3.     在 /etc/hive/conf.dist 目录下,在 hive-site.xml 文件中添加或编辑以下行。这将启用与 RDS 数据库实例的 SSL 连接。在以下示例中,将 JDBC URL 中的终端节点替换为 RDS 数据库实例的终端节点。

<property>
  <name>javax.jdo.option.ConnectionURL</name>
  <value>jdbc:mysql://mysql-hive-meta.########.us-east-1.rds.amazonaws.com:3306/hive?createDatabaseIfNotExist=true&amp;useSSL=true&amp;serverSslCert=/home/hadoop/rds-combined-ca-bundle.pem</value>
  <description>JDBC URL for the metastore database</description>
</property>

<property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>hive_user</value>
    <description>User name for the metastore database</description>
</property>

<property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>HIVE_USER_PASSWORD</value>
    <description>Password for metastore database</description>
</property>

重要提示:和号 (&) 是 XML 中的特殊字符。要在 hive-site.xml 中使用和号(例如在 JDBC 字符串中),必须使用“&amp;”而不是“&”。 否则,当您重新启动 hive-hcatalog-server 时会出现错误。

4.     运行类似以下内容的命令来测试 SSL 连接。

mysql -h mysql-hive-meta.########.us-east-1.rds.amazonaws.com -P 3306 -u hive_user -p --ssl-ca ./rds-combined-ca-bundle.pem

5.     重新启动主节点上的 hive-server2hive-hcatalog-server。有关更多信息,请参阅重新启动进程

6.     在 /var/log/ 目录中,验证服务是否已成功重新启动。日志的条目应如下所示:

sudo stop hive-server2
sudo stop hive-hcatalog-server
sudo start hive-hcatalog-server
sudo start hive-server2

7.     打开主节点上的 hive 会话。然后,创建表。 可以是任意表,仅用于测试目的。示例:

hive> create table tb_test (col1 STRING, col2 BIGINT);
OK
Time taken: 2.371 seconds

hive> describe tb_test;
OK
col1                    string
col2                    bigint
Time taken: 0.254 seconds, Fetched: 2 row(s)

8.     使用主节点上的 mysql 客户端连接到 RDS MySQL 元存储。然后,验证元存储中的表元数据。如果元数据与您在上一步中创建的表相对应,则表示 SSL 连接工作正常。示例:

$ mysql -h mysql-hive-meta.########.us-east-1.rds.amazonaws.com -P 3306 -u $RDS_MASTER_USER_NAME -p
Enter password: $RDS_MASTER_PASSWORD

mysql> use hive;
Database changed

mysql> select t1.OWNER, t1.TBL_NAME, t1.TBL_TYPE, s1.INPUT_FORMAT, s1.OUTPUT_FORMAT, s1.LOCATION from TBLS t1 inner join SDS s1 on s1.SD_ID = t1.SD_ID where t1.TBL_NAME = 'tb_test'\G
*************************** 1. row ***************************
        OWNER: hadoop
     TBL_NAME: tb_test
     TBL_TYPE: MANAGED_TABLE
 INPUT_FORMAT: org.apache.hadoop.mapred.TextInputFormat
OUTPUT_FORMAT: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
     LOCATION: hdfs://ip-xxx-xx-xx-xxx.ec2.internal:8020/user/hive/warehouse/tb_test
1 row in set (0.23 sec)

mysql> select t1.OWNER, t1.TBL_NAME, c1.COLUMN_NAME, c1.TYPE_NAME from TBLS t1 inner join SDS s1 on s1.SD_ID = t1.SD_ID inner join COLUMNS_V2 c1 on c1.CD_ID = s1.CD_ID where t1.TBL_NAME = 'tb_test';
+--------+----------+-------------+-----------+
| OWNER  | TBL_NAME | COLUMN_NAME | TYPE_NAME |
+--------+----------+-------------+-----------+
| hadoop | tb_test  | col1        | string    |
| hadoop | tb_test  | col2        | bigint    |
+--------+----------+-------------+-----------+
2 rows in set (0.22 sec)

排除 hive-hcatalog-server 重新启动错误

当您尝试重新启动 hive-hcatalog-server 时,可能会收到类似于以下内容的错误消息。当 RDS MySQL 数据库实例作为安全预防措施来阻止 EMR 集群的主节点时,通常会发生这种情况。

2020-08-20T14:18:50,750 WARN [main] org.apache.hadoop.hive.metastore.HiveMetaStore - Retrying creating default database after error: Unable to open a test connection to the given database. JDBC url = jdbc:mysql://mariadb-hive-meta.ch1nkjp4jjbq.eu-west-1.rds.amazonaws.com:3306/hive?createDatabaseIfNotExist=true&useSSL=true&serverSSlCert=/home/hadoop/rds-combined-ca-bundle.pem, username = masteruser. Terminating connection pool (set lazyInit to true if you expect to start your database after your app). Original Exception: ------
java.sql.SQLException: Host '172.31.41.187' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'

要解决此错误,请连接到安装了 mysqladmin 工具的其他本地计算机或 Amazon Elastic Compute Cloud (Amazon EC2) 实例。运行以下命令从数据库实例刷新主节点。

mysqladmin -h mysql-hive-meta.########.us-east-1.rds.amazonaws.com -P 3306 -u $RDS_MASTER_USER_NAME -p flush-hosts
Enter password: $RDS_MASTER_PASSWORD

您现在应该能够成功重新启动 hive-hcatalog-server


这篇文章对您有帮助吗?


您是否需要账单或技术支持?