用受Kerberos保护的Hadoop集群启用gphdfs认证

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

    上级主题: 安全性配置指南

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

    • Greenplum数据库集群
    • 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的位置。例如:

    4. 引入.bashrc或.bash_profile文件将改动应用到用户的环境。例如:

    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数据库参考指南

      1. gpstop -u

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

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

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

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

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

    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。
      • 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上的拥有关系和权限:

    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. <value>true</value>
      3. </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 - the 主机的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. <value>/home/gpadmin/gpadmin.hdfs.keytab</value>
      11. </property>
      12. <property>
      13. <name>com.emc.greenplum.gpdb.hdfsconnector.security.user.name</name>
      14. <value>gpadmin/@LOCAL.DOMAIN</value>
      15. </property>

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

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

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

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

      1. hdfs dfs -put test1.txt hdfs://namenode:8020/tmp
    2. 登入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 ',');
    3. 从该外部表读取数据:

      1. SELECT * FROM test_hdfs;

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

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

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

    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的故障

    如果用户在执行来自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}"

    在读写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

    按这些步骤测试单个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
      1. source /usr/local/greenplum-db/greenplum_path.sh
      2. source env.sh
    3. 测试Greenplum数据库的HDFS读取器: