HDFS 集成 Kerberos

2023-05-16

本文主要记录 CDH Hadoop 集群上配置 HDFS 集成 Kerberos 的过程,包括 Kerberos 的安装和 Hadoop 相关配置修改说明。

注意:

下面第一、二部分内容,摘抄自《Hadoop的kerberos的实践部署》,主要是为了对 Hadoop 的认证机制和 Kerberos 认证协议做个简单介绍。在此,对原作者表示感谢。

1. Hadoop 的认证机制

简单来说,没有做 kerberos 认证的 Hadoop,只要有 client 端就能够连接上。而且,通过一个有 root 的权限的内网机器,通过创建对应的 linux 用户,就能够得到 Hadoop 集群上对应的权限。

而实行 Kerberos 后,任意机器的任意用户都必须现在 Kerberos 的 KDC 中有记录,才允许和集群中其它的模块进行通信。

详细介绍请参考 Hadoop安全机制研究

2. Kerberos 认证协议

Kerberos 是一种网络认证协议,其设计目标是通过密钥系统为客户机/服务器应用程序提供强大的认证服务。

使用 Kerberos 时,一个客户端需要经过三个步骤来获取服务:

  • 认证:客户端向认证服务器发送一条报文,并获取一个含时间戳的 Ticket-Granting Ticket(TGT)。
  • 授权:客户端使用 TGT 向 Ticket-Granting Server(TGS)请求一个服务 Ticket。
  • 服务请求:客户端向服务器出示服务 Ticket ,以证实自己的合法性。

为此,Kerberos 需要 The Key Distribution Centers(KDC)来进行认证。KDC 只有一个 Master,可以带多个 slaves 机器。slaves 机器仅进行普通验证。Mater 上做的修改需要自动同步到 slaves。

另外,KDC 需要一个 admin,来进行日常的管理操作。这个 admin 可以通过远程或者本地方式登录。

3. 搭建 Kerberos

3.1 环境#

我们在三个节点的服务器上安装 Kerberos,这三个节点上安装了 hadoop 集群,安装 hadoop 过程见:使用yum安装CDH Hadoop集群。这三个节点机器分布为:cdh1、cdh2、cdh3。

  • 操作系统:CentOs 6.6
  • 运行用户:root

3.2 安装过程#

3.2.1 准备工作#

确认添加主机名解析到 /etc/hosts 文件中。

$ cat /etc/hosts
127.0.0.1       localhost

192.168.56.121 cdh1
192.168.56.122 cdh2
192.168.56.123 cdh3

注意:hostname 请使用小写,要不然在集成 kerberos 时会出现一些错误。

3.2.2 安装 kdc server#

在 KDC (这里是 cdh1 ) 上安装包 krb5、krb5-server 和 krb5-client。

$ yum install krb5-server krb5-libs krb5-auth-dialog krb5-workstation  -y

在其他节点(cdh1、cdh2、cdh3)安装 krb5-devel、krb5-workstation :

$ ssh cdh1 "yum install krb5-devel krb5-workstation -y"
$ ssh cdh2 "yum install krb5-devel krb5-workstation -y"
$ ssh cdh3 "yum install krb5-devel krb5-workstation -y"

3.2.3 修改配置文件#

kdc 服务器涉及到三个配置文件:

/etc/krb5.conf
/var/kerberos/krb5kdc/kdc.conf
/var/kerberos/krb5kdc/kadm5.acl

配置 Kerberos 的一种方法是编辑配置文件 /etc/krb5.conf。默认安装的文件中包含多个示例项。

$ cat /etc/krb5.conf
  [logging]
   default = FILE:/var/log/krb5libs.log
   kdc = FILE:/var/log/krb5kdc.log
   admin_server = FILE:/var/log/kadmind.log

  [libdefaults]
   default_realm = JAVACHEN.COM
   dns_lookup_realm = false
   dns_lookup_kdc = false
   clockskew = 120
   ticket_lifetime = 24h
   renew_lifetime = 7d
   forwardable = true
   renewable = true
   udp_preference_limit = 1
   default_tgs_enctypes = arcfour-hmac
   default_tkt_enctypes = arcfour-hmac

  [realms]
   JAVACHEN.COM = {
    kdc = cdh1:88
    admin_server = cdh1:749
   }

  [domain_realm]
    .javachen.com = JAVACHEN.COM
    www.javachen.com = JAVACHEN.COM

  [kdc]
  profile=/var/kerberos/krb5kdc/kdc.conf

说明:#

  • [logging]:表示 server 端的日志的打印位置
  • [libdefaults]:每种连接的默认配置,需要注意以下几个关键的小配置
    • default_realm = JAVACHEN.COM:设置 Kerberos 应用程序的默认领域。如果您有多个领域,只需向 [realms] 节添加其他的语句。
    • udp_preference_limit= 1:禁止使用 udp 可以防止一个Hadoop中的错误
    • clockskew:时钟偏差是不完全符合主机系统时钟的票据时戳的容差,超过此容差将不接受此票据。通常,将时钟扭斜设置为 300 秒(5 分钟)。这意味着从服务器的角度看,票证的时间戳与它的偏差可以是在前后 5 分钟内。
    • ticket_lifetime: 表明凭证生效的时限,一般为24小时。
    • renew_lifetime: 表明凭证最长可以被延期的时限,一般为一个礼拜。当凭证过期之后,对安全认证的服务的后续访问则会失败。
  • [realms]:列举使用的 realm。
    • kdc:代表要 kdc 的位置。格式是 机器:端口
    • admin_server:代表 admin 的位置。格式是 机器:端口
    • default_domain:代表默认的域名
  • [appdefaults]:可以设定一些针对特定应用的配置,覆盖默认配置。

修改 /var/kerberos/krb5kdc/kdc.conf ,该文件包含 Kerberos 的配置信息。例如,KDC 的位置,Kerbero 的 admin 的realms 等。需要所有使用的 Kerberos 的机器上的配置文件都同步。这里仅列举需要的基本配置。详细介绍参考:krb5conf

$ cat /var/kerberos/krb5kdc/kdc.conf
[kdcdefaults]
 v4_mode = nopreauth
 kdc_ports = 88
 kdc_tcp_ports = 88

