访问Kerberos化的Hadoop集群

使用外部表和gphdfs协议,Greenplum数据库可以从Hadoop文件系统(HDFS)读取文件或者向HDFS写入文件。为了最好的性能,Greenplum的Segment会并行读写HDFS的文件。

当Hadoop集群受Kerberos(“Kerberized”)保护时,Greenplum数据库必须被配置为允许Greenplum数据库的gpadmin角色(它拥有HDFS中的外部表)通过Kerberos认证。这个主题提供了配置Greenplum数据库与Kerberos化的HDFS协作的步骤,包括配置的验证和故障排查。

上级主题: 最佳实践

先决条件

确认下列组件正常工作并且在网络上可访问:

  • Greenplum数据库集群——要么是Pivotal的Greenplum数据库软件,要么是Dell EMC Data Computing Appliance (DCA)。
  • Kerberos保护的Hadoop集群。支持的Hadoop版本请见Greenplum数据库发行注记
  • Kerberos密钥发行中心(KDC)服务器。

配置Greenplum集群

Greenplum集群中的主机必须安装有Java JRE、Hadoop客户端文件以及Kerberos客户端。

按下列步骤准备Greenplum集群。

  1. 在所有的Greenplum集群主机上安装Java 1.6或者之后的JRE。

    要匹配Hadoop集群运行的JRE版本。用户可以在Hadoop节点上通过运行java —version来找到JRE版本。

  2. (可选)确认Java加密扩展(JCE)存在。

    JCE库的默认位置是JAVA_HOME/lib/security。如果安装了JDK,该目录是JAVA_HOME/jre/lib/security。文件local_policy.jar以及US_export_policy.jar应该出现在JCE目录中。

    Greenplum集群和Kerberos服务器最好应该使用相同版本的JCE库。如果需要,用户可以从Kerberos服务器把JCE文件拷贝到Greenplum集群。

  3. 为gpadmin账户在.bashrc或.bash_profile文件中将JAVA_HOME环境变量设置为JRE的位置。例如:

    1. export JAVA_HOME=/usr/java/default
  4. 引入.bashrc或.bash_profile文件将改动应用到用户的环境。例如:

    1. $ source ~/.bashrc
  5. 在所有集群主机上安装Kerberos客户端工具。在安装它们之前,确保共享库匹配KDC服务器上的版本。

    例如,下面的命令在Red Hat或者CentOS Linux上安装Kerberos客户端文件:

    1. $ sudo yum install krb5-libs krb5-workstation

    使用kinit命令确认Kerberos客户端被安装并且正确地配置。

  6. 在Greenplum集群中的所有主机上安装Hadoop客户端文件。其指令请参考所使用的Hadoop的文档。

  7. 为Hadoop设置Greenplum数据库的服务器配置参数。gp_hadoop_target_version参数指定Hadoop集群的版本。与所使用的Hadoop相对应的目标版本值请见Greenplum数据库发行注记。gp_hadoop_home参数指定Hadoop安装目录。

    1. $ gpconfig -c gp_hadoop_target_version -v "hdp2"
    2. $ gpconfig -c gp_hadoop_home -v "/usr/lib/hadoop"

    更多信息请见Greenplum数据库参考指南

  8. 为Master和Segment重载更新后的postgresql.conf文件:

    1. gpstop -u

    用户可以用下面的命令确认更改:

    1. $ gpconfig -s gp_hadoop_target_version
    2. $ gpconfig -s gp_hadoop_home
  9. 为拥有HDFS中外部表的角色授予Greenplum数据库的gphdfs协议特权,这些角色包括gpadmin和其他超级用户角色。授予SELECT特权会让角色能够创建HDFS中的可读外部表。授予INSERT特权会让角色能够创建HDFS中的可写外部表。

    1. #= GRANT SELECT ON PROTOCOL gphdfs TO gpadmin;
    2. #= GRANT INSERT ON PROTOCOL gphdfs TO gpadmin;
  10. 为外部表拥有者角色授予Greenplum数据库的外部表特权:

    1. ALTER ROLE HDFS_USER CREATEEXTTABLE (type='readable');
    2. ALTER ROLE HDFS_USER CREATEEXTTABLE (type='writable');

    注意: 一种最佳实践是,至少每年都重新审查数据库特权,包括gphdfs外部表特权。

