前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于HDFS-KMS集群化部署教程,你以前看的都错了!

关于HDFS-KMS集群化部署教程,你以前看的都错了!

作者头像
京东技术
发布2018-07-30 16:13:51
2.3K0
发布2018-07-30 16:13:51
举报
文章被收录于专栏:京东技术

作 者 简 介

吕信,京东商城基础架构部资深架构师,拥有多年数据产品研发及架构经验。在京东及国内主导过多种数据产品的开发及社区建设,积极活跃于数据产品领域,对数据库及大数据领域各个产品具有丰富经验,目前在京东商城主导弹性数据库研发及推广使用。

>>>>

写在前面

本来要进行HDFS集群的KMS部署的,其实这是很成熟的技术,在网上找了很长,竟然没有靠谱的教程,不是错误的,就是单机自己玩模式的,不知从什么时候起,有个先驱写了一篇错误的教程,然后这些抄袭者们就开始各种复制粘贴,也不去验证对错,着实让我悲愤。

一气之下,决定自己参照官方文档进行部署,然后将部署的过程和结果写下来,来祭奠那些抄袭者们。

本文章仅代表作者自己的实际部署及操作结果,有任何疏漏,望指正。

>>>>

KMS说明

Hadoop KMS是一个基于 Hadoop的加密管理服务端。Client是一个KeyProvider的实现,使用KMS HTTP REST API与KMS交互。

KMS和它的客户端内置安全验证并且它们支持HTTP SPNEGO Kerberos 身份验证和HTTPS安全转换。

由于本次只是为了说明如何部署KMS,所以本文档就采用simple的身份认证模式,没有采用Kerberos。需要采用Kerberos进行身份认证的同仁可以参考官方文档进行Kerberos认证模式部署。

KMS实际上是一个Java Web应用程序,运行在与Hadoop发行版绑定在一起的预先配置好的Tomcat服务器上。

注意:Kms是一个密钥管理服务器,它并不负责加密文件。

通过KMS可以实现用户无感知的HDFS端到端的透明加密。配置完kms后,用户往hdfs上存储数据的时候,无需用户做任何程序代码的更改(通过调用KeyProvider API ,在数据存入到HDFS上面的时候进行数据加密,解密的过程一样)。数据加密和解密由客户端自动完成。

>>>>

环境说明

软件名称

软件版本

Hadoop

Hadoop 2.6.1

JDK

1.8.0_92

操作系统

CentOS release 6.5 (Final)

Hadoop超级用户

hadp

>>>>

服务器列表

HostName

IP地址

角色

说明

BJ-PRESTO-TEST-100080.lvxin.com

192.168.100.80

NameNode,kms

BJ-PRESTO-TEST-100081.lvxin.com

192.168.100.81

NameNode

BJ-PRESTO-TEST-100082.lvxin.com

192.168.100.82

DataNode

BJ-PRESTO-TEST-100083.lvxin.com

192.168.100.83

DataNode

BJ-PRESTO-TEST-100084.lvxin.com

192.168.100.84

DataNode

BJ-PRESTO-TEST-100085.lvxin.com

192.168.100.85

DataNode

BJ-PRESTO-TEST-100086.lvxin.com

192.168.100.86

DataNode

BJ-PRESTO-TEST-100087.lvxin.com

192.168.100.87

DataNode

BJ-PRESTO-TEST-100088.lvxin.com

192.168.100.88

DataNode

BJ-PRESTO-TEST-100089.lvxin.com

192.168.100.89

DataNode

BJ-PRESTO-TEST-100090.lvxin.com

192.168.100.90

DataNode

BJ-PRESTO-TEST-100091.lvxin.com

192.168.100.91

DataNode

BJ-PRESTO-TEST-100092.lvxin.com

192.168.100.92

DataNode

BJ-PRESTO-TEST-100093.lvxin.com

192.168.100.93

HDFS Client

>>>>

配置说明

完成KMS的配置共涉及到5个文件的修改,分别是:core-site.xml、hdfs-site.xml、kms-site.xml、kms-env.sh、kms-acls.xml。下面对每个文件的修改内容进行依次说明:

>>>>

core-site.xml

在所有的NameNode和DataNode上修改该配置文件,在该配置文件上增加如下配置内容:

<property><name>hadoop.security.key.provider.path</name><value>kms://http@BJ-PRESTO-TEST-100080.lvxin.com:16000/kms</value></property>

>>>>

hdfs-site.xml