[realms]
 JAVACHEN.COM = {
  #master_key_type = aes256-cts
  acl_file = /var/kerberos/krb5kdc/kadm5.acl
  dict_file = /usr/share/dict/words
  admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
  supported_enctypes =  des3-hmac-sha1:normal arcfour-hmac:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal des-cbc-crc:v4 des-cbc-crc:afs3
  max_life = 24h
  max_renewable_life = 10d
  default_principal_flags = +renewable, +forwardable
 }

说明:#

  • JAVACHEN.COM: 是设定的 realms。名字随意。Kerberos 可以支持多个 realms,会增加复杂度。大小写敏感,一般为了识别使用全部大写。这个 realms 跟机器的 host 没有大关系。
  • master_key_type:和 supported_enctypes 默认使用 aes256-cts。由于,JAVA 使用 aes256-cts 验证方式需要安装额外的 jar 包(后面再做说明)。推荐不使用,并且删除 aes256-cts。
  • acl_file:标注了 admin 的用户权限,需要用户自己创建。文件格式是:Kerberos_principal permissions [target_principal] [restrictions]
  • supported_enctypes:支持的校验方式。
  • admin_keytab:KDC 进行校验的 keytab。

关于AES-256加密:

对于使用 centos5. 6及以上的系统,默认使用 AES-256 来加密的。这就需要集群中的所有节点上安装 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy File。

下载的文件是一个 zip 包,解开后,将里面的两个文件放到下面的目录中:$JAVA_HOME/jre/lib/security

为了能够不直接访问 KDC 控制台而从 Kerberos 数据库添加和删除主体,请对 Kerberos 管理服务器指示允许哪些主体执行哪些操作。通过编辑文件 /var/lib/kerberos/krb5kdc/kadm5.acl 完成此操作。ACL(访问控制列表)允许您精确指定特权。

$ cat /var/kerberos/krb5kdc/kadm5.acl
  */admin@JAVACHEN.COM *

3.2.4 同步配置文件#

将 kdc 中的 /etc/krb5.conf 拷贝到集群中其他服务器即可。

$ scp /etc/krb5.conf cdh2:/etc/krb5.conf
$ scp /etc/krb5.conf cdh3:/etc/krb5.conf

请确认集群如果关闭了 selinux。

3.2.5 创建数据库#

在 cdh1 上运行初始化数据库命令。其中 -r 指定对应 realm。

$ kdb5_util create -r JAVACHEN.COM -s

出现 Loading random data 的时候另开个终端执行点消耗CPU的命令如 cat /dev/sda > /dev/urandom 可以加快随机数采集。

该命令会在 /var/kerberos/krb5kdc/ 目录下创建 principal 数据库。

如果遇到数据库已经存在的提示,可以把 /var/kerberos/krb5kdc/ 目录下的 principal 的相关文件都删除掉。默认的数据库名字都是 principal。可以使用 -d 指定数据库名字。

3.2.6 启动服务#

在 cdh1 节点上运行:

$ chkconfig --level 35 krb5kdc on
$ chkconfig --level 35 kadmin on
$ service krb5kdc start
$ service kadmin start

3.2.7 创建 kerberos 管理员#

关于 kerberos 的管理,可以使用 kadmin.local 或 kadmin,至于使用哪个,取决于账户和访问权限:

  • 如果有访问 kdc 服务器的 root 权限,但是没有 kerberos admin 账户,使用 kadmin.local
  • 如果没有访问 kdc 服务器的 root 权限,但是用 kerberos admin 账户,使用 kadmin

在 cdh1 上创建远程管理的管理员:

#手动输入两次密码,这里密码为 root
$ kadmin.local -q "addprinc root/admin"

# 也可以不用手动输入密码
$ echo -e "root\nroot" | kadmin.local -q "addprinc root/admin"

系统会提示输入密码,密码不能为空,且需妥善保存。

3.2.8 测试 kerberos#

以下内容仅仅是为了测试,你可以直接跳到下部分内容。

查看当前的认证用户:

# 查看principals
$ kadmin: list_principals

  # 添加一个新的 principal
  kadmin:  addprinc user1
    WARNING: no policy specified for user1@JAVACHEN.COM; defaulting to no policy
    Enter password for principal "user1@JAVACHEN.COM":
    Re-enter password for principal "user1@JAVACHEN.COM":
    Principal "user1@JAVACHEN.COM" created.

  # 删除 principal
  kadmin:  delprinc user1
    Are you sure you want to delete the principal "user1@JAVACHEN.COM"? (yes/no): yes
    Principal "user1@JAVACHEN.COM" deleted.
    Make sure that you have removed this principal from all ACLs before reusing.

  kadmin: exit

也可以直接通过下面的命令来执行:

# 提示需要输入密码
$ kadmin -p root/admin -q "list_principals"
$ kadmin -p root/admin -q "addprinc user2"
$ kadmin -p root/admin -q "delprinc user2"

# 不用输入密码
$ kadmin.local -q "list_principals"
$ kadmin.local -q "addprinc user2"
$ kadmin.local -q "delprinc user2"

创建一个测试用户 test,密码设置为 test:

$ echo -e "test\ntest" | kadmin.local -q "addprinc test"

获取 test 用户的 ticket:

# 通过用户名和密码进行登录
$ kinit test
Password for test@JAVACHEN.COM:

$ klist  -e
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: test@JAVACHEN.COM

Valid starting     Expires            Service principal
11/07/14 15:29:02  11/08/14 15:29:02  krbtgt/JAVACHEN.COM@JAVACHEN.COM
  renew until 11/17/14 15:29:02, Etype (skey, tkt): AES-128 CTS mode with 96-bit SHA-1 HMAC, AES-128 CTS mode with 96-bit SHA-1 HMAC


Kerberos 4 ticket cache: /tmp/tkt0
klist: You have no tickets cached

销毁该 test 用户的 ticket:

$ kdestroy

$ klist
klist: No credentials cache found (ticket cache FILE:/tmp/krb5cc_0)


Kerberos 4 ticket cache: /tmp/tkt0
klist: You have no tickets cached

更新 ticket:

$ kinit root/admin
  Password for root/admin@JAVACHEN.COM:

$  klist
  Ticket cache: FILE:/tmp/krb5cc_0
  Default principal: root/admin@JAVACHEN.COM

  Valid starting     Expires            Service principal
  11/07/14 15:33:57  11/08/14 15:33:57  krbtgt/JAVACHEN.COM@JAVACHEN.COM
    renew until 11/17/14 15:33:57

  Kerberos 4 ticket cache: /tmp/tkt0
  klist: You have no tickets cached