创建并安装Keytab文件

  1. 作为root登入KDC服务器。
  2. 使用kadmin.local命令为gpadmin用户创建一个新的主体:

    1. # kadmin.local -q "addprinc -randkey gpadmin@LOCAL.DOMAIN"
  3. 使用kadmin.local为Greenplum数据库集群中的每一台主机产生一个Kerberos服务主体。服务主体应该是下列形式之一name/role@REALM,其中

    • name是gphdfs服务的用户名。这个例子使用了gphdfs。
    • role是一台Greenplum集群主机的DNS可解析的主机名(hostname -f命令的输出)。
    • REALM是Kerberos的realm,例如LOCAL.DOMAIN。

    例如,下面的命令为四台Greenplum数据库主机mdw.example.com、smdw.example.com、sdw1.example.com以及sdw2.example.com增加服务主体:

    1. # kadmin.local -q "addprinc -randkey gphdfs/mdw.example.com@LOCAL.DOMAIN"
    2. # kadmin.local -q "addprinc -randkey gphdfs/smdw.example.com@LOCAL.DOMAIN"
    3. # kadmin.local -q "addprinc -randkey gphdfs/sdw1.example.com@LOCAL.DOMAIN"
    4. # kadmin.local -q "addprinc -randkey gphdfs/sdw2.example.com@LOCAL.DOMAIN"

    为每一台Greenplum集群主机创建一个主体。使用相同的主体名称和realm,为每台主机替换完全限定的域名。

  4. 为刚创建的每一个主体(gpadmin和每一个gphdfs主体)生成一个keytab文件。用户可以在任意方便的位置存放keytab文件(这个例子使用了目录/etc/security/keytabs)。在后面的步骤中,用户将把服务主体的keytab文件部署到它们相应的Greenplum主机上:

    1. # kadmin.local -q “xst -k /etc/security/keytabs/gphdfs.service.keytab gpadmin@LOCAL.DOMAIN”
    2. # kadmin.local -q “xst -k /etc/security/keytabs/mdw.service.keytab gpadmin/mdw gphdfs/mdw.example.com@LOCAL.DOMAIN”
    3. # kadmin.local -q “xst -k /etc/security/keytabs/smdw.service.keytab gpadmin/smdw gphdfs/smdw.example.com@LOCAL.DOMAIN”
    4. # kadmin.local -q “xst -k /etc/security/keytabs/sdw1.service.keytab gpadmin/sdw1 gphdfs/sdw1.example.com@LOCAL.DOMAIN”
    5. # kadmin.local -q “xst -k /etc/security/keytabs/sdw2.service.keytab gpadmin/sdw2 gphdfs/sdw2.example.com@LOCAL.DOMAIN”
    6. # kadmin.local -q “listprincs”
  5. 按下面的方式更改gphdfs.service.keytab上的拥有关系和权限:

    1. # chown gpadmin:gpadmin /etc/security/keytabs/gphdfs.service.keytab
    2. # chmod 440 /etc/security/keytabs/gphdfs.service.keytab
  6. 为gpadmin@LOCAL.DOMAIN把keytab文件拷贝到Greenplum的Master主机:

    1. # scp /etc/security/keytabs/gphdfs.service.keytab mdw_fqdn:/home/gpadmin/gphdfs.service.keytab
  7. 为每一个服务主体将keytab文件拷贝到相应的Greenplum主机:

    1. # scp /etc/security/keytabs/mdw.service.keytab mdw_fqdn:/home/gpadmin/mdw.service.keytab
    2. # scp /etc/security/keytabs/smdw.service.keytab smdw_fqdn:/home/gpadmin/smdw.service.keytab
    3. # scp /etc/security/keytabs/sdw1.service.keytab sdw1_fqdn:/home/gpadmin/sdw1.service.keytab
    4. # scp /etc/security/keytabs/sdw2.service.keytab sdw2_fqdn:/home/gpadmin/sdw2.service.keytab

