凌云的博客

行胜于言

HDFS 部署 Kerberos 认证

分类:hadoop| 发布时间:2018-12-03 11:18:00


概述

本文主要描述了如何在一个 HDFS 集群中部署 Kerberos 认证,假设集群中有以下节点, 所有节点都是使用 Ubuntu 14.04 系统:

  • namenode: 作为 namenode
  • datanode1:数据节点
  • datanode2:数据节点

为了部署 Kerberos 认证,需要添加一台服务器用于部署 KDC(key distribution center), 部署 Kerberos 认证后整个集群有如下节点:

  • namenode: 作为 namenode
  • datanode1:数据节点
  • datanode2:数据节点
  • KDC:作为 KDC 以及 admin-server

安装 KDC

  • 首先使用如下命令安装 KDC 和 admin-server
$ sudo apt-get install krb5-kdc krb5-admin-server
  • 安装过程中,会提示配置默认 realm(比如:HADOOPKRB),可用以下命令重新配置
$ sudo dpkg-reconfigure krb5-config

在本文中以默认 realm 为 HADOOPKRB 为例,如果你配置了不同的默认 realm 需要作相应修改

  • 创建 KRB5 数据库和管理员密码
$ sudo krb5_newrealm
  • 创建相应的 Principal
    • 创建 hdfs Principal
    $ sudo kadmin.local -q "addprinc -randkey hdfs/namenode@HADOOPKRB"
    $ sudo kadmin.local -q "addprinc -randkey hdfs/datanode1@HADOOPKRB"
    $ sudo kadmin.local -q "addprinc -randkey hdfs/datanode2@HADOOPKRB"
    
    • 创建 HTTP Principal
    $ sudo kadmin.local -q "addprinc -randkey HTTP/namenode@HADOOPKRB"
    $ sudo kadmin.local -q "addprinc -randkey HTTP/datanode1@HADOOPKRB"
    $ sudo kadmin.local -q "addprinc -randkey HTTP/datanode2@HADOOPKRB"
    

这里一共为每个 HDFS 节点创建了两条 Principal,一个用于 HDFS 协议,一个用于 HTTP 协议。 在这里 -randkey 标志表示 kadmin 为 Principal 创建一个随机密码而不是由用户设置密码。 之所以在这里使用这个标志,是因为此 Principal 不需要用户交互。

  • 创建客户端 Principal
$ sudo kadmin.local
kadmin.local addprinc hdfs/client@HADOOPKRB

这里创建的 Principal 主要用于客户端登录用。

  • 查看已有的 Principal
$ kadmin.local -q "listprincs"
  • 创建 keytab 文件,keytab 保存了一个或多个 principals 的长期密钥。通过 keytab 文件可以实现无交互的 Kerberos 认证。
  • 创建包含所有节点 hdfs principal 的 hdfs keytab
    $ sudo kadmin.local -q "xst -norandkey -k hdfs.keytab hdfs/namenode@HADOOPKRB hdfs/datanode1@HADOOPKRB hdfs/datanode2@HADOOPKRB"
    
  • 创建包含所有节点 HTTP principal 的 HTTP keytab
$ sudo kadmin.local -q "xst -norandkey -k http.keytab HTTP/namenode@HADOOPKRB HTTP/datanode1@HADOOPKRB HTTP/datanode2@HADOOPKRB"

安装 krb5 客户端

  • 在所有 KDC 外的节点安装 krb5 客户端
$ sudo apt-get install krb5-user krb5-config
  • 将上一步创建的 keytab 文件复制到各个节点

配置 HDFS

公共配置

  • 修改所有节点的 core-site.xml
<property>
    <name>hadoop.security.auth_to_local</name>
    <value>
        RULE:[2:$1@$0](.*@HADOOPKRB)s/.*/hadoop/
        DEFAULT
    </value>
</property>
<property>
    <name>hadoop.security.authentication</name>
    <value>kerberos</value>
</property>
  • hadoop.security.auth_to_local 映射 Kerberos 的 principals 到本地用户, 这里将所有的 HADOOPKRB realm 的 principals 映射为本地的 hadoop 用户, 你可能需要根据实际情况进行修改。这里是映射规则的说明 Configuring the Mapping from Kerberos Principals to Short Names
  • hadoop.security.authentication 将认证方式设置为 kerberos
  • 修改所有节点的 hdfs-site.xml
<property>
    <name>dfs.block.access.token.enable</name>
    <value>true</value>
</property>

NameNode

  • hdfs-site.xml
<property>
    <name>dfs.namenode.kerberos.principal</name>
    <value>hdfs/_HOST@HADOOPKRB</value>