$ kinit -R

$ klist
  Ticket cache: FILE:/tmp/krb5cc_0
  Default principal: root/admin@JAVACHEN.COM

  Valid starting     Expires            Service principal
  11/07/14 15:34:05  11/08/14 15:34:05  krbtgt/JAVACHEN.COM@JAVACHEN.COM
    renew until 11/17/14 15:33:57

  Kerberos 4 ticket cache: /tmp/tkt0
  klist: You have no tickets cached

抽取密钥并将其储存在本地 keytab 文件 /etc/krb5.keytab 中。这个文件由超级用户拥有,所以您必须是 root 用户才能在 kadmin shell 中执行以下命令:

$ kadmin.local -q "ktadd kadmin/admin"

$ klist -k /etc/krb5.keytab
  Keytab name: FILE:/etc/krb5.keytab
  KVNO Principal
  ---- --------------------------------------------------------------------------
     3 kadmin/admin@LASHOU-INC.COM
     3 kadmin/admin@LASHOU-INC.COM
     3 kadmin/admin@LASHOU-INC.COM
     3 kadmin/admin@LASHOU-INC.COM
     3 kadmin/admin@LASHOU-INC.COM

4. HDFS 上配置 kerberos

4.1 创建认证规则#

在 Kerberos 安全机制里,一个 principal 就是 realm 里的一个对象,一个 principal 总是和一个密钥(secret key)成对出现的。

这个 principal 的对应物可以是 service,可以是 host,也可以是 user,对于 Kerberos 来说,都没有区别。

Kdc(Key distribute center) 知道所有 principal 的 secret key,但每个 principal 对应的对象只知道自己的那个 secret key 。这也是“共享密钥“的由来。

对于 hadoop,principals 的格式为 username/fully.qualified.domain.name@YOUR-REALM.COM

通过 yum 源安装的 cdh 集群中,NameNode 和 DataNode 是通过 hdfs 启动的,故为集群中每个服务器节点添加两个principals:hdfs、HTTP。

在 KCD server 上(这里是 cdh1)创建 hdfs principal:

kadmin.local -q "addprinc -randkey hdfs/cdh1@JAVACHEN.COM"
kadmin.local -q "addprinc -randkey hdfs/cdh2@JAVACHEN.COM"
kadmin.local -q "addprinc -randkey hdfs/cdh3@JAVACHEN.COM"

-randkey 标志没有为新 principal 设置密码,而是指示 kadmin 生成一个随机密钥。之所以在这里使用这个标志,是因为此 principal 不需要用户交互。它是计算机的一个服务器帐户。

创建 HTTP principal:

kadmin.local -q "addprinc -randkey HTTP/cdh1@JAVACHEN.COM"
kadmin.local -q "addprinc -randkey HTTP/cdh2@JAVACHEN.COM"
kadmin.local -q "addprinc -randkey HTTP/cdh3@JAVACHEN.COM"

创建完成后,查看:

$ kadmin.local -q "listprincs"

4.2 创建keytab文件#

keytab 是包含 principals 和加密 principal key 的文件。

keytab 文件对于每个 host 是唯一的,因为 key 中包含 hostname。keytab 文件用于不需要人工交互和保存纯文本密码,实现到 kerberos 上验证一个主机上的 principal。

因为服务器上可以访问 keytab 文件即可以以 principal 的身份通过 kerberos 的认证,所以,keytab 文件应该被妥善保存,应该只有少数的用户可以访问

创建包含 hdfs principal 和 host principal 的 hdfs keytab:

xst -norandkey -k hdfs.keytab hdfs/fully.qualified.domain.name host/fully.qualified.domain.name

创建包含 mapred principal 和 host principal 的 mapred keytab:

xst -norandkey -k mapred.keytab mapred/fully.qualified.domain.name host/fully.qualified.domain.name

注意:
上面的方法使用了xst的norandkey参数,有些kerberos不支持该参数。
当不支持该参数时有这样的提示:Principal -norandkey does not exist.,需要使用下面的方法来生成keytab文件。

在 cdh1 节点,即 KDC server 节点上执行下面命令:

$ cd /var/kerberos/krb5kdc/

$ kadmin.local -q "xst  -k hdfs-unmerged.keytab  hdfs/cdh1@JAVACHEN.COM"
$ kadmin.local -q "xst  -k hdfs-unmerged.keytab  hdfs/cdh2@JAVACHEN.COM"
$ kadmin.local -q "xst  -k hdfs-unmerged.keytab  hdfs/cdh3@JAVACHEN.COM"

$ kadmin.local -q "xst  -k HTTP.keytab  HTTP/cdh1@JAVACHEN.COM"
$ kadmin.local -q "xst  -k HTTP.keytab  HTTP/cdh2@JAVACHEN.COM"
$ kadmin.local -q "xst  -k HTTP.keytab  HTTP/cdh3@JAVACHEN.COM"

这样,就会在 /var/kerberos/krb5kdc/ 目录下生成 hdfs-unmerged.keytab 和 HTTP.keytab 两个文件,接下来使用 ktutil 合并者两个文件为 hdfs.keytab

$ cd /var/kerberos/krb5kdc/

$ ktutil
ktutil: rkt hdfs-unmerged.keytab
ktutil: rkt HTTP.keytab
ktutil: wkt hdfs.keytab

使用 klist 显示 hdfs.keytab 文件列表:

$ klist -ket  hdfs.keytab
Keytab name: FILE:hdfs.keytab
KVNO Timestamp         Principal
---- ----------------- --------------------------------------------------------
   2 11/13/14 10:40:18 hdfs/cdh1@JAVACHEN.COM (des3-cbc-sha1)
   2 11/13/14 10:40:18 hdfs/cdh1@JAVACHEN.COM (arcfour-hmac)
   2 11/13/14 10:40:18 hdfs/cdh1@JAVACHEN.COM (des-hmac-sha1)
   2 11/13/14 10:40:18 hdfs/cdh1@JAVACHEN.COM (des-cbc-md5)
   4 11/13/14 10:40:18 hdfs/cdh2@JAVACHEN.COM (des3-cbc-sha1)
   4 11/13/14 10:40:18 hdfs/cdh2@JAVACHEN.COM (arcfour-hmac)
   4 11/13/14 10:40:18 hdfs/cdh2@JAVACHEN.COM (des-hmac-sha1)
   4 11/13/14 10:40:18 hdfs/cdh2@JAVACHEN.COM (des-cbc-md5)
   4 11/13/14 10:40:18 hdfs/cdh3@JAVACHEN.COM (des3-cbc-sha1)
   4 11/13/14 10:40:18 hdfs/cdh3@JAVACHEN.COM (arcfour-hmac)
   4 11/13/14 10:40:18 hdfs/cdh3@JAVACHEN.COM (des-hmac-sha1)
   4 11/13/14 10:40:18 hdfs/cdh3@JAVACHEN.COM (des-cbc-md5)
   3 11/13/14 10:40:18 HTTP/cdh1@JAVACHEN.COM (des3-cbc-sha1)
   3 11/13/14 10:40:18 HTTP/cdh1@JAVACHEN.COM (arcfour-hmac)
   3 11/13/14 10:40:18 HTTP/cdh1@JAVACHEN.COM (des-hmac-sha1)
   3 11/13/14 10:40:18 HTTP/cdh1@JAVACHEN.COM (des-cbc-md5)
   3 11/13/14 10:40:18 HTTP/cdh2@JAVACHEN.COM (des3-cbc-sha1)
   3 11/13/14 10:40:18 HTTP/cdh2@JAVACHEN.COM (arcfour-hmac)
   3 11/13/14 10:40:18 HTTP/cdh2@JAVACHEN.COM (des-hmac-sha1)
   3 11/13/14 10:40:18 HTTP/cdh2@JAVACHEN.COM (des-cbc-md5)
   3 11/13/14 10:40:18 HTTP/cdh3@JAVACHEN.COM (des3-cbc-sha1)
   3 11/13/14 10:40:18 HTTP/cdh3@JAVACHEN.COM (arcfour-hmac)
   3 11/13/14 10:40:18 HTTP/cdh3@JAVACHEN.COM (des-hmac-sha1)
   3 11/13/14 10:40:18 HTTP/cdh3@JAVACHEN.COM (des-cbc-md5)

验证是否正确合并了key,使用合并后的keytab,分别使用hdfs和host principals来获取证书。

$ kinit -k -t hdfs.keytab hdfs/cdh1@JAVACHEN.COM
$ kinit -k -t hdfs.keytab HTTP/cdh1@JAVACHEN.COM

如果出现错误:kinit: Key table entry not found while getting initial credentials
则上面的合并有问题,重新执行前面的操作。

4.3 部署kerberos keytab文件#

拷贝 hdfs.keytab 文件到其他节点的 /etc/hadoop/conf 目录

$ cd /var/kerberos/krb5kdc/

$ scp hdfs.keytab cdh1:/etc/hadoop/conf
$ scp hdfs.keytab cdh2:/etc/hadoop/conf
$ scp hdfs.keytab cdh3:/etc/hadoop/conf

并设置权限,分别在 cdh1、cdh2、cdh3 上执行:

$ ssh cdh1 "chown hdfs:hadoop /etc/hadoop/conf/hdfs.keytab ;chmod 400 /etc/hadoop/conf/hdfs.keytab"
$ ssh cdh2 "chown hdfs:hadoop /etc/hadoop/conf/hdfs.keytab ;chmod 400 /etc/hadoop/conf/hdfs.keytab"
$ ssh cdh3 "chown hdfs:hadoop /etc/hadoop/conf/hdfs.keytab ;chmod 400 /etc/hadoop/conf/hdfs.keytab"

由于 keytab 相当于有了永久凭证,不需要提供密码(如果修改kdc中的principal的密码,则该keytab就会失效),所以其他用户如果对该文件有读权限,就可以冒充 keytab 中指定的用户身份访问 hadoop,所以 keytab 文件需要确保只对 owner 有读权限(0400)

4.4 修改 hdfs 配置文件#

先停止集群:

$ for x in `cd /etc/init.d ; ls hive-*` ; do sudo service $x stop ; done
$ for x in `cd /etc/init.d ; ls impala-*` ; do sudo service $x stop ; done
$ for x in `cd /etc/init.d ; ls hadoop-*` ; do sudo service $x stop ; done
$ for x in `cd /etc/init.d ; ls zookeeper-*` ; do sudo service $x stop ; done

在集群中所有节点的 core-site.xml 文件中添加下面的配置:

<property>
  <name>hadoop.security.authentication</name>
  <value>kerberos</value>
</property>

<property>
  <name>hadoop.security.authorization</name>
  <value>true</value>
</property>

在集群中所有节点的 hdfs-site.xml 文件中添加下面的配置:

<property>
  <name>dfs.block.access.token.enable</name>
  <value>true</value>
</property>
<property>  
  <name>dfs.datanode.data.dir.perm</name>  
  <value>700</value>  
</property>
<property>
  <name>dfs.namenode.keytab.file</name>
  <value>/etc/hadoop/conf/hdfs.keytab</value>
</property>
<property>
  <name>dfs.namenode.kerberos.principal</name>
  <value>hdfs/_HOST@JAVACHEN.COM</value>
</property>
<property>
  <name>dfs.namenode.kerberos.https.principal</name>
  <value>HTTP/_HOST@JAVACHEN.COM</value>
</property>
<property>
  <name>dfs.datanode.address</name>
  <value>0.0.0.0:1004</value>
</property>
<property>
  <name>dfs.datanode.http.address</name>
  <value>0.0.0.0:1006</value>
</property>
<property>
  <name>dfs.datanode.keytab.file</name>
  <value>/etc/hadoop/conf/hdfs.keytab</value>
</property>
<property>
  <name>dfs.datanode.kerberos.principal</name>
  <value>hdfs/_HOST@JAVACHEN.COM</value>
</property>
<property>
  <name>dfs.datanode.kerberos.https.principal</name>
  <value>HTTP/_HOST@JAVACHEN.COM</value>
</property>

如果想开启 SSL,请添加(本文不对这部分做说明):

<property>
  <name>dfs.http.policy</name>
  <value>HTTPS_ONLY</value>
</property>

如果 HDFS 配置了 QJM HA,则需要添加(另外,你还要在 zookeeper 上配置 kerberos):