为Kerberos配置gphdfs

  1. 在所有Greenplum集群主机上编辑Hadoop的core-site.xml客户端配置文件。通过把hadoop.security.authorization属性设置为true来启用服务级授权。例如:

    1. <property>
    2. <name>hadoop.security.authorization</name>
    3. <value>true</value>
    4. </property>
  2. 在所有的集群主机上编辑yarn-site.xml客户端配置文件。设置资源管理器地址以及yarn的Kerberos服务主体。例如:

    1. <property>
    2. <name>yarn.resourcemanager.address</name>
    3. <value>hostname:8032</value>
    4. </property>
    5. <property>
    6. <name>yarn.resourcemanager.principal</name>
    7. <value>yarn/hostname@DOMAIN</value>
    8. </property>
  3. 在所有的集群主机上编辑hdfs-site.xml客户端配置文件。设置属性以标识NameNode的Kerberos主体、Kerberos的keytab文件位置以及其主体:

    • dfs.namenode.kerberos.principal - gphdfs协议将为NameNode使用的Kerberos主体名,例如gpadmin@LOCAL.DOMAIN。
    • dfs.namenode.https.principal - gphdfs将用于NameNode的安全HTTP服务器的Kerberos主体名。例如gpadmin@LOCAL.DOMAIN。
    • com.emc.greenplum.gpdb.hdfsconnector.security.user.keytab.file - 用于Kerberos保护的HDFS服务的keytab文件路径,例如 /home/gpadmin/mdw.service.keytab。
    • com.emc.greenplum.gpdb.hdfsconnector.security.user.name - 主机的gphdfs服务主体,例如 gphdfs/mdw.example.com@LOCAL.DOMAIN。

    例如:

    1. <property>
    2. <name>dfs.namenode.kerberos.principal</name>
    3. <value>gphdfs/gpadmin@LOCAL.DOMAIN</value>
    4. </property>
    5. <property>
    6. <name>dfs.namenode.https.principal</name>
    7. <value>gphdfs/gpadmin@LOCAL.DOMAIN</value>
    8. </property>
    9. <property>
    10. <name>com.emc.greenplum.gpdb.hdfsconnector.security.user.keytab.file</name>
    11. <value>/home/gpadmin/gpadmin.hdfs.keytab</value>
    12. </property>
    13. <property>
    14. <name>com.emc.greenplum.gpdb.hdfsconnector.security.user.name</name>
    15. <value>gpadmin/@LOCAL.DOMAIN</value>
    16. </property>

测试Greenplum数据库对HDFS的访问

确认在Greenplum集群中所有主机上都能通过Kerberos认证访问HDFS。例如,输入下列命令列出一个HDFS目录:

  1. hdfs dfs -ls hdfs://namenode:8020

在HDFS中创建一个可读外部表

按照这些步骤验证能够在Kerberos化的Hadoop集群中创建可读外部表。

  1. 创建一个逗号分隔的文本文件test1.txt,其内容如下:

    1. 25, Bill
    2. 19, Anne
    3. 32, Greg
    4. 27, Gloria
  2. 将示例文本文件放在HDFS中:

    1. hdfs dfs -put test1.txt hdfs://namenode:8020/tmp
  3. 登入Greenplum数据库,并且创建一个指向Hadoop中test1.txt文件的可读外部表:

    1. CREATE EXTERNAL TABLE test_hdfs (age int, name text)
    2. LOCATION('gphdfs://namenode:8020/tmp/test1.txt')
    3. FORMAT 'text' (delimiter ',');
  4. 从该外部表读取数据:

    1. SELECT * FROM test_hdfs;