在所有的NameNode和DataNode上修改该配置文件,在该配置文件上增加如下配置内容:

<property><name>dfs.encryption.key.provider.uri </name><value>kms://http@BJ-PRESTO-TEST-177080.jd.com:16000/kms</value></property>

注意】上面两个配置文件修改完毕后,需要重启HDFS服务,后面的修改仅重启kms服务即可。

>>>>

kms-site.xml

由于Kms服务只需要在NameNode:BJ-PRESTO-TEST-100080.lvxin.com上启动,因此仅需要修改BJ-PRESTO-TEST-100080.lvxin.com服务器上的该配置文件,其他服务器上的该配置文件不需要修改。在该配置文件上增加如下配置内容:

<!-- KMS Backend KeyProvider --><property><name>hadoop.kms.key.provider.uri</name><value>jceks://file@/${user.home}/kms.keystore</value></property><property><name>hadoop.security.keystore.java-keystore-provider.password-file</name><value>kms.keystore.password</value> <!--秘钥密码存储文件,该文件需要手动创建,并且放在kms的tomcat下classes文件夹下--></property><!—本文关注与kms部署这里选择simple就可以了--> <property> <name>hadoop.kms.authentication.type</name> <value>simple</value> </property></configuration>

使用keytool生成的秘钥密码是123456 将密码直接写入到kms.keystore.password文件:

echo 123456 > ${HADOOP_HOME}/share/hadoop/kms/tomcat/webapps/kms/WEB-INF/classes/kms.keystore.password

>>>>

kms-env.sh

由于Kms服务仅需要在NameNode:BJ-PRESTO-TEST-100080.lvxin.com上启动,因此仅需要修改BJ-PRESTO-TEST-100080.lvxin.com服务器上的该配置文件,其他服务器上的该配置文件不需要修改。在该配置文件上增加如下配置内容:

export KMS_HOME=${HADOOP_HOME}export KMS_LOG=${KMS_HOME}/logs/kmsexport KMS_HTTP_PORT=16000export KMS_ADMIN_PORT=16001

】这里可以通过kms-env.sh这个脚本来设置。也可以直接设置在~/.bashrc中。

>>>>

kms-acls.xml

由于Kms服务仅需要在NameNode:BJ-PRESTO-TEST-100080.lvxin.com上启动,因此仅需要修改BJ-PRESTO-TEST-100080.lvxin.com服务器上的该配置文件:kms-acls.xml,其他服务器上的该配置文件不需要修改。该文件可能会随时改变,主要用来配置key与用户的对应关系。

根据测试需要,我们添加两个用户:user_a和user_b,新增user_a_key对应user_a,user_b_key对应user_b,因此需要在配置文件:$HADOOP_CONF_DIR/kms-acls.xml中添加如下配置项:

<property> <name>key.acl.user_a_key.DECRYPT_EEK</name> <value>user_a</value> </property> <property> <name>key.acl.user_b_key.DECRYPT_EEK</name> <value>user_b</value> </property>

>>>>

创建密钥

只需要在NameNode:BJ-PRESTO-TEST-100080.lvxin.com 上创建密钥,创建密钥步骤如下:

Step1:创建user_a_key

[hadp@BJ-PRESTO-TEST-100080 hadoop]$ keytool -genkey -alias 'user_a_key'输入密钥库口令:##这里输入的口令是:123456您的名字与姓氏是什么? [Unknown]: lvxin您的组织单位名称是什么? [Unknown]: jd您的组织名称是什么? [Unknown]: jd您所在的城市或区域名称是什么? [Unknown]: bj您所在的省/市/自治区名称是什么? [Unknown]: bj该单位的双字母国家/地区代码是什么? [Unknown]: cnCN=lvxin, OU=jd, O=jd, L=bj, ST=bj, C=cn是否正确? [否]: 是 输入 <user_a_key> 的密钥口令 (如果和密钥库口令相同, 按回车):#这里输入的口令与第一次输入的口令一样,都是:123456再次输入新口令:[hadp@BJ-PRESTO-TEST-100080 hadoop]$

Step2:以相同方式创建user_b_key