<property>
  <name>dfs.journalnode.keytab.file</name>
  <value>/etc/hadoop/conf/hdfs.keytab</value>
</property>
<property>
  <name>dfs.journalnode.kerberos.principal</name>
  <value>hdfs/_HOST@JAVACHEN.COM</value>
</property>
<property>
  <name>dfs.journalnode.kerberos.internal.spnego.principal</name>
  <value>HTTP/_HOST@JAVACHEN.COM</value>
</property>

如果配置了 WebHDFS,则添加:

<property>
  <name>dfs.webhdfs.enabled</name>
  <value>true</value>
</property>

<property>
  <name>dfs.web.authentication.kerberos.principal</name>
  <value>HTTP/_HOST@JAVACHEN.COM</value>
</property>

<property>
  <name>dfs.web.authentication.kerberos.keytab</name>
  <value>/etc/hadoop/conf/hdfs.keytab</value>
</property>

配置中有几点要注意的:

  • 1. dfs.datanode.address表示 data transceiver RPC server 所绑定的 hostname 或 IP 地址,如果开启 security,端口号必须小于 1024(privileged port),否则的话启动 datanode 时候会报 Cannot start secure cluster without privileged resources 错误
  • 2. principal 中的 instance 部分可以使用 _HOST 标记,系统会自动替换它为全称域名
  • 3. 如果开启了 security, hadoop 会对 hdfs block data(由 dfs.data.dir 指定)做 permission check,方式用户的代码不是调用hdfs api而是直接本地读block data,这样就绕过了kerberos和文件权限验证,管理员可以通过设置 dfs.datanode.data.dir.perm 来修改 datanode 文件权限,这里我们设置为700

4.5 检查集群上的 HDFS 和本地文件的权限#

请参考 Verify User Accounts and Groups in CDH 5 Due to Security 或者 Hadoop in Secure Mode。

4.6 启动 NameNode#

启动之前,请确认 JCE jar 已经替换,请参考前面的说明。

在每个节点上获取 root 用户的 ticket,这里 root 为之前创建的 root/admin 的密码。

$ ssh cdh1 "echo root|kinit root/admin"
$ ssh cdh1 "echo root|kinit root/admin"
$ ssh cdh1 "echo root|kinit root/admin"

获取 cdh1的 ticket:

$ kinit -k -t /etc/hadoop/conf/hdfs.keytab hdfs/cdh1@JAVACHEN.COM

如果出现下面异常 kinit: Password incorrect while getting initial credentials
,则重新导出 keytab 再试试。

然后启动服务,观察日志:

$ /etc/init.d/hadoop-hdfs-namenode start

验证 NameNode 是否启动,一是打开 web 界面查看启动状态,一是运行下面命令查看 hdfs:

$ hadoop fs -ls /
Found 4 items
drwxrwxrwx   - yarn hadoop          0 2014-06-26 15:24 /logroot
drwxrwxrwt   - hdfs hadoop          0 2014-11-04 10:44 /tmp
drwxr-xr-x   - hdfs hadoop          0 2014-08-10 10:53 /user
drwxr-xr-x   - hdfs hadoop          0 2013-05-20 22:52 /var

如果在你的凭据缓存中没有有效的 kerberos ticket,执行上面命令将会失败,将会出现下面的错误:

14/11/04 12:08:12 WARN ipc.Client: Exception encountered while connecting to the server : javax.security.sasl.SaslException:
GSS initiate failed [Caused by GS***ception: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]
Bad connection to FS. command aborted. exception: Call to cdh1/192.168.56.121:8020 failed on local exception: java.io.IOException:
javax.security.sasl.SaslException: GSS initiate failed [Caused by GS***ception: No valid credentials provided (Mechanism level: Failed to find any Kerberos tgt)]

4.6 启动DataNode#

DataNode 需要通过 JSVC 启动。首先检查是否安装了 JSVC 命令,然后配置环境变量。

在 cdh1 节点查看是否安装了 JSVC:

$ ls /usr/lib/bigtop-utils/
bigtop-detect-classpath  bigtop-detect-javahome  bigtop-detect-javalibs  jsvc

然后编辑 /etc/default/hadoop-hdfs-datanode,取消对下面的注释并添加一行设置 JSVC_HOME,修改如下:

export HADOOP_SECURE_DN_USER=hdfs
export HADOOP_SECURE_DN_PID_DIR=/var/run/hadoop-hdfs
export HADOOP_SECURE_DN_LOG_DIR=/var/log/hadoop-hdfs

export JSVC_HOME=/usr/lib/bigtop-utils

将该文件同步到其他节点:

$ scp /etc/default/hadoop-hdfs-datanode cdh2:/etc/default/hadoop-hdfs-datanode
$ scp /etc/default/hadoop-hdfs-datanode cdh3:/etc/default/hadoop-hdfs-datanode

分别在 cdh2、cdh3 获取 ticket 然后启动服务:

#root 为 root/admin 的密码
$ ssh cdh1 "kinit -k -t /etc/hadoop/conf/hdfs.keytab hdfs/cdh1@JAVACHEN.COM; service hadoop-hdfs-datanode start"
$ ssh cdh2 "kinit -k -t /etc/hadoop/conf/hdfs.keytab hdfs/cdh2@JAVACHEN.COM; service hadoop-hdfs-datanode start"
$ ssh cdh3 "kinit -k -t /etc/hadoop/conf/hdfs.keytab hdfs/cdh3@JAVACHEN.COM; service hadoop-hdfs-datanode start"

观看 cdh1 上 NameNode 日志,出现下面日志表示 DataNode 启动成功:

14/11/04 17:21:41 INFO security.UserGroupInformation:
Login successful for user hdfs/cdh2@JAVACHEN.COM using keytab file /etc/hadoop/conf/hdfs.keytab

5. 其他

5.1 批量生成 keytab#

为了方便批量生成 keytab,写了一个脚本,如下:

#!/bin/bash

DNS=LASHOU.COM
hostname=`hostname -i`

