《Greenplum5.0 最佳实践》 访问HDFS存储 (七)

访问Hadoop集群中数据用到的工具有 外部表 external tablesgphdfs 协议, Greenplum 可以从 HDFS 上读取文件也可以向 HDFS 写文件。为了达到更快的性能,所有的段数据库是并行地读取 HDFS 中的数据。
当Hadoop集群采用的是 Kerbes 实现集群中各个节点的认证的,以确保集群数据不被恶意攻击。那么 Greenplum 必须使用的用户为 gpadmin, 该用户拥有对外部表的读写权限在HDFS中,需要通过 Kerbes 的授权。为了实现对 gpadmin 的授权,需要验证和故障排除配置。(关于kerbes的信息参看参考文献)

前期准备工作

确保功能正常和网络正常

  1. Greenplum 数据库集群
  2. 有 Kerberos-Hadoop 集群 (具体配置参考 Greenplum Database Release Notes for supported Hadoop version 都支持那些版本的HDFS )
  3. Kerberos 秘钥服务

配置 Greenplum集群

Greenplum 必须安装 JRE, Hadoop 客户端文件, Kerberos 客户端文件。
按照下面的顺序准备安装

  1. 在GPDB的所有节点上都安装相同版本的 JAVA 1.6 或者之后的版本。最好和 Hadoop 集群中配置的 JAVA环境一致。 使用命令为 java --version
  2. (可选项) 确认存在 Java 加密扩展 (Java Cryptography Extension JCE).
    默认情况下该扩展包在 JAVA_HOME/lib/security 下。 如果安装的是 JDK, 那么其所在的文件路径为 JAVA_HOME/jre/lib/security, 这个文件有 local_policy.jar
    US_eport_policy.jar 。需要注意的是 GreenplumKerberos 都应该使用的相同的 JCE 版本。
  3. .bashrc 或者 .bash_profile 中配置 JAVA_HOME 环境变量。

    export JAVA_HOME=/usr/java/jd../

  4. 执行如下代码使得环境变量生效

    source .bashrc
    source .bash_profile
  5. 安装 Kerberos 客户端, 在所有的Greenplum节点上。确保这个安装文件要和已有的 KDC 版本匹配
    在centos 上执行如下命令:

$ sudo yum -y install krb5-libs krb5-workstation
$ kinit                ## 用来确定是否安装成功

  1. 对Greenplum中的全部节点都安装 Hadoop 客户端, 参考 Hadoop 发行版相关的文件。
  2. 针对 Hadoop 设置Greenplum集群的参数配置。 版本为 gp_hadoop_target_version 参数用来确定 Hadoop 的版本。 gp_hadoop_home 确定Hadoop的安装路径
    具体参考文章 《 Greenplum Database Release Notes 》 《Greenplum Database Reference Guide》


    $ gpconfig -c gp_hadoop_target_version -v "hdp2"
    $ gpconfig -c gp_hadoop_home -v "/usr/lib/hadoop"
    1. 重新加载 Greenplum 的配置问价 postgresql.conf

      $ gpstop -u
       --- 使用如下命令确认参数的修改
      $ gpconfig -s gp_hadoop_version
      $ gpconfig -s gp_hadoop_home
      </code></pre>
    2. 授权 Greenplum的角色可以在HDFS中拥有自己的可读写外部表, 包括的用户有 gpadmin 和 其他超级用户。 授权 SELECT 权限能够在 HDFS 上创建爱你可读外部表,

      授权 *INSERT* 权限可以去写外部表在 *HDFS* 上
      <pre><code>
       #= GRANT SELECT ON PROTOCOL gphdfs TO gpadmin;
       #= GRANT INSERT ON PROTOCOL gphdfs TO gpamdin;
       </code></pre>
    3. 将 Greenplum 数据库外部表权限授予外部表所有者角色。

       <pre><code>
        #= ALTER ROLE HDFS_USER CREATEEXTTABLE (type='readable');
        #= ALTER ROLE HDFS_USER CREATEEXTTABLE (type='writable');
        </code></pre>
      

创建和安装秘钥文件