[hadp@BJ-PRESTO-TEST-100080 hadoop]$ keytool -genkey -alias 'user_b_key'输入密钥库口令:您的名字与姓氏是什么? [Unknown]: lvxin您的组织单位名称是什么? [Unknown]: jd您的组织名称是什么? [Unknown]: jd您所在的城市或区域名称是什么? [Unknown]: bj您所在的省/市/自治区名称是什么? [Unknown]: bj该单位的双字母国家/地区代码是什么? [Unknown]: cnCN=lvxin, OU=jd, O=jd, L=bj, ST=bj, C=cn是否正确? [否]: 是 输入 <user_b_key> 的密钥口令 #(如果和密钥库口令相同, 按回车):[hadp@BJ-PRESTO-TEST-100080 hadoop]$

Step3:查看刚刚创建完成的密钥

[hadp@BJ-PRESTO-TEST-100080 hadoop]$ keytool -list输入密钥库口令: #这里输入上面的密码:123456 密钥库类型: JKS密钥库提供方: SUN 您的密钥库包含 2 个条目 user_a_key, 2018-7-3, PrivateKeyEntry,证书指纹 (SHA1): 47:5A:5B:09:6F:50:65:8D:9B:5F:5A:E5:48:88:1C:86:63:BB:10:39user_b_key, 2018-7-3, PrivateKeyEntry,证书指纹 (SHA1): 71:75:E8:7F:90:57:BE:E1:CD:03:63:D1:7F:28:5D:51:BC:5D:D5:8C[hadp@BJ-PRESTO-TEST-100080 hadoop]$

>>>>

启动hdfs

[hadp@BJ-PRESTO-TEST-100080 hadoop]$start-dfs.sh

>>>>

启动KMS

在namenode:BJ-PRESTO-TEST-100080.lvxin.com上执行命令:kms.sh start,此时会启动一个进程:Bootstrap,如下所示:

[hadp@BJ-PRESTO-TEST-100080 ~]$ kms.sh start setting KMS_HOME=${HADOOP_HOME} setting KMS_LOG=${KMS_HOME}/logs/kms setting KMS_HTTP_PORT=16000 setting KMS_ADMIN_PORT=16001Using CATALINA_BASE: /software/servers/hadoop-2.6.1/share/hadoop/kms/tomcatUsing CATALINA_HOME: /software/servers/hadoop-2.6.1/share/hadoop/kms/tomcatUsing CATALINA_TMPDIR: /software/servers/hadoop-2.6.1/share/hadoop/kms/tomcat/tempUsing JRE_HOME: /software/servers/jdk1.8.0_92Using CLASSPATH: /software/servers/hadoop-2.6.1/share/hadoop/kms/tomcat/bin/bootstrap.jarUsing CATALINA_PID: /tmp/kms.pidExisting PID file found during start.Removing/clearing stale PID file.[hadp@BJ-PRESTO-TEST-100080 ~]$ ps -ef|grep -i "Bootstrap"hadp 14414 1 99 16:12 pts/1 00:00:12 /software/servers/jdk1.8.0_92/bin/java -Djava.util.logging.config.file=/software/servers/hadoop-2.6.1/share/hadoop/kms/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Dkms.home.dir=/software/servers/hadoop-2.6.1 -Dkms.config.dir=/software/servers/hadoop-2.6.1/etc/hadoop -Dkms.log.dir=/software/servers/hadoop-2.6.1/logs/kms -Dkms.temp.dir=/software/servers/hadoop-2.6.1/temp -Dkms.admin.port=16001 -Dkms.http.port=16000 -Dkms.max.threads=1000 -Dkms.ssl.keystore.file=/home/hadp/.keystore -Dkms.ssl.keystore.pass=password -Djava.endorsed.dirs=/software/servers/hadoop-2.6.1/share/hadoop/kms/tomcat/endorsed -classpath /software/servers/hadoop-2.6.1/share/hadoop/kms/tomcat/bin/bootstrap.jar -Dcatalina.base=/software/servers/hadoop-2.6.1/share/hadoop/kms/tomcat -Dcatalina.home=/software/servers/hadoop-2.6.1/share/hadoop/kms/tomcat -Djava.io.tmpdir=/software/servers/hadoop-2.6.1/share/hadoop/kms/tomcat/temp org.apache.catalina.startup.Bootstrap starthadp 14482 14371 0 16:13 pts/1 00:00:00 grep -i Bootstrap

>>>>

创建加密区

创建key

