为Hadoop集群开启安全模式,防止集群裸奔被恶意攻击,几乎是生产环境下使用Hadoop集群的一个基本需求。这个配置过程可以说相当复杂,在参考了在线Hadoop in Secure Mode 的官方文档再结合数篇实践博客的基础上,配置的过程依然是相当坎坷。这篇文章是我对自己在实践后,摔过无数跟头的基础上,一些经验的总结,在Hadoop和Kerberos认证方面我并不是老司机,但是力求将配置中一些核心概念的理解和学习呈现出来,希望能帮助后来人少走弯路。
准备工作
这次测试工作是基于三台docker容器,容器操作系统基于开源的CentOS7。
创建Docker测试容器
创建docker 容器的命令:
1 docker run -it --name hadoop01 --hostname hadoop01.esrichina.com --privileged =true --mount source =hdfs_db,target=/home/hdfs_db hadoopbase
使用同样的命令,依次创建hadoop02,hadoop03容器。
其中:
-Hadoop01: Hadoop集群的master主机;
-Hadoop02 和Hadoop03: 数据节点,在集群中扮演slave角色;
配置所有服务器之间能通过域名彼此通信。
对于基于Kerberos的集群认证,最推荐的方式是通过使用DNS配置集群内所有服务器能够正确的域名解析。但是为了简单,我在这里采用通过配置/etc/hosts文件的方式来达到同样的效果。
在三台服务器上执行同样的配置命令:
1 2 3 4 5 6 7 8 9 10 11 [root@hadoop01 ~] 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 hadoop01.esrichina.com hadoop01 172.17.0.3 hadoop02.esrichina.com hadoop02 172.17.0.4 hadoop03.esrichina.com hadoop03 172.17.0.5 hadoop04.esrichina.com hadoop04
安装ssh,配置hadoop master免密登陆自身和节点服务器
配置Hadoop Master 免密验证节点服务器是hadoop集群配置中非常重要的步骤。为了缩短文章的长度,将重点放到后面的安全配置部分。关于如何配置ssh免密登陆,可以参考我之前写的技术文章:《配置Linux集群服务器间ssh免密码登陆 》。
搭建Kerberos认证环境
Kerberos认证环境搭建本身也是相当复杂的过程,具体的配置过程可以参考我之前写的另一篇文章:《Kerberos 简单配置攻略 》。
为Hadoop开启基于Kerberos的服务级认证时,终端用户在和hadoop服务交互前必须要认证自己。最简单的方式是使用kerberos kinit 命令交互式实现认证。如果是编程实现认证那可以基于Kerberos keytab文件来验证,因为使用kinit交互式登录就不方便了,因此在后续的配置中hadoop集群中进程间是基于keytab来认证的。
Hadoop安全配置过程
为Hadoop 守护进程创建本地用户及分配权限
1)创建本地用户
据官方文档建议,要配置HDFS和YARN进程以及MapReduce JobHistory Server以不同的Unix用户运行,但是可以共用同一个组。之所以这样要求,是为了能通过不同用户控制权限。
在三台服务器上分别创建Hadoop进程需要的用户:
1 2 3 [root@hadoop01 ~]# adduser hdfs -g hadoop -p hdfs [root@hadoop01 ~]# adduser yarn -g hadoop -p yarn [root@hadoop01 ~]# adduser mapred -g hadoop -p mapred
2)为HDFS和本地文件系统路径设置权限
下面的表格是hadoop在线文档中推荐的权限设置,需要在所有节点中执行相应的权限配置。local目录的配置我们放在这个环节配置。hdfs目录的权限配置我会放到hadoop服务启动后再来配置。
Filesystem
Path
User:Group
Permissions
local
dfs.namenode.name.dir
hdfs:hadoop
drwx------
local
dfs.datanode.data.dir
hdfs:hadoop
drwx------
local
$HADOOP_LOG_DIR
hdfs:hadoop
drwxrwxr-x
local
$YARN_LOG_DIR
yarn:hadoop
drwxrwxr-x
local
yarn.nodemanager.local-dirs
yarn:hadoop
drwxr-xr-x
local
yarn.nodemanager.log-dirs
yarn:hadoop
drwxr-xr-x
local
container-executor
root:hadoop
---Sr-s---
local
conf/container-executor.cfg
root:hadoop
-r--------
hdfs
/
hdfs:hadoop
drwxr-xr-x
hdfs
/tmp
hdfs:hadoop
drwxrwxrwxt
hdfs
/user
hdfs:hadoop
drwxr-xr-x
hdfs
yarn.nodemanager.remote-app-log-dir
yarn:hadoop
drwxrwxrwxt
hdfs
mapreduce.jobhistory.intermediate-done-dir
mapred:hadoop
drwxrwxrwxt
hdfs
mapreduce.jobhistory.done-dir
mapred:hadoop
drwxr-x---
1 2 3 [root@hadoop01 hdfs]# mkdir -p /hadoop/hdfs/namenode [root@hadoop01 hdfs]# mkdir -p /hadoop/hdfs/datanode [root@hadoop01 hdfs]# mkdir -p /hadoop/hdfs/log
1 2 3 [root@hadoop01 hdfs]# chown hdfs:hadoop /hadoop/hdfs/namenode [root@hadoop01 hdfs]# chown hdfs:hadoop /hadoop/hdfs/datanode [root@hadoop01 hdfs]# chown hdfs:hadoop /hadoop/hdfs/log
1 2 3 [root@hadoop01 hdfs]# chmod -R 700 /hadoop/hdfs/datanode [root@hadoop01 hdfs]# chmod -R 700 /hadoop/hdfs/namenode [root@hadoop01 hdfs]# chmod -R 775 /hadoop/hdfs/log
1 2 3 [root@hadoop01 yarn]# mkdir -p /hadoop/yarn/yarn_log [root@hadoop01 ~]# mkdir -p /hadoop/yarn/local [root@hadoop01 ~]# mkdir -p /hadoop/yarn/log
1 2 3 [root@hadoop01 yarn]# chown yarn:hadoop /hadoop/yarn/yarn_log [root@hadoop01 yarn]# chown yarn:hadoop /hadoop/yarn/local [root@hadoop01 yarn]# chown yarn:hadoop /hadoop/yarn/log
1 2 3 [root@hadoop01 yarn]# chmod 775 /hadoop/yarn/yarn_log [root@hadoop01 yarn]# chmod 755 /hadoop/yarn/local [root@hadoop01 yarn]# chmod 755 /hadoop/yarn/log
修改container-executor和 container-executor.cfg权限,这步必须如此设置,否则后面nodemanager会无法启动。
1 2 3 4 5 6 7 8 9 10 11 12 [root@hadoop01 bin]# chown root:hadoop /home/hadoop/hadoop-2.8 /bin/container -executor [root@hadoop01 bin]# chmod 6050 /home/hadoop/hadoop-2.8 /bin/container -executor [root@hadoop01 bin]# cp -f /home/hadoop/hadoop-2.8 /etc/hadoop/container -executor.cfg /etc/ [root@hadoop01 ~]# chown root:hadoop /etc/container -executor.cfg [root@hadoop01 ~]# vim /etc/container -executor.cfg yarn.nodemanager.local-dirs=/hadoop/yarn/local yarn.nodemanager.log -dirs=/hadoop/yarn/log yarn.nodemanager.linux-container -executor.group = hadoop banned.users=hdfs,yarn,mapred min .user.id=1000 [root@hadoop01 ~]# chmod 400 /etc/container -executor.cfg
对于container-executor和container-executor.cfg的配置有点儿复杂,由于诸多限定,可执行文件container-executor需要重新编译以满足上述权限设定。container-executor.cfg配置文件的路径是在重新编译container-executor时,硬编码到程序中的,这个默认目录是/etc/container-executor.cfg 。如果不想入坑太深,请严格参照上述配置。
上述步骤需要在各台服务器执行。另外,配置hdfs权限需要在后续集群配置完成,启动hadoop后来执行操作,因此hdfs配置步骤我们放到后面执行。
创建principals 和 keytab文件
Kerberos principal作为Kerberos安全系统的身份标识,Kerberos会给它分配tickets以便他们能访问基于Kerberos安全的Hadoop服务。对于Hadoop来说,每个Hadoop服务实例都需要配置它的principal和keytab文件位置。通常服务principal的配置格式为username/fully.qualified.domain.name@YOUR-REALM.COM。
为了简化配置,Hadoop允许通过“_HOST”通配符来简化配置具体的hostname值。理解这一点非常重要,因为实际运行时进程会将"_HOST"替换为服务器实际的全域名。这个特性对于批量部署上千台服务器组成的Hadoop集群就非常非常重要了,因为我们可以使用同样一套配置文件适配所有的服务器,运行时又可以被进程自动解析为各自服务器的principal。
创建principal和keytab的命令:
1 2 3 4 5 6 7 8 9 [root@hadoop01 hadoop]# kadmin.local *1 Authenticating as principal makl/admin@ESRICHINA.COM with password. kadmin.local: addprinc -randkey nn/hadoop01.esrichina.com@ESRICHINA.COM *2 WARNING: no policy specified for nn/hadoop01.esrichina.com@ESRICHINA.COM; defaulting to no policy Principal "nn/hadoop01.esrichina.com@ESRICHINA.COM" created. kadmin.local: ktadd -k /etc/security/keytab/nn.service.keytab nn/hadoop01.esrichina.com@ESRICHINA.COM *3 Entry for principal nn/hadoop01.esrichina.com@ESRICHINA.COM with kvno 2, encryption type arcfour-hmac added to keytab WRFILE:/etc/security/keytab/nn.service.keytab. Entry for principal nn/hadoop01.esrichina.com@ESRICHINA.COM with kvno 2, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/security/keytab/nn.service.keytab. Entry for principal nn/hadoop01.esrichina.com@ESRICHINA.COM with kvno 2, encryption type des-cbc-crc added to keytab WRFILE:/etc/security/keytab/nn.service.keytab.
*1: 我的KDC部署在hadoop01服务器上,因此我可以通过kadmin.local 登录kerberos 管理器。当然你也可以使用kadmin来登录kerberos管理器。
*2: addprinc 命令用于创建principal,-randkey代表生成随机密码。因为进程间要通过keytab密钥表来认证,所以手动创建密码意义不大,这种方式简化了principal的创建过程。
*3: ktadd命令为principal创建自动校验的密钥表。-k 参数,后面需要指定keytab保存的目录,最后一项nn/hadoop01.esrichina.com@ESRICHINA.COM 代表需要添加到密钥表的用户principal。
上面的例子演示了为NameNode创建principal,并同时生成keytab的过程。这个keytab非常重要,它相当于通过Kerberos认证的身份令牌,所以只应当在需要验证的服务器上出现,而不是在整个集群内随意分发。每个服务创建独立的principal虽然麻烦,但是有利于:
这确保了如果集群中某一台DataNode被攻破,不会累及其它服务器。
如果多个DataNodes使用相同的principal并且同时连接NameNode, 如果Kerberos认证机出现了使用相同时间戳的情况,那认证就可能因为重复请求被拒绝,从而出现认证失败。
使用相同的逻辑为以下服务创建principals和keytabs
Service
Component
Mandatory Principal Name
Mandatory Keytab File Name
HDFS
NameNode
nn/hadoop01.esrichina.com@ESRICHINA.COM
nn.service.keytab
HDFS
NameNode HTTP
HTTP/hadoop01.esrichina.com@ESRICHINA.COM
spnego.service.keytab
HDFS
SecondaryNameNode
sn/hadoop01.esrichina.com@ESRICHINA.COM
sn.service.keytab
HDFS
SecondaryNameNode HTTP
HTTP/hadoop01.esrichina.com@ESRICHINA.COM
spnego.service.keytab
HDFS
DataNode
dn/hadoop02.esrichina.com@ESRICHINA.COM
dn.service.keytab
HDFS
DataNode
dn/hadoop03.esrichina.com@ESRICHINA.COM
dn.service.keytab
MR2
History Server
jhs/hadoop01.esrichina.com@ESRICHINA.COM
jhs.service.keytab
MR2
History Server HTTP
HTTP/hadoop01.esrichina.com@ESRICHINA.COM
spnego.service.keytab
YARN
ResourceManager
rm/hadoop01.esrichina.com@ESRICHINA.COM
rm.service.keytab
YARN
NodeManager
nm/hadoop02.esrichina.com@ESRICHINA.COM
nm.service.keytab
YARN
NodeManager
nm/hadoop03.esrichina.com@ESRICHINA.COM
nm.service.keytab
YARN
Timeline Server
tl/hadoop01.esrichina.com@ESRICHINA.COM
tl.service.keytab
⚠️:HTTP principal必须是HTTP/fully.qualified.domain.name@YOUR-REALM.COM格式。principal的第一部分必须是“HTTP”。 这个格式对于SPNEGO的HTTP principals是标准格式并且被硬编码到Hadoop中。
开启Hadoop安全并配置principal到本地用户的映射
这部分内容是Hadoop集群通用配置过程,具体是针对core-site.xml文件进行配置。
1 2 [root@hadoop01 hadoop]# cd /home/hadoop/hadoop-2.8/etc/hadoop [root@hadoop01 hadoop]# vim core-site.xml
1 2 3 4 5 <property > <name > fs.defaultFS</name > <value > hdfs://hadoop01.esrichina.com:9000</value > </property >
1 2 3 4 5 6 7 8 9 10 11 <property > <name > hadoop.security.authorization</name > <value > true</value > <description > Set the authentication for the cluster.Valid values are: simple or kerberos.</description > </property > <property > <name > hadoop.security.authentication</name > <value > kerberos</value > <description > Enable authentication for different protocols.</description > </property >
Hadoop通过规则系统来创建服务principals到他们相关的UNIX用户的映射。默认规则是提取principal name的第一部分作为系统用户,例如默认规则映射principal “host/full.qualified.domain.name@REALM.TLD” 为系统用户“host”。但是大多数情况默认规则都不满足需要,所以需要自定义映射规则。
映射规则语法:
“RULE:[2:$1@$0](nn/.*@.*ESRICHINA.COM )s/.*/hdfs/”
[2:$1@$0]: 这部分中"2"代表这个principal除了域(realm)之外包含两个组成部分。在这个模式中$1代表第一部分,$0代表realm, $2代表第二部分。
(nn/.*@.*ESRICHINA.COM ):过滤部分,所有匹配第一组成部分为nn, realm结尾为ESRICHINA.COM的principals
s/.*/hdfs/: 这部分是sed规则,翻译正则为修复字符串
具体配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!-- Mapping from Kerberos principals to OS user accounts --> <property> <name>hadoop.security.auth_to_local</name> <value> RULE:[2 :$1 @$0](nn/.*@.*ESRICHINA.COM)s/ .*/hdfs/ RULE:[2 :$1 @$0](sn/.*@.*ESRICHINA.COM)s/ .*/hdfs/ RULE:[2 :$1 @$0](dn/.*@.*ESRICHINA.COM)s/ .*/hdfs/ RULE:[2 :$1 @$0](nm/.*@.*ESRICHINA.COM)s/ .*/yarn/ RULE:[2 :$1 @$0](rm/.*@.*ESRICHINA.COM)s/ .*/yarn/ RULE:[2 :$1 @$0](tl/.*@.*ESRICHINA.COM)s/ .*/yarn/ RULE:[2 :$1 @$0](jhs/.*@.*ESRICHINA.COM)s/ .*/mapred/ RULE:[2 :$1 @$0](Http/.*@.*ESRICHINA.COM)s/ .*/hdfs/ DEFAULT </value> <description> The mapping from kerberos principal names to local OS user names. </description> </property>
⚠️:千万别忘了Value值中的DEFAULT配置。
完整版core-site.xml 配置文件样例下载
配置HDFS安全
这部分内容是为HDFS开启安全,具体是针对hdfs-site.xml文件进行配置
通过vim命令打开hdfs-site.xml文件。
1 [root@hadoop01 hadoop]# vim hdfs-site.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 <property > <name > dfs.block.access.token.enable</name > <value > true</value > </property > <property > <name > dfs.namenode.name.dir</name > <value > /hadoop/hdfs/namenode</value > </property > <property > <name > dfs.datanode.data.dir</name > <value > /hadoop/hdfs/datanode</value > </property >
1 2 3 4 5 6 7 8 9 10 11 12 13 <property > <name > dfs.namenode.kerberos.principal</name > <value > nn/_HOST@ESRICHINA.COM</value > </property > <property > <name > dfs.namenode.keytab.file</name > <value > /etc/security/keytab/nn.service.keytab</value > </property > <property > <name > dfs.namenode.kerberos.internal.spnego.principal</name > <value > HTTP/_HOST@ESRICHINA.COM</value > </property >
1 2 3 4 5 6 7 8 9 10 11 12 13 <property > <name > dfs.secondary.namenode.kerberos.principal</name > <value > sn/_HOST@ESRICHINA.COM</value > </property > <property > <name > dfs.secondary.namenode.keytab.file</name > <value > /etc/security/keytab/sn.service.keytab</value > </property > <property > <name > dfs.secondary.namenode.kerberos.internal.spnego.principal</name > <value > HTTP/_HOST@ESRICHINA.COM</value > </property >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <property > <name > dfs.datanode.kerberos.principal</name > <value > dn/_HOST@ESRICHINA.COM</value > </property > <property > <name > dfs.datanode.keytab.file</name > <value > /etc/security/keytab/dn.service.keytab</value > </property > <property > <name > dfs.datanode.data.dir.perm</name > <value > 700</value > </property > <property > <name > dfs.datanode.address</name > <value > 0.0.0.0:61004</value > </property > <property > <name > dfs.datanode.http.address</name > <value > 0.0.0.0:61006</value > </property >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <property > <name > dfs.http.policy</name > <value > HTTPS_ONLY</value > </property > <property > <name > dfs.data.transfer.protection</name > <value > integrity</value > </property > <property > <name > dfs.https.port</name > <value > 50470</value > </property > <property > <name > dfs.https.address</name > <value > hadoop01.esrichina.com:50470</value > </property > <property > <name > dfs.webhdfs.enabled</name > <value > true</value > </property > <property > <name > dfs.web.authentication.kerberos.principal</name > <value > HTTP/_HOST@ESRICHINA.COM</value > </property > <property > <name > dfs.web.authentication.kerberos.keytab</name > <value > /etc/security/keytab/spnego.service.keytab</value > </property > <property > <name > dfs.permissions.supergroup</name > <value > hdfs</value > <description > The name of the group of super-users.</description > </property > </configuration >
我们能不能偷懒基于HTTP通信,省略证书的繁复配置?答案是No。Hadoop安全模式要求集群中服务器之间通信需要基于HTTPS。接下来我们就开始生成密钥和证书配置支持HTTPS。
这部分配置需要用到openssl,如果你没有装,那使用下面的命令先安装openssl.
安装openssl:
1 [root@hadoop01 hadoop]# yum install openssl
生成CA根密钥和根证书:
1 [root@hadoop01 hadoop]# openssl req -new -x509 -keyout hd_ca_key -out hd_ca_cert -days 9999 -subj '/C=CN/ST=beijing/L=beijing/O=hadoop01.esrichina.com/OU=security/CN=esrichina.com'
注意:O=hadoop01.esrichina.com 这个值中需要替换为CA服务器全域名。
将上述生成的CA根密钥和根证书分发到所有服务器,然后在每台服务器上继续执行如下命令生成证书库:
1 2 3 4 5 [root@hadoop01 certTest]# keytool -keystore keystore -alias localhost -validity 9999 -genkey -keyalg RSA -keysize 2048 -dname "CN=hadoop01.esrichina.com, OU=esrichina, O=esrichina, L=beijing, ST=beijing, C=CN" [root@hadoop01 certTest]# keytool -keystore truststore -alias CARoot -import -file hd_ca_cert [root@hadoop01 certTest]# keytool -certreq -alias localhost -keystore keystore -file cert [root@hadoop01 certTest]# keytool -keystore keystore -alias CARoot -import -file hd_ca_cert [root@hadoop01 certTest]# keytool -keystore keystore -alias localhost -import -file cert_signed
测试中所有涉及设置密码的地方,我都使用了“123456”为密码。
配置hadoop ssl-server.xml和ssl-client.xml:
这两个文件可以通过ssl-client.xml.example和ssl-server.xml.example 模版文件生成,生成后参考如下配置:
ssl-server.xml需要手动配置的片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <property> <name> ssl.server.truststore.location</name> <value> /home/ hadoop/hadoop-2.8 /etc/ hadoop/truststore</value> <description> Truststore to be used by NN and DN. Must be specified. </description> </property> <property> <name> ssl.server.truststore.password</name> <value> 123456 </value> <description> Optional. Default value is "" . </description> </property> <property> <name> ssl.server.keystore.location</name> <value> /home/ hadoop/hadoop-2.8 /etc/ hadoop/keystore</value> <description> Keystore to be used by NN and DN. Must be specified. </description> </property> <property> <name> ssl.server.keystore.password</name> <value> 123456 </value> <description> Must be specified. </description> </property> <property> <name> ssl.server.keystore.keypassword</name> <value> 123456 </value> <description> Must be specified. </description> </property>
ssl-client.xml需要手动配置的片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <property> <name> ssl.client.truststore.location</name> <value> /home/ hadoop/hadoop-2.8 /etc/ hadoop/truststore</value> <description> Truststore to be used by clients like distcp. Must be specified. </description> </property> <property> <name> ssl.client.truststore.password</name> <value> 123456 </value> <description> Optional. Default value is "" . </description> </property> <property> <name> ssl.client.keystore.location</name> <value> /home/ hadoop/hadoop-2.8 /etc/ hadoop/keystore</value> <description> Keystore to be used by clients like distcp. Must be specified. </description> </property> <property> <name> ssl.client.keystore.password</name> <value> 123456 </value> <description> Optional. Default value is "" . </description> </property> <property> <name> ssl.client.keystore.keypassword</name> <value> 123456 </value> <description> Optional. Default value is "" . </description> </property>
完整版ssl-server.xml 配置文件样例下载。
完整版ssl-client.xml 配置文件样例下载。
完整版hdfs-site.xml 配置文件样例下载。
配置MapReduce安全
1 2 3 4 5 6 7 8 9 10 11 12 <property> <name> mapreduce.framework.name</name> <value> yarn</value> </property> <property> <name> mapreduce.jobhistory.intermediate-done-dir</name> <value> /mr-history/ tmp</value> </property> <property> <name> mapreduce.jobhistory.done-dir</name> <value> /mr-history/ done</value> </property>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <property > <name > mapreduce.jobhistory.address</name > <value > hadoop01:10020</value > </property > <property > <name > mapreduce.jobhistory.webapp.address</name > <value > hadoop01:19888</value > </property > <property > <name > mapreduce.jobhistory.keytab</name > <value > /etc/security/keytab/jhs.service.keytab</value > </property > <property > <name > mapreduce.jobhistory.principal</name > <value > jhs/_HOST@ESRICHINA.COM</value > </property >
1 2 3 4 5 6 7 8 9 10 11 12 13 <property > <name > mapreduce.jobhistory.webapp.address</name > <value > hadoop01:19888</value > </property > <property > <name > mapreduce.jobhistory.webapp.spnego-keytab-file</name > <value > /etc/security/spnego.service.keytab</value > </property > <property > <name > mapreduce.jobhistory.webapp.spnego-principal</name > <value > HTTP/_HOST@ESRICHINA.COM</value > </property >
1 2 3 4 5 6 <property > <name > mapreduce.jobhistory.http.policy</name > <value > HTTPS_ONLY</value > </property > </configuration >
完整版mapred-site.xml 配置文件样例下载。
配置Yarn安全
1 2 3 4 5 6 7 8 9 10 11 12 13 <property > <name > yarn.nodemanager.local-dirs</name > <value > /hadoop/yarn/local</value > </property > <property > <name > yarn.nodemanager.log-dirs</name > <value > /hadoop/yarn/log</value > </property > <property > <name > yarn.nodemanager.remote-app-log-dir</name > <value > /logs</value > </property >
1 2 3 4 5 6 7 8 9 10 11 12 <property> <name> yarn.resourcemanager.principal</name> <value> rm/_HOST@ESRICHINA.COM</value> </property> <property> <name> yarn.resourcemanager.keytab</name> <value> /etc/ security/keytab/ rm.service.keytab</value> </property> <property> <name> yarn.resourcemanager.webapp.delegation-token-auth-filter.enabled</name> <value> true</value> </property>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <property > <name > yarn.nodemanager.principal</name > <value > nm/_HOST@ESRICHINA.COM</value > </property > <property > <name > yarn.nodemanager.keytab</name > <value > /etc/security/keytab/nm.service.keytab</value > </property > <property > <name > yarn.nodemanager.container-executor.class</name > <value > org.apache.hadoop.yarn.server.nodemanager.LinuxContainerExecutor</value > </property > <property > <name > yarn.nodemanager.linux-container-executor.path</name > <value > /home/hadoop/hadoop-2.8/bin/container-executor</value > </property > <property > <name > yarn.nodemanager.linux-container-executor.group</name > <value > hadoop</value > </property >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <property > <name > yarn.timeline-service.principal</name > <value > tl/_HOST@ESRICHINA.COM</value > </property > <property > <name > yarn.timeline-service.keytab</name > <value > /etc/security/keytab/tl.service.keytab</value > </property > <property > <name > yarn.timeline-service.http-authentication.type</name > <value > kerberos</value > </property > <property > <name > yarn.timeline-service.http-authentication.kerberos.principal</name > <value > HTTP/_HOST@ESRICHINA.COM</value > </property > <property > <name > yarn.timeline-service.http-authentication.kerberos.keytab</name > <value > /etc/security/keytab/spnego.service.keytab</value > </property >
1 2 3 4 5 6 <property > <name > yarn.http.policy</name > <value > HTTPS_ONLY</value > </property > </configuration >
完整版yarn-site.xml 配置文件样例下载。
配置container-executor.cfg
1 2 3 4 5 6 7 8 [root@hadoop01 ~]# chmod 777 /etc/container -executor.cfg [root@hadoop01 ~]# vim /etc/container -executor.cfg yarn.nodemanager.local-dirs=/hadoop/yarn/local yarn.nodemanager.log -dirs=/hadoop/yarn/log yarn.nodemanager.linux-container -executor.group =hadoop banned.users=hdfs,yarn,mapred,bin min .user.id=1000 [root@hadoop01 ~]# chmod 400 /etc/container -executor.cfg
完整版container-executor.cfg 配置文件和编译好的container-executor 样例下载。
Hadoop集群部署
配置slave文件
1 2 3 [root@hadoop01 hadoop] hadoop02 hadoop03
在这次测试中hadoop01服务器是作为整个集群的Master角色,hadoop02和hadoop03是数据节点,作为slave角色,因此在slaves文件中只添加hadoop02,hadoop03即可。
配置Java环境变量和日志路径
在分发介质之前,还有一步重要的工作,就是要为hadoop配置环境变量,其中涉及到hadoop-env.sh 、mapred-env.sh 、yarn-env.sh 。具体配置过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 [root@hadoop01 hadoop]# vim hadoop-env.sh export JAVA_HOME =/home/jdk1.8.0_65export HADOOP_CONF_DIR =/hadoop/etc/hadoopexport HADOOP_LOG_DIR =/hadoop/hdfs/log[root@hadoop01 hadoop]# vim yarn-env.sh export JAVA_HOME =/home/jdk1.8.0_65export YARN_LOG_DIR =/hadoop/yarn/yarn_log[root@hadoop01 hadoop]# vim mapred-env.sh export JAVA_HOME =/home/jdk1.8.0_65
格式化hdfs
1 2 [root@hadoop 01 hadoop] cd ../../ bin [root@hadoop 01 bin] ./hadoop namenode -format
集群内部署keytab文件
分发之前创建的keytab文件到集群内其它服务器上,具体到这次测试中是要将文件分发到hadoop02、hadoop03服务器上。在所有服务器上keytab的保存目录要和配置文件中配置的目录保持一致。
1 2 [root@hadoop01 hadoop] [root@hadoop01 hadoop]
集群内部署Hadoop
保持和hadoop01同样的目录结构将包含之前在hadoop01上修改过配置文件的hadoop安装文件拷贝到hadoop02、hadoop03服务器上。
1 2 [root@hadoop01 hadoop-2.8 ] [root@hadoop01 hadoop-2.8 ]
启动服务
启动服务需要切换到hdfs用户下,按照之前的用户配置,我们以hdfs用户启动服务。
1 2 3 4 [root@hadoop01 bin]# su hdfs [hdfs@hadoop01 bin]# cd /home/hadoop/hadoop-2.8/sbin [hdfs@hadoop01 sbin]# ./start-all.sh
配置hdfs权限
配置hdfs需要以kerberos principal用户登陆到hdfs,我们通过kinit命令初始化登陆用户。
以nn/hadoop01.esrichina.com@ESRICHINA.COM用户登陆
1 2 3 4 5 [root@hadoop01 bin]# ./hadoop fs -mkdir /tmp [root@hadoop01 bin]# ./hadoop fs -mkdir /user [root@hadoop01 bin]# ./hadoop fs -mkdir -p /logs [root@hadoop01 bin]# ./hadoop fs -mkdir -p /mr-history/tmp [root@hadoop01 bin]# ./hadoop fs -mkdir -p /mr-history/done
1 2 3 4 5 6 [root@hadoop01 bin]# ./hadoop fs -chown hdfs:hadoop / [root@hadoop01 bin]# ./hadoop fs -chown hdfs:hadoop /tmp [root@hadoop01 bin]# ./hadoop fs -chown hdfs:hadoop /user [root@hadoop01 bin]# ./hadoop fs -chown yarn:hadoop /logs [root@hadoop01 bin]# ./hadoop fs -chown mapred:hadoop /mr-history/tmp [root@hadoop01 bin]# ./hadoop fs -chown mapred:hadoop /mr-history/done
1 2 3 4 5 6 [root@hadoop01 bin]# ./hadoop fs -chmod 755 / [root@hadoop01 bin]# ./hadoop fs -chmod 777 /tmp [root@hadoop01 bin]# ./hadoop fs -chmod 755 /user [root@hadoop01 bin]# ./hadoop fs -chmod 777 /logs [root@hadoop01 bin]# ./hadoop fs -chmod 777 /mr-history/tmp [root@hadoop01 bin]# ./hadoop fs -chmod 750 /mr-history/done
1 2 3 4 5 6 7 8 9 10 11 12 [root@hadoop01 bin]# ./hadoop fs -ls / Found 5 items drwxrwxrwx - yarn hadoop 0 2018-01 -23 06:28 /logs drwxr-xr-x - nn hadoop 0 2018-01 -23 06:28 /mr-history drwxrwxrwx - hdfs hadoop 0 2018-01 -23 06:26 /tmp drwxr-xr-x - hdfs hadoop 0 2018-01 -23 06:26 /user drwxr-xr-x - hdfs hadoop 0 2018-01 -22 07:19 /usr [root@hadoop01 bin]# ./hadoop fs -ls /mr-history Found 2 items drwxr-x--- - mapred hadoop 0 2018-01 -23 06:28 /mr-history/done drwxrwxrwx - mapred hadoop 0 2018-01 -23 06:28 /mr-history/tmp
至此整个基于Hadoop集群开启kerberos安全认证的配置工作算是初步完成了,接下来我们检查各服务器节点进程状态来验证配置是否成功。
检验配置成果
检验各服务器节点的相应进程是否都能成功启动,也可以作为检验安全配置是否成功的标准。如果配置正确,你在各服务器节点上会看到如下hadoop进程。
Master节点验证:
1 2 3 4 5 [hdfs@hadoop01 sbin]# jps 3858 NameNode4102 SecondaryNameNode4615 Jps4329 ResourceManager
slave节点验证:
1 2 3 4 5 6 7 8 9 [hdfs@hadoop02 etc]$ jps 20377 NodeManager20491 Jps20237 DataNode[hdfs@hadoop03 etc]$ jps 18633 NodeManager18763 Jps18493 DataNode
如果配置后,在各节点进程的检测中,未看到上述进程,那可以通过hadoop日志来排查错误,日志中会包含报错信息,这些信息可以作为进一步排查问题的线索。
棘手的问题
在整个配置过程中,我碰到最棘手的问题就是hadoop集群启用安全后Node Manager无法启动。经历了九九八十一难后,终于搞定,为了纪念这个深坑,我将解决方案单独总结到另外一篇文章中《理解和配置LinuxContainerExecutor 》。如果你使用的hadoop版本偏早期,那可能要经历更多的波折,了解下面这个关于containerExecutor的bug可能对你有帮助。
make default container-executor.conf.dir be a path relative to the container-executor binary
参考资料:
1 Hadoop in Secure Mode
2 hortonworks:Hadoop Security Guide
3 cloudera : Enabing Kerberos Authentication for Hadoop Using the Command Line
4 IBM configuring YARN container executor