yum install krb5-server krb5-libs krb5-auth-dialog krb5-workstation  -y
rm -rf /var/kerberos/krb5kdc/*.keytab /var/kerberos/krb5kdc/prin*

kdb5_util create -r LASHOU.COM -s

chkconfig --level 35 krb5kdc on
chkconfig --level 35 kadmin on
service krb5kdc restart
service kadmin restart

echo -e "root\nroot" | kadmin.local -q "addprinc root/admin"

for host in  `cat /etc/hosts|grep 10|grep -v $hostname|awk '{print $2}'` ;do
  for user in hdfs hive; do
    kadmin.local -q "addprinc -randkey $user/$host@$DNS"
    kadmin.local -q "xst -k /var/kerberos/krb5kdc/$user-un.keytab $user/$host@$DNS"
  done
  for user in HTTP lashou yarn mapred impala zookeeper sentry llama zkcli ; do
    kadmin.local -q "addprinc -randkey $user/$host@$DNS"
    kadmin.local -q "xst -k /var/kerberos/krb5kdc/$user.keytab $user/$host@$DNS"
  done
done

cd /var/kerberos/krb5kdc/
echo -e "rkt lashou.keytab\nrkt hdfs-un.keytab\nrkt HTTP.keytab\nwkt hdfs.keytab" | ktutil
echo -e "rkt lashou.keytab\nrkt hive-un.keytab\nwkt hive.keytab" | ktutil

#kerberos 重新初始化之后,还需要添加下面代码用于集成 ldap

kadmin.local -q "addprinc ldapadmin@JAVACHEN.COM"
kadmin.local -q "addprinc -randkey ldap/cdh1@JAVACHEN.COM"
kadmin.local -q "ktadd -k /etc/openldap/ldap.keytab ldap/cdh1@JAVACHEN.COM"

#如果安装了 openldap ,重启 slapd
/etc/init.d/slapd restart

#测试 ldap 是否可以正常使用
ldapsearch -x -b 'dc=javachen,dc=com'

以下脚本用于在每个客户端上获得 root/admin 的 ticket,其密码为 root:

#!/bin/sh

for node in 56.121 56.122 56.123 ;do
  echo "========10.168.$node========"
  ssh 192.168.$node 'echo root|kinit root/admin'
done

5.2 管理集群脚本#

另外,为了方便管理集群,在 cdh1 上创建一个 shell 脚本用于批量管理集群,脚本如下(保存为 manager_cluster.sh):

#!/bin/bash

role=$1
command=$2

dir=$role

if [ X"$role" == X"hdfs" ];then
  dir=hadoop
fi

if [ X"$role" == X"yarn" ];then
        dir=hadoop
fi

if [ X"$role" == X"mapred" ];then
        dir=hadoop
fi

for node in 56.121 56.122 56.123 ;do
  echo "========192.168.$node========"
  ssh 192.168.$node '
    #先获取 root/admin 的凭证
    echo root|kinit root/admin
    host=`hostname -f| tr "[:upper:]" "[:lower:]"`
    path="'$role'/$host"
    #echo $path
    principal=`klist -k /etc/'$dir'/conf/'$role'.keytab | grep $path | head -n1 | cut -d " " -f5`
    #echo $principal
    if [ X"$principal" == X ]; then
      principal=`klist -k /etc/'$dir'/conf/'$role'.keytab | grep $path | head -n1 | cut -d " " -f4`
      if [ X"$principal" == X ]; then
            echo "Failed to get hdfs Kerberos principal"
            exit 1
      fi
    fi
    kinit -r 24l -kt /etc/'$dir'/conf/'$role'.keytab $principal
    if [ $? -ne 0 ]; then
        echo "Failed to login as hdfs by kinit command"
        exit 1
    fi
    kinit -R
    for src in `ls /etc/init.d|grep '$role'`;do service $src '$command'; done
  '
done

使用方法为:

$ sh manager_cluster.sh hdfs start #启动 hdfs 用户管理的服务
$ sh manager_cluster.sh yarn start #启动 yarn 用户管理的服务
$ sh manager_cluster.sh mapred start #启动 mapred 用户管理的服务

$ sh manager_cluster.sh hdfs status # 在每个节点上获取 hdfs 的 ticket,然后可以执行其他操作,如批量启动 datanode 等等

5.3 使用 java 代码测试 kerberos#

在 hdfs 中集成 kerberos 之前,可以先使用下面代码(Krb.java)进行测试:

import com.sun.security.auth.module.Krb5LoginModule;

import javax.security.auth.Subject;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class Krb {
    private void loginImpl(final String propertiesFileName) throws Exception {
        System.out.println("NB: system property to specify the krb5 config: [java.security.krb5.conf]");
        //System.setProperty("java.security.krb5.conf", "/etc/krb5.conf");

        System.out.println(System.getProperty("java.version"));

        System.setProperty("sun.security.krb5.debug", "true");

        final Subject subject = new Subject();

        final Krb5LoginModule krb5LoginModule = new Krb5LoginModule();
        final Map<String,String> optionMap = new HashMap<String,String>();

        if (propertiesFileName == null) {
            //optionMap.put("ticketCache", "/tmp/krb5cc_1000");
            optionMap.put("keyTab", "/etc/krb5.keytab");
            optionMap.put("principal", "foo"); // default realm

            optionMap.put("doNotPrompt", "true");
            optionMap.put("refreshKrb5Config", "true");
            optionMap.put("useTicketCache", "true");
            optionMap.put("renewTGT", "true");
            optionMap.put("useKeyTab", "true");
            optionMap.put("storeKey", "true");
            optionMap.put("isInitiator", "true");
        } else {
            File f = new File(propertiesFileName);
            System.out.println("======= loading property file ["+f.getAbsolutePath()+"]");
            Properties p = new Properties();
            InputStream is = new FileInputStream(f);
            try {
                p.load(is);
            } finally {
                is.close();
            }
            optionMap.putAll((Map)p);
        }
        optionMap.put("debug", "true"); // switch on debug of the Java implementation

        krb5LoginModule.initialize(subject, null, new HashMap<String,String>(), optionMap);

        boolean loginOk = krb5LoginModule.login();
        System.out.println("======= login:  " + loginOk);

        boolean commitOk = krb5LoginModule.commit();
        System.out.println("======= commit: " + commitOk);
        System.out.println("======= Subject: " + subject);
    }

    public static void main(String[] args) throws Exception {
        System.out.println("A property file with the login context can be specified as the 1st and the only paramater.");
        final Krb krb = new Krb();
        krb.loginImpl(args.length == 0 ? null : args[0]);
    }
}

创建一个配置文件krb5.properties:

keyTab=/etc/hadoop/conf/hdfs.keytab
principal=hdfs/cdh1@JAVACHEN.COM

doNotPrompt=true
refreshKrb5Config=true
useTicketCache=true
renewTGT=true
useKeyTab=true
storeKey=true
isInitiator=true

编译 java 代码并运行:

# 先销毁当前 ticket

$ kdestroy

$ javac Krb.java

$ java -cp . Krb ./krb5.properties
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HDFS 集成 Kerberos 的相关文章

  • Spring Security Kerberos + AD,校验和失败

    我正在尝试使用 Active Directory 凭据执行 Spring Security Kerberos 如中所述http docs spring io spring security kerberos docs 1 0 1 RELEA
  • 通过 LDAP 进行 Kerberos 身份验证

    我正在开发控制台应用程序 它使用 ldap DirectoryServices Protocols 从活动目录中获取用户数据 目前 我可以使用 SSL TLS 和简单连接 既不是 SSL 也不是 TLS 的基本身份验证来获取数据 但现在我想
  • hdfs - ls:本地异常失败:com.google.protobuf.InvalidProtocolBufferException:

    我正在尝试使用以下内容列出我在 hdfs 中的目录 ubuntu ubuntu hadoop fs ls hdfs 127 0 0 1 50075 ls Failed on local exception com google protob
  • 如何将小型 ORC 文件组合或合并为较大的 ORC 文件?

    SO 和网络上的大多数问题 答案都讨论使用 Hive 将一堆小 ORC 文件合并为一个较大的文件 但是 我的 ORC 文件是按天分隔的日志文件 我需要将它们分开 我只想每天 汇总 ORC 文件 HDFS 中的目录 我最有可能需要用 Java
  • 解析数百万个小 XML 文件

    我有 1000 万个小 XML 文件 300KB 500KB 我在 Mapreduce 中使用 Mahaout 的 XML 输入格式来读取数据 并使用 SAX 解析器进行解析 但处理速度非常慢 使用输入文件的压缩 lzo 有助于提高性能吗
  • 尝试在 h5py 中打开 pandas 创建的 hdf 时缺少列

    这就是我的数据框的样子 第一列是一个整数 第二列是 512 个整数的单个列表 IndexID Ids 1899317 0 47715 1757 9 38994 230 12 241 12228 22861131 0 48156 154 63
  • Hadoop 中的分割大小与块大小

    Hadoop 中的分割大小和块大小之间有什么关系 当我读到this http willddy github io 2012 08 25 Hadoop Split and Block html 分割大小必须是块大小的n倍 n是整数并且n gt
  • Hadoop - 重新启动数据节点和任务跟踪器

    我想关闭单个数据节点和任务跟踪器 以便我在mapred site xml中所做的一些新更改生效 例如mapred reduce child java opts等 我该怎么做 但是 我不想关闭整个集群 因为我有正在运行的活动作业 另外 如何确
  • HDFS 复制因子更改

    如果集群中的复制因子发生变化 例如从 5 更改为 3 并且集群重新启动 旧文件块会发生什么情况 它们是否会被视为过度复制并被删除 或者复制因子仅适用于新文件 这意味着旧文件块被复制 5 次 新文件块 重新启动后 被复制 3 次 如果集群不重
  • Namenode-HDFS 出现“连接被拒绝”错误(Hadoop 问题)

    当我们看到使用时 我的所有节点都已启动并运行jps命令 但我仍然无法连接到 hdfs 文件系统 每当我点击Browse the filesystem在 Hadoop Namenode localhost 8020 页面上 我得到的错误是Co
  • Kerberos:UPN 和 SPN 之间的区别

    我现在正在使用 GSSAPI 对跨平台应用程序进行 Kerberized 虽然我不清楚 UPN 和 SPN 之间的区别 开发环境是 CentOS 6 4 上的 Samba4 AD DC 服务器 带有 Windows Server 2008
  • 如何从java通过hdfs协议访问hadoop?

    我找到了一种通过以下方式连接到hadoop的方法hftp 并且工作正常 只读 uri hftp 172 16 xxx xxx 50070 System out println uri uri Configuration conf new C
  • Hadoop 顺序数据访问

    根据 Hadoop 权威指南 HDFS 是一个文件系统 设计用于存储非常大的文件 流式或顺序数据访问模式 什么是流式或顺序数据访问 它如何减少磁盘的寻道时间 这并不是 Hadoop 特有的 顺序访问模式是指按顺序读取数据 通常是从开始到结束
  • 如何使用 Spring 和 Active Directory 实现单点登录

    我有一个基于 Spring 的 Web 应用程序 我想在其上实现单点登录解决方案 基本流程是 1 用户登录 Windows 工作站 台式电脑 根据组织的 Active Directory 进行身份验证 2 用户打开浏览器并导航到 Sprin
  • 使用 FSDataOutputStream 将不需要的字符从 java REST-API 写入 HadoopDFS

    我们构建了一个 java REST API 来接收事件数据 例如单击购买按钮 并将该数据写入 HDFS 本质上 我们为发送数据 以 JSON 形式 的每个主机打开流 或者使用现有的流 使用时间戳 事件名称和主机名丰富数据 并将其写入 FS
  • HBase如何实现对HDFS的随机访问?

    鉴于HBase是一个数据库 其文件存储在HDFS中 那么它如何实现对HDFS中单个数据的随机访问呢 这是通过什么方法实现的呢 From Apache HBase 参考指南 http hbase apache org book archite
  • 如何为 HDFS 递归列出子目录?

    我在 HDFS 中递归创建了一组目录 如何列出所有目录 对于普通的 UNIX 文件系统 我可以使用以下命令来做到这一点 find path type d print 但我想为 HDFS 得到类似的东西 递归列出目录内容hadoop dfs
  • 无法使用 PDI 步骤连接到 HDFS

    我已经配置成功了Hadoop 2 4 in an Ubuntu 14 04 虚拟机 from a 视窗8系统 Hadoop 安装工作绝对正常 而且我还可以从 Windows 浏览器查看 Namenode 附图如下 所以 我的主机名是 ubu
  • Curl下载到HDFS

    我有这个代码 curl o fileName csv url xargs hdfs dfs moveFromLocal 1 somePath 当我执行此代码时 curl 将请求中的值放入 fileName csv 中 该文件将移动到 HDF
  • alter Windows 文件中的 krb5.ini 文件哪里去了?

    至少在 Windows XP 之前 如果您加入具有 Kerberos 领域特定设置的域 就会有一个 krb5 ini 文件 从 Vista 或 7 开始 不再需要此文件 我试图找到有关此的更多信息 但陷入困境 krb5 ini 文件中的设置

随机推荐

  • VScode使用Remote - SSH插件实现远程服务器开发

    一 引言 最近做实验需要用到远程服务器开发 xff0c 在windows系统上可以下载Xshell PuTTY 来进行实验 xff0c 因为助教推荐使用VScode 43 Remote ssh来进行实验 xff0c 所以百度了怎么样来操作
  • YUV/RGB颜色空间转换公式

    经过调研 xff0c 最终选择以下转换公式 xff1a Jack Keith Video Demystified a Handbook for the Digital Engineer LLH Technology Publishing 3
  • c语言编程软件有哪些 Win7下用哪种C语言编译器

    C语言是一门历史很长的编程语言 xff0c 其编译器和开发工具也多种多样 xff0c 其开发工具包括编译器 xff0c 现举几个开发工具供大家选择 xff0c 当然也要根据自己的操作系统来选择适合自己的开发工具 好多刚开始接触c语言的朋友都
  • 大数据时代的图表可视化利器——highcharts,D3和百度的echarts

    还记得阿里巴巴那个令人澎湃激情的双十一吗 xff1f 还记得淘宝生动形象地把你的的消费历程一一地展示给你看吗 xff1f 还记得那些酷炫拽的it报告图表吗 xff1f 在这个大数据越来越盛行的年代 xff0c 怎样去表达一些用户的关系 xf
  • 在tinycorelinux上安装lxc,lxd (1)

    本文关键字 xff0c 在tinycorelinux上安装lxc xff0c lxd gcc4 4 self reference struct typedef 在前面的文章中我们讲到过内置虚拟化的os设计 xff0c 它可以使包括裸金属 x
  • STM32上第一个程序-GPIO控制LED-第3季第5部分-朱有鹏-专题视频课程

    STM32上第一个程序 GPIO控制LED 第3季第5部分 759人已学习 课程介绍 本课程是 朱有鹏老师单片机完全学习系列课程 第3季第5个课程 xff0c 从零开始带大家写代码控制板载LED xff0c 并且用三个版本的开发板都实现了功
  • Cas 5.3x cas-overlay-template用iframe实现登录跳转

    Cas 5 3x cas overlay template用iframe实现登录跳转 在上一篇Cas 5 3x 简单配置 xff0c 解决https访问的问题的基础上 xff0c 我尝试了一下如何用iframe实现登录和跳转 xff0c 因
  • Linux自带防火墙基本使用

    文章目录 四 Linux自带防火墙1 查看linux的防火墙状态2 查看已经对外开放的端口3 开放端口 重载防火墙配置4 filewalld常用命令 四 Linux自带防火墙 前言 xff1a CentOS7 端口的开放关闭查看都是用防火墙
  • BGP边界网关协议基础知识点

    BGP xff1a 边界网关协议 AS 自治系统 由单一机构或组织管理的一系列IP网络机器设备的集合 网络范围太大 xff0c 协议跑不过来 xff0c 需要进行划分自治管理 为了方便区分和标定不同AS xff0c 我们给每个自治系统设计了
  • 温湿度传感器SHTC3驱动开发(一)小白也能轻松理解

    一 首先了解设备硬件原理图 首先在公司干活 xff0c 要你开发一个设备驱动 xff0c 那你的老大必须得给你的东西如下 xff1a 开发板主板硬件原理图驱动设备的硬件原理图驱动的设备的数据手册 xff08 datasheet xff09
  • nodejs的版本管理工具(nvm)

    1 nvm是什么 nvm全名node js version management xff0c 顾名思义是一个nodejs的版本管理工具 为了解决node各种版本存在不兼容现象 nvm是让你在同一台机器上安装和切换不同版本的node的工具 x
  • A变为a和a的ASCII值

    span class hljs comment include lt stdio h gt span main char ch span class hljs keyword printf span span class hljs stri
  • 机器学习python Kmeans聚类

    import numpy as np import matplotlib pyplot as plt import pandas as pd from sklearn cluster import KMeans from sklearn i
  • 为wget命令设置代理

    实验环境 xff1a ubuntu 12 04 LTS goagent 方法一 在环境变量中设置代理 export http proxy 61 http 127 0 0 1 8087 方法二 使用配置文件 为wget使用代理 xff0c 可
  • ubuntu14.04安裝numpy,scipy

    在windows下搞python xff0c 实在出错太多 xff0c 就安装了双系统 xff0c 在ubuntu下试着学习一下 xff0c 我的ubuntu版本为ubuntu14 04 以前不知道python的这些包之间是有依赖关系的 x
  • STM32的中断体系和FSMC控制LCD-第3季第7部分视频课程-朱有鹏-专题视频课程

    STM32的中断体系和FSMC控制LCD 第3季第7部分视频课程 861人已学习 课程介绍 本课程是 朱有鹏老师单片机完全学习系列课程 第3季第7个课程 xff0c 本课程详细讲解STM32的外部中断和FSMC模块 xff0c 这两个模块都
  • ubuntu加入Windows的AD域(使用Samba和Winbind的方式)

    ubuntu加入Windows的AD域 Integrate Ubuntu 16 04 to AD as a Domain Member with Samba and Winbind Part 8 Step 1 Initial Configu
  • XTU 1262 Fish(优先队列+贪心)

    钓鱼 http 202 197 224 59 exam index php problem read id 1262 题目描述 小明很喜欢钓鱼 xff0c 现在有n个池塘可以钓鱼 xff0c 第i个池塘首次内能钓到ai条鱼 第i个池塘如果被
  • webpack开发调试模式devtool

    devtool 有7种模式 eval 文档上解释的很明白 xff0c 每个模块都封装到 eval 包裹起来 xff0c 并在后面添加 sourceURL source map 这是最原始的 source map 实现方式 xff0c 其实现
  • HDFS 集成 Kerberos

    本文主要记录 CDH Hadoop 集群上配置 HDFS 集成 Kerberos 的过程 xff0c 包括 Kerberos 的安装和 Hadoop 相关配置修改说明 注意 xff1a 下面第一 二部分内容 xff0c 摘抄自 Hadoop