按照如下顺序执行

  1. 使用 root 用户登录到 KDC 服务器上
  2. 使用 kadmin.local 命令为 gpadmin 创建新的代理

    <pre><code>

    # kadmin.local -q "addprinc -randkey gpadmin@LOCAL.DOMAIN"

    </code></pre>
  3. 使用 kadmin.local 创建为Greenplum集群的每一个节点创建一个 Kerberos 服务代理, 这个代理的名字应该是 name|role@REALM 格式,解释如下

    *name* 是 *gphdfs* 服务的名称,默认情况下使用 *gphdfs*
    *role*    是 *Greenplum* 集群主机的 DNS 可解析的主机名称( hostname -f 命令)
    *REALM* 是 *Kerberos* 的realm, 例如 *LOCAL.DOMAIN*
    例子如下,下面这些明亮用来向Greenplum数据库集群中的四个节点 (mdw.exam[ple.com smdw.example.com sdw1.example.com sdw2.example.com)
    <pre><code>
     # kadmin.local -q "addprinc -randkey6 gphdfs/mdw.example.com@LOCAL.DOMAIN"
     # kadmin.local -q "addprinc -randkey6 gphdfs/smdw.example.com@LOCAL.DOMAIN"
     # kadmin.local -q "addprinc -randkey6 gphdfs/smdw1.example.com@LOCAL.DOMAIN"
     # kadmin.local -q "addprinc -randkey6 gphdfs/smdw2.example.com@LOCAL.DOMAIN"

创建代理为每一个主机,使用相同的代理和realm,用每个主机的完整名称限定替换

  1. 位每个节点创建代理(gpadmin 和 gphdfs 服务代理)。 存储秘钥在一个方便的文件位置(例如:/etc/security/keytabs)。也可以将秘钥在稍后的时间内部署到各自的主机上。

    <pre><code>
     # kadmin.local -q "xst -k /etc/security/keytabs/gphdfs.service.keytab gpadmin@LOCAL.DOMAIN"
     # kadmin.local -q "xst -k /etc/security/keytabs/mdw.service.keytrab gpadmin/mdw gphdfs/mdw.example.com@LOCAL.DOMAIN"
     # kadmin.local -q "xst -k /etc/security/keytabs//smdw.service.keytrab gpadmin/smdw gphdfs/smdw.example.com@LOCAL.DOMAIN"
     # kadmin.local -q "xst -k /etc/security/keytabs//smdw1.service.keytrab gpadmin/smdw1 gphdfs/smdw1.example.com@LOCAL.DOMAIN"
     # kadmin.local -q "xst -k /etc/security/keytabs//smdw1.service.keytrab gpadmin/smdw1 gphdfs/smdw2.example.com@LOCAL.DOMAIN"
    </code></pre>
  2. 修改 gphdfs.service.keytab 的访问者权限

    # chown gpadmin:gpadmin /etc/security/keytabs/gphdfs.service.keytab
    # chmod 440 /etc/security/keytabs/gphdfs.service.keytab

  3. 复制秘钥文件到 gpadmin@LOCAL.DOMAIN 到GPDB的master节点上

# scp /etc/security/keytabs/gphdfs.service.keytab mdw_fqdn:/home/gpadmin/gphdfs.service.keytab

  1. 将对应的秘钥文件发送到对应的GPDB节点上

# scp /etc/security/keytabs/mdw.service.keytab mdw_fqdn:/home/gpadmin/mdw.service.keytab
# scp /etc/security/keytabs/smdw.service.keytab smdw_fqdn:/home/gpadmin/smdw.service.keytab
# scp /etc/security/keytabs/smdw1.service.keytab smdw1_fqdn:/home/gpadmin/smdw1.service.keytab
# scp /etc/security/keytabs/smdw2.service.keytab smdw2_fqdn:/home/gpadmin/smdw2.service.keytab

为 Kerberos 配置 gphdfs

  1. 编辑Hadoop 的 core-site.xml 客户端配置文件在Greenplum中的所有的节点上。设置服务层的授权,使用的是 hadoop.security.authorization 参数为 true

    <property>
        <name>hadoop.serurity.authorization</name>
        <value>true</value>
    </preperty>

  2. 编辑集群的所有节点的 yarn-site.xml 客户端配置文件。设置资源管理器地址和yarn的kerberos 服务代理

    <pre><code>    

       <name>yarn.resourcemanger.address</name>
       <value>hostname:8032</value>

    <name>yarn.resourcemanger.principal</name>
    <value>yarn/hostname@DOMAIN</value>


  1. 编辑文件 hdfs-site.xml 客户端配置文件在全部的集群节点上。设置 NameNode 的代理, Kerberos 的秘钥文件
    dfs.namenode.kerberos.principal gphdfs 的协议代理,将会被 NameNode 使用。

dfs.namenode.https.principal 将会被 NameNode 的 安全 HTTP 协议使用
com.emc.greenplum.gpdb.hdfsconnector.serurity.user.keytab.file 对于 Kerberos HDFS 服务的秘钥文件路径, 例如路径是 /home/gpamdin/mdw.service.keytab ...
com.emc.greenplum.gpdb.hdfsconnector.security.user.name gphdfs 代理的节点。


<name>dfs.namenode.kerberos.principal</name>
<value>gphdfs/gpadmin@LOCAL.DOMAIN</value>


<name>dfs.namenode.https.principal</name>
<value>gphdfs/gpadmin@LOCAL.DOMAIN</value>


<name>com.emc.greenplum.gpdb.hdfsconnector.security.user.keytab.file</name>
<value>/home/gpadmin/gpadmin.hdfs.keytab</value>


<name>com.emc.greenplum.gpdb.hdfsconnector.security.user.name</name>
<value>gpadmin/@LOCAL.DOMAIN</value>


使用Greenplum去访问HDFS

确保 Greenplum 的所有节点可以通过 Kerberos 访问HDFS。
在HDFS文件路径下,执行如下的命令


hdfs dfs -ls hdfs://namenode:8020

在HDFS上创建可读的外部表

按照如下步骤在Hadoop上创建可读外部表

  1. 创建一个逗号分隔符的文件, test1.txt 包含如下内容

25, Bill
19,Anne
32,Greg
27,Gloria

  1. 将这个实例文件保存到HDFS中

hdfs dfs -put test1.txt hdfs://namenode:8020/tmp

  1. 登录到Greenplum数据库集群中,创建一个可以读的外部表,并将该外部表指向Hadoop路径

CREATE EXTERNAL TABLE test_hdfs (age int, name text)
LOCATION ('gphdfs://namenode:8020/tmp/test1.txt')
FORMAT 'text' (delimiter ',');

  1. 读取外部表的数据

SELECT * FROM test_hdfs;

在HDFS上创建可以写的外部表

创建可以写的外部表同样按照下面的步骤执行。

  1. 登录Greenplum数据库集群,创建一个指向HDFS上文件的外部表 test_hdfs2

CREATE WRITABLE EXTERNAL TABLE test_hdfs2 (like test_hdfs)
LOCATION ('gphdfs://namenode:8020/tmp/test2.txt' )
FORMAT 'text' (DELIMITER ',');

  1. 向外部表中写入数据

INSERT INTO test_hdfs2 SELECT * FROM test_hdfs;

  1. 检查新创建的外部表的文件是否在HDFS中

hdfs dfs -ls hdfs://namenode:8020/tmp/test2.txt

  1. 确认外部表文件中的内容

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

异常处理部分

强制环境变量 (Forcing Classpath)

当执行 SELECT 语句查询外部表数据的时候,如果遇到 "class not found" 错误。需要去编辑 $GPHOME/lib/hadoop-env.sh 文件。同时在文件的后面追加如下信息,且在 JAVA_LIBRARY_PATH设置之前。更新该文件


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

允许 Kerberos 客户端可以Debug Messages

从Kerberos看到debug信息, 编辑 $GPHOME/lib/hadoop-env.sh 客户端脚本在集群的所有节点,设置 HADOOP_OPTS 环境变量


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

调整段节点上 JVM 程序的内存

每一个段数据库都会加载一个JVM进程去读写HDFS上的外部文件,为了修改这个JVM进程内存的申请,需要修改环境变量 GP_JAVA_OPT
$GPHOME/lib/hadoop-env.sh 客户端脚本编辑如下


export GP_JAVA_OPT=-Xmx1000m

确保 Kerberos 的安全设置

重新检查 /etc/krb5.conf 文件
如果 AES256 加密文件不能使用,确保所有的节点都安装了 JCE 模块
确保全波的加密文件中的所有加密类型与 krb5.conf 定义文件匹配


cat /etc/krb5.conf | egrep supported_enctypes

测试单个段数据的联通性

按照如下的步骤去测试 Greenplum 数据库节点去读取 HDFS 上的文件。这个测试方法执行的是 Greenplum 中的 HDFSReader JAVA类。可以用来帮助我们派出故障

  1. 将文件保存在HDFS中

hdfs dfs -put test1.txt hdfs://namenode:8020/tmp

  1. 在一个段数据库上测试, 创建环境脚本文件 env.sh,

$ vi env.sh
export JAVA_HOME=/usr/java/default
export HADOOP_HOME=/usr/lib/hadoop
export GP_HADOOP_CON_VERSIONM=hdp2
export GP_HADOOP_CON_JARDIR=/usr/lib/hadoop

  1. 刷新环境变量文件

source /usr/local/greenplum-db/greenplum_path.sh
source env.sh
source $GPHOME/lib/hadoop-env.sh

  1. 测试 Greenplum 的 HDFS 的读能力

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

参考文献
">https://gpdb.docs.pivotal.io/500/best_practices/kerberos-hdfs.html>

上一篇:理解 postgresql.conf 的work_mem 参数配置


下一篇:json 函数介绍