在HDFS中创建一个可写外部表

按照这些步骤验证能够在Kerberos化的Hadoop集群中创建可写外部表。这些步骤使用之前创建的可读外部表test_hdfs。

  1. 登入Greenplum数据库,并且创建一个可写外部表指向一个HDFS中的文本文件:

    1. CREATE WRITABLE EXTERNAL TABLE test_hdfs2 (LIKE test_hdfs)
    2. LOCATION ('gphdfs://namenode:8020/tmp/test2.txt'
    3. FORMAT 'text' (DELIMITER ',');
  2. 装载数据到可写外部表中:

    1. INSERT INTO test_hdfs2
    2. SELECT * FROM test_hdfs;
  3. 检查该文件在HDFS中存在:

    1. hdfs dfs -ls hdfs://namenode:8020/tmp/test2.txt
  4. 验证外部文件的内容:

    1. hdfs dfs -cat hdfs://namenode:8020/tmp/test2.txt

排查带有Kerberos的HDFS的故障

强制Classpath

如果用户在执行来自gphdfs的外部表上的SELECT语句时遇到“class not found”错误,可编辑$GPHOME/lib/hadoop-env.sh文件并且把下面的行加在该文件的末尾,但是要放在设置JAVA_LIBRARY_PATH之前。在所有集群主机上都更新该脚本。

  1. if [ -d "/usr/hdp/current" ]; then
  2. for f in /usr/hdp/current/**/*.jar; do
  3. CLASSPATH=${CLASSPATH}:$f;
  4. done
  5. fi

启用Kerberos客户端调试消息

要查看来自Kerberos客户端的调试消息,可在所有集群主机上编辑$GPHOME/lib/hadoop-env.sh客户端shell脚本,并且将HADOOP_OPTS变量设置为如下:

  1. export HADOOP_OPTS="-Djava.net.prefIPv4Stack=true -Dsun.security.krb5.debug=true ${HADOOP_OPTS}"

在Segment主机上调整JVM进程内存

在读写HDFS中的外部表时,每个Segment会启动一个JVM进程。要更改为每个JVM进程分配的内存量,可以配置GP_JAVA_OPT环境变量。

在所有集群主机上编辑$GPHOME/lib/hadoop-env.sh客户端shell脚本。

例如:

  1. export GP_JAVA_OPT=-Xmx1000m

验证Kerberos的安全性设置

检查/etc/krb5.conf文件:

  • 如果AES256加密没有被禁用,确保所有集群主机都安装了JCE Unlimited Strength Jurisdiction Policy Files。
  • 确保Kerberos的keytab文件中的所有加密类型匹配krb5.conf文件中的定义。

    1. cat /etc/krb5.conf | egrep supported_enctypes

在单个Segment主机上测试连通性

按这些步骤测试单个Greenplum数据库主机能够读取HDFS数据。这种测试方法在命令行中执行Greenplum的HDFSReader Java类,并且能够有助于排查数据库之外的连通性问题。

  1. 在HDFS中保存一份示例数据文件。

    1. hdfs dfs -put test1.txt hdfs://namenode:8020/tmp
  2. 在要测试的Segment主机上,按下面的内容创建一个环境脚本env.sh:

    1. export JAVA_HOME=/usr/java/default
    2. export HADOOP_HOME=/usr/lib/hadoop
    3. export GP_HADOOP_CON_VERSION=hdp2
    4. export GP_HADOOP_CON_JARDIR=/usr/lib/hadoop
  3. 引入所有环境脚本:

    1. source /usr/local/greenplum-db/greenplum_path.sh
    2. source env.sh
    3. source $GPHOME/lib/hadoop-env.sh
  4. 测试Greenplum数据库的HDFS读取器:

    1. java com.emc.greenplum.gpdb.hdfsconnector.HDFSReader 0 32 TEXT hdp2 gphdfs://namenode:8020/tmp/test1.txt