</property>
<property>
    <name>dfs.namenode.keytab.file</name>
    <value>/etc/hadoop/hdfs.keytab</value>
</property>
<property>
    <name>dfs.namenode.kerberos.internal.spnego.principal</name>
    <value>HTTP/_HOST@HADOOPKRB</value>
</property>
<property>
    <name>dfs.web.authentication.kerberos.keytab</name>
    <value>/etc/hadoop/http.keytab</value>
</property>
<property>
    <name>dfs.web.authentication.kerberos.principal</name>
    <value>HTTP/_HOST@HADOOPKRB</value>
</property>
  • 需要将 _HOST 修改为具体的主机名
  • hdfs.keytab 和 http.keytab 的路径请根据实际情况进行修改

Secondary NameNode

  • hdfs-site.xml
<property>
    <name>dfs.secondary.namenode.kerberos.principal</name>
    <value>hdfs/_HOST@HADOOPKRB</value>
</property>
<property>
    <name>dfs.secondary.namenode.keytab.file</name>
    <value>/etc/hadoop/hdfs.keytab</value>
</property>
<property>
    <name>dfs.secondary.namenode.kerberos.internal.spnego.principal</name>
    <value>HTTP/_HOST@HADOOPKRB</value>
</property>
<property>
    <name>dfs.secondary.web.authentication.kerberos.keytab</name>
    <value>/etc/hadoop/http.keytab</value>
</property>
<property>
    <name>dfs.secondary.web.authentication.kerberos.principal</name>
    <value>HTTP/_HOST@HADOOPKRB</value>
</property>
  • 需要将 _HOST 修改为具体的主机名

DataNode

在安全模式下 DataNode 有两种方式认证本身,一种是通过 SASL,另外一种是通过使用特权端口的方式。 这里使用通过特权端口的方式。

  • 安装 jsvc
$ sudo apt-get install jsvc
  • 修改 hdfs-site.xml
<property>
    <name>dfs.datanode.kerberos.principal</name>
    <value>hdfs/_HOST@HADOOPKRB</value>
</property>
<property>
    <name>dfs.datanode.keytab.file</name>
    <value>/etc/hadoop/hdfs.keytab</value>
</property>
<property>
    <name>dfs.datanode.address</name>
    <value>0.0.0.0:578</value>
</property>
<property>
    <name>dfs.datanode.http.address</name>
    <value>0.0.0.0:579</value>
</property>
  • 需要将 _HOST 替换为具体的主机名
  • dfs.datanode.address 和 dfs.datanode.http.address 修改为小于 1024 的未使用的值即可
  • hdfs.keytab 的路径需要根据具体情况进行修改
  • 修改 hadoop-env.sh
export HDFS_DATANODE_SECURE_USER=hadoop
export JSVC_HOME=/usr/bin
  • 如果你使用的是 3.0 以下的 HDFS 需要将 HDFS_DATANODE_SECURE_USER 改为 HADOOP_SECURE_DN_USER

通过特权端口来认证 DataNode 的方式需要首先使用 root 用户启动 DataNode 的进程监听特权端口然后再切换到非 root 用户。 为了能在 NameNode 使用 start-dfs.sh 能启动各个 DataNode 的进程需要配置 NameNode 到各个 DataNode 的 root 用户的 SSH 认证。 关于 SSH 密钥认证的配置可以查看这里:How To Configure SSH Key-Based Authentication on a Linux Server

这里给出一个例子(/home/hadoop/.ssh/config):

host datanode1
    user root
    IdentityFile /home/hadoop/.ssh/node1_id_rsa

host datanode2
    user root
    IdentityFile /home/hadoop/.ssh/node2_id_rsa

测试

  • 启动 HDFS 集群 在 NameNode 节点调用:
$ start-dfs.sh
  • 测试验证配置是否有效
    • 验证 RPC port
    $ kinit hdfs/client@HADOOPKRB
    $ hdfs dfs -ls /
    $ kdestroy
    $ hdfs dfs -ls /
    
    • 验证 REST port
    $ kinit hdfs/client@HADOOPKRB
    $ hdfs dfs -ls webhdfs://namenode:9000/
    

    端口 9000 需要根据你的实际情况进行修改,可以查看 namenode 的 core-site.xml 中的 fs.default.name 配置项得到当前配置的端口号

    • 遇到问题时,可以开启 debug 模式,如下:
    $ export HADOOP_ROOT_LOGGER=TRACE,console
    $ export HADOOP_OPTS="-Dsun.security.krb5.debug=true"
    $ hdfs dfs -ls /
    

参考