[hadp@BJ-PRESTO-TEST-100080 ~]$ hadoop key create user_a_keyuser_a_key has been successfully created with options Options{cipher='AES/CTR/NoPadding', bitLength=128, description='null', attributes=null}.KMSClientProvider[http://BJ-PRESTO-TEST-100080.lvxin.com:16000/kms/v1/] has been updated

】user_a_key为上面通过keytool创建的密钥。

查看key详细信息

[hadp@BJ-PRESTO-TEST-100080 ~]$ hadoop key listListing keys for KeyProvider: KMSClientProvider[http://BJ-PRESTO-TEST-100080.lvxin.com:16000/kms/v1/]user_a_key[hadp@BJ-PRESTO-TEST-100080 ~]$

创建文件目录

[hadp@BJ-PRESTO-TEST-100080 ~]$ hadoop fs -mkdir /user_a

配置user_a目录权限

[hadp@BJ-PRESTO-TEST-100080 ~]$ hadoop fs -chown user_a:test_group /user_a

设置/user_a为加密区

[hadp@BJ-PRESTO-TEST-100080 ~]$ hdfs crypto -createZone -keyName user_a_key -path /user_aAdded encryption zone /user_a[hadp@BJ-PRESTO-TEST-100080 ~]$

】加密区必须是空目录,几级目录都行,但必须为空。

查看已加密区域

[hadp@BJ-PRESTO-TEST-100080 ~]$ hdfs crypto -listZones/user_a user_a_key [hadp@BJ-PRESTO-TEST-100080 ~]$

】以相同方式创建user_b目录并使用user_b_key对目录加密。

>>>>

验证

我们通过添加三个用户user_a、user_b、user_c对加密结果进行验证。

>>>>

添加测试用户

>>>>

NameNode操作

在两个NameNode:BJ-PRESTO-TEST-100080.lvxin.com和BJ-PRESTO-TEST-100081.lvxin.com上的配置文件:hadoop-policy.xml中添加测试用户访问权限。

常用的限制访问hdfs的权限配置,只需要修改security.client.protocol.acl参数即可,此参数用于控制哪些用户可以访问hdfs,配置为“*”时表示任何用户都不受限制,此参数在配置文件:hadoop-policy.xml中。

Step1:修改配置文件

在NameNode:BJ-PRESTO-TEST-100080.lvxin.com的配置文件:$HADOOP_CONF_DIR/Hadoop-policy.xml中添加如下配置项:

<property> <name>security.client.protocol.acl</name> <value>hadp,user_a,user_b,user_c</value></property>

修改完成后,将该配置文件scp到另一个NameNode:BJ-PRESTO-TEST-100081.lvxin.com上:

[hadp@BJ-PRESTO-TEST-100080 hadoop]$ scp hadoop-policy.xml 192.168.100.81:$HADOOP_CONF_DIR/hadoop-policy.xml

Step2:刷新NameNode用户访问权限

在任意一个NameNode上执行以下命令刷新用户权限:

[hadp@BJ-PRESTO-TEST-100080 hadoop]$ hdfs dfsadmin -refreshServiceAclRefresh service acl successful for BJ-PRESTO-TEST-100080.lvxin.com/192.168.100.80:8020Refresh service acl successful for BJ-PRESTO-TEST-100081.lvxin.com/192.168.100.81:8020[hadp@BJ-PRESTO-TEST-100080 hadoop]$

】如果启动了Federation的功能,每组NameNode都需要执行该命令,并且每组的用户权限都是独立的。

>>>>

Client端操作

在HDFS Client端: BJ-PRESTO-TEST-100093.lvxin.com上有三个用户分别是user_a,user_b,user_c,然后在每个新建用户的~/.bashrc中添加如下配置信息:

[user_a@BJ-PRESTO-TEST-100093 ~]$ cat ~/.bashrc# .bashrc# Source global definitionsif [ -f /etc/bashrc ]; then . /etc/bashrcfiexport JAVA_HOME=/software/servers/jdk1.8.0_92export PATH=$JAVA_HOME/bin:$PATHexport HADOOP_HOME=/software/servers/hadoop-2.6.1export HADOOP_MAPRED_HOME=$HADOOP_HOMEexport HADOOP_COMMON_HOME=$HADOOP_HOMEexport HADOOP_HDFS_HOME=$HADOOP_HOMEexport HADOOP_YARN_HOME=$HADOOP_HOMEexport HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoopexport HDFS_CONF_DIR=$HADOOP_HOME/etc/hadoopexport YARN_CONF_DIR=$HADOOP_HOME/etc/hadoopexport PATH=$PATH:$HADOOP_HOME/bin:$JAVA_HOME/bin:$HADOOP_HOME/sbin:

然后执行source:

[user_a@BJ-PRESTO-TEST-100093 ~]$ source ~/.bashrc

>>>>

加密验证

在Client端:BJ-PRESTO-TEST-100093.lvxin.com,使用user_c用户上传文件test.txt至user_a及user_b文件目录,均报错没有权限,但是可以上传至/user_c目录:

[root@BJ-PRESTO-TEST-100093 ~]# su - user_c[user_c@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -put test.txt /user_aput: Permission denied: user=user_c, access=WRITE, inode="/user_a":user_a:test_group:drwxr-xr-x[user_c@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -put test.txt /user_bput: Permission denied: user=user_c, access=WRITE, inode="/user_b":user_b:test_group:drwxr-xr-x[user_c@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -put test.txt /user_cuser_c@BJ-PRESTO-TEST-100093 ~]$

切换至user_a用户,将test.txt文件上传至/user_a文件夹,切换至user_b用户,将test.txt文件上传至/user_b文件夹。

使用user_a用户读取/user_a/test.txt文件可正常显示,读取/user_b/test.txt文件提示没有权限:

[root@BJ-PRESTO-TEST-100093 ~]# su - user_a[user_a@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -put test.txt /user_a[user_a@BJ-PRESTO-TEST-100093 ~]$ logout[root@BJ-PRESTO-TEST-100093 ~]# su - user_b[user_b@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -put test.txt /user_b[user_b@BJ-PRESTO-TEST-100093 ~]$ logout[root@BJ-PRESTO-TEST-100093 ~]# su - user_a[user_a@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -cat /user_a/test.txtthis is content!!!![user_a@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -cat /user_b/test.txtcat: User [user_a] is not authorized to perform [DECRYPT_EEK] on key with ACL name [user_b_key]!![user_a@BJ-PRESTO-TEST-100093 ~]$

由于在hdfs中所有的文件都会在目录/.reserved下面存储一份原始文件,因此我们查看加密区下文件/user_a/test.txt在/.reserved下面的原始文件,从而验证该文件有没有被加密:

[user_a@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -cat /.reserved/raw/user_a/test.txtW�F(�9����N!�r'�:[user_a@BJ-PRESTO-TEST-100093 ~]$

由于原始文件没有在加密区中,但是文件的内容是经过kms加密后的内容,所以读取原始文件的过程没有kms解密阶段,所以读出来的内容是密文。

然后查看/user_c/test.txt对应的的原始文件:

[user_a@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -cat /.reserved/raw/user_c/test.txtthis is content!!!![user_a@BJ-PRESTO-TEST-100093 ~]$

由于/user_c不是加密区,所以文件/user_c/test.txt的内容是没有经过加密的因此该目录下的所有文件都是非加密的,因此读到的原始文件的内容就是明文。

因此,可以证明加密区的文件确实经过了kms的透明加密。

>>>>

总结

通过KMS可以实现hdfs文件的透明加密,并且验证通过。

>>>>

问题及解决方案

1、Access denied for user user_a. Superuser privilege is require

在使用user_a查看/.reserved/raw下面的文件的时候,报出错误,说没有权限,现象如下:

[user_a@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -cat /.reserved/raw/user_a/test.txt

cat: Access denied for user user_a. Superuser privilege is required

[user_a@BJ-PRESTO-TEST-100093 ~]$

原因:user_a,user_b,user_c不是超级用户权限。由于hdfs中没有配置超级用户组,因此hdfs的的默认超级用户组就是:supergroup,由于hdfs的用户权限验证过程是:根据客户端的用户名,验证在NameNode上的操作系统中该用户名所属的用户组是否为超级用户:supergroup,若是supergroup,则该用户就是超级用户;否则就不是超级用户。因此需要在两个NameNode上都执行下面的操作可以解决该问题:

useradd -g supergroup user_auseradd -g supergroup user_buseradd -g supergroup user_c

2、can't be moved from an encryption zone

当从加密区删除透明加密过的文件时报出此错误,如下:

[user_a@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -rm /user_a/test.txt18/07/04 13:04:25 INFO fs.TrashPolicyDefault: Namenode trash configuration: Deletion interval = 1440 minutes, Emptier interval = 0 minutes.rm: Failed to move to trash: hdfs://ns1/user_a/test.txt: /user_a/test.txt can't be moved from an encryption zone.

解决

删除的时候加上-skipTrash。

[user_a@BJ-PRESTO-TEST-100093 ~]$ hdfs dfs -rm -skipTrash /user_a/test.txtDeleted /user_a/test.txt

---------------------END---------------------

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 京东技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档