访问Hadoop集群中数据用到的工具有 外部表 external tables 和 gphdfs 协议, Greenplum 可以从 HDFS 上读取文件也可以向 HDFS 写文件。为了达到更快的性能,所有的段数据库是并行地读取 HDFS 中的数据。
当Hadoop集群采用的是 Kerbes 实现集群中各个节点的认证的,以确保集群数据不被恶意攻击。那么 Greenplum 必须使用的用户为 gpadmin, 该用户拥有对外部表的读写权限在HDFS中,需要通过 Kerbes 的授权。为了实现对 gpadmin 的授权,需要验证和故障排除配置。(关于kerbes的信息参看参考文献)
前期准备工作
确保功能正常和网络正常
- Greenplum 数据库集群
- 有 Kerberos-Hadoop 集群 (具体配置参考 Greenplum Database Release Notes for supported Hadoop version 都支持那些版本的HDFS )
- Kerberos 秘钥服务
配置 Greenplum集群
Greenplum 必须安装 JRE, Hadoop 客户端文件, Kerberos 客户端文件。
按照下面的顺序准备安装
- 在GPDB的所有节点上都安装相同版本的 JAVA 1.6 或者之后的版本。最好和 Hadoop 集群中配置的 JAVA环境一致。 使用命令为 java --version
- (可选项) 确认存在 Java 加密扩展 (Java Cryptography Extension JCE).
默认情况下该扩展包在 JAVA_HOME/lib/security 下。 如果安装的是 JDK, 那么其所在的文件路径为 JAVA_HOME/jre/lib/security, 这个文件有 local_policy.jar 和
US_eport_policy.jar 。需要注意的是 Greenplum 和 Kerberos 都应该使用的相同的 JCE 版本。 -
在 .bashrc 或者 .bash_profile 中配置 JAVA_HOME 环境变量。
export JAVA_HOME=/usr/java/jd../
- 执行如下代码使得环境变量生效
source .bashrc
source .bash_profile - 安装 Kerberos 客户端, 在所有的Greenplum节点上。确保这个安装文件要和已有的 KDC 版本匹配
在centos 上执行如下命令:
$ sudo yum -y install krb5-libs krb5-workstation
$ kinit ## 用来确定是否安装成功
- 对Greenplum中的全部节点都安装 Hadoop 客户端, 参考 Hadoop 发行版相关的文件。
-
针对 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"-
重新加载 Greenplum 的配置问价 postgresql.conf
$ gpstop -u --- 使用如下命令确认参数的修改 $ gpconfig -s gp_hadoop_version $ gpconfig -s gp_hadoop_home </code></pre>
-
授权 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>
-
将 Greenplum 数据库外部表权限授予外部表所有者角色。
<pre><code> #= ALTER ROLE HDFS_USER CREATEEXTTABLE (type='readable'); #= ALTER ROLE HDFS_USER CREATEEXTTABLE (type='writable'); </code></pre>
-
创建和安装秘钥文件
按照如下顺序执行
- 使用 root 用户登录到 KDC 服务器上
-
使用 kadmin.local 命令为 gpadmin 创建新的代理
<pre><code>
# kadmin.local -q "addprinc -randkey gpadmin@LOCAL.DOMAIN"
</code></pre>
-
使用 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,用每个主机的完整名称限定替换
-
位每个节点创建代理(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>
-
修改 gphdfs.service.keytab 的访问者权限
# chown gpadmin:gpadmin /etc/security/keytabs/gphdfs.service.keytab # chmod 440 /etc/security/keytabs/gphdfs.service.keytab
- 复制秘钥文件到 gpadmin@LOCAL.DOMAIN 到GPDB的master节点上
# scp /etc/security/keytabs/gphdfs.service.keytab mdw_fqdn:/home/gpadmin/gphdfs.service.keytab
- 将对应的秘钥文件发送到对应的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
-
编辑Hadoop 的 core-site.xml 客户端配置文件在Greenplum中的所有的节点上。设置服务层的授权,使用的是 hadoop.security.authorization 参数为 true
<property> <name>hadoop.serurity.authorization</name> <value>true</value> </preperty>
-
编辑集群的所有节点的 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>
- 编辑文件 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上创建可读外部表
- 创建一个逗号分隔符的文件, test1.txt 包含如下内容
25, Bill
19,Anne
32,Greg
27,Gloria
- 将这个实例文件保存到HDFS中
hdfs dfs -put test1.txt hdfs://namenode:8020/tmp
- 登录到Greenplum数据库集群中,创建一个可以读的外部表,并将该外部表指向Hadoop路径
CREATE EXTERNAL TABLE test_hdfs (age int, name text)
LOCATION ('gphdfs://namenode:8020/tmp/test1.txt')
FORMAT 'text' (delimiter ',');
- 读取外部表的数据
SELECT * FROM test_hdfs;
在HDFS上创建可以写的外部表
创建可以写的外部表同样按照下面的步骤执行。
- 登录Greenplum数据库集群,创建一个指向HDFS上文件的外部表 test_hdfs2
CREATE WRITABLE EXTERNAL TABLE test_hdfs2 (like test_hdfs)
LOCATION ('gphdfs://namenode:8020/tmp/test2.txt' )
FORMAT 'text' (DELIMITER ',');
- 向外部表中写入数据
INSERT INTO test_hdfs2 SELECT * FROM test_hdfs;
- 检查新创建的外部表的文件是否在HDFS中
hdfs dfs -ls hdfs://namenode:8020/tmp/test2.txt
- 确认外部表文件中的内容
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类。可以用来帮助我们派出故障
- 将文件保存在HDFS中
hdfs dfs -put test1.txt hdfs://namenode:8020/tmp
- 在一个段数据库上测试, 创建环境脚本文件 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
- 刷新环境变量文件
source /usr/local/greenplum-db/greenplum_path.sh
source env.sh
source $GPHOME/lib/hadoop-env.sh
- 测试 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>