一、安装Kerberos
1. 整体说明
软件版本
操作系统:CentOs 6.8
CDH版本:Hadoop 2.6.0-cdh5.9.0
JDK版本:jdk1.7.0_67-cloudera
运行用户:root
集群主机角色划分
sunmvm20 作为master节点,安装kerberos Server
其他节点作为slave节点,安装kerberos client
2. 配置host
添加主机名到 /etc/hosts 文件中。
$ cat /etc/hosts
127.0.0.1 localhost
192.168.1.20 sunmvm20
192.168.1.26 sunmvm26
192.168.1.27 sunmvm27
192.168.1.28 sunmvm28
注意:hostname 请使用小写,要不然在集成 kerberos 时会出现一些错误。
在 sunmvm20 上安装 krb5、krb5-server 和 krb5-client。
yum install krb5-server -y
# klist等命令找不大时执行下面安装
yum install -y krb5-server krb5-workstation pam_krb5
在其他节点安装 krb5-devel、krb5-workstation
$ ssh sunmvm26 "yum install krb5-devel krb5-workstation -y"
$ ssh sunmvm27 "yum install krb5-devel krb5-workstation -y"
$ ssh sunmvm28 "yum install krb5-devel krb5-workstation -y"
4. 修改配置文件
kdc 服务涉及到三个配置文件:
/etc/krb5.conf
/var/kerberos/krb5kdc/kdc.conf
/var/kerberos/krb5kdc/kadm5.acl
1)编辑配置文件 /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 = 0HKJ.COM
dns_lookup_realm = false
dns_lookup_kdc = false
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = true
default_tgs_enctypes = aes256-cts-hmac-sha1-96
default_tkt_enctypes = aes256-cts-hmac-sha1-96
permitted_enctypes = aes256-cts-hmac-sha1-96
clockskew = 120
udp_preference_limit = 1
[realms]
0HKJ.COM = {
kdc = sunmvm20
admin_server = sunmvm20
}
[domain_realm]
.0hkj.com = 0HKJ.COM
ohkj.com = 0HKJ.COM
说明:
[logging]:表示 server 端的日志的打印位置
[libdefaults]:每种连接的默认配置,需要注意以下几个关键的小配置
default_realm = 0HKJ.COM:设置 Kerberos 应用程序的默认领域。如果您有多个领域,只需向 [realms] 节添加其他的语句。
ticket_lifetime: 表明凭证生效的时限,一般为24小时。
renew_lifetime: 表明凭证最长可以被延期的时限,一般为一个礼拜。当凭证过期之后,对安全认证的服务的后续访问则会失败。
clockskew:时钟偏差是不完全符合主机系统时钟的票据时戳的容差,超过此容差将不接受此票据。通常,将时钟扭斜设置为 300 秒(5 分钟)。这意味着从服务器的角度看,票证的时间戳与它的偏差可以是在前后 5 分钟内。
udp_preference_limit= 1:禁止使用 udp 可以防止一个 Hadoop 中的错误
[realms]:列举使用的 realm。
kdc:代表要 kdc 的位置。格式是 机器:端口
admin_server:代表 admin 的位置。格式是 机器:端口
default_domain:代表默认的域名
[appdefaults]:可以设定一些针对特定应用的配置,覆盖默认配置。
2)修改 /var/kerberos/krb5kdc/kdc.conf ,该文件包含 Kerberos 的配置信息。例如,KDC 的位置,Kerbero 的 admin 的realms 等。需要所有使用的 Kerberos 的机器上的配置文件都同步。这里仅列举需要的基本配置。详细介绍参考:krb5conf
[kdcdefaults]
kdc_ports = 88
kdc_tcp_ports = 88
[realms]
0HKJ.COM = {
#master_key_type = aes256-cts acl_file = /var/kerberos/krb5kdc/kadm5.acl
dict_file = /usr/share/dict/words
max_renewable_life = 7d
max_life = 1d
admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
supported_enctypes = aes256-cts:normal aes128-cts:normal des3-hmac-sha1:normal arcfour-hmac:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
default_principal_flags = +renewable, +forwardable
}
说明:
0HKJ.COM: 是设定的 realms。名字随意。Kerberos 可以支持多个 realms,会增加复杂度。大小写敏感,一般为了识别使用全部大写。这个 realms 跟机器的 host 没有大关系。
master_key_type:和 supported_enctypes 默认使用 aes256-cts。JAVA 使用 aes256-cts 验证方式需要安装 JCE 包,见下面的说明。为了简便,你可以不使用 aes256-cts 算法,这样就不需要安装 JCE 。
acl_file:标注了 admin 的用户权限,需要用户自己创建。文件格式是:Kerberos_principal permissions [target_principal] [restrictions]
supported_enctypes:支持的校验方式。
admin_keytab:KDC 进行校验的 keytab。
关于AES-256加密:
对于使用 centos5. 6 及以上的系统,默认使用 AES-256 来加密的。这就需要集群中的所有节点上安装 JCE,如果你使用的是 JDK1.6 ,则到Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for JDK/JRE 6 页面下载,如果是 JDK1.7,则到 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for JDK/JRE 7 下载。下载的文件是一个 zip 包,解开后,将里面的两个文件放到下面的目录中:$JAVA_HOME/jre/lib/security.
上面这一步一定要做,否则会报zk,namenode等不支持默认tkt的加密方式错误。
3)为了能够不直接访问 KDC 控制台而从 Kerberos 数据库添加和删除主体,请对 Kerberos 管理服务器指示允许哪些主体执行哪些操作。通过创建 /var/lib/kerberos/krb5kdc/kadm5.acl 完成此操作。
$ cat /var/kerberos/krb5kdc/kadm5.acl
内容如下:
表示principal的名字的第二部分如果是admin,那么该principal就拥有管理员权限
将 kdc 中的 /etc/krb5.conf 拷贝到集群中其他服务器即可。
$ scp /etc/krb5.conf sunmvm26:/etc/krb5.conf
$ scp /etc/krb5.conf sunmvm27:/etc/krb5.conf
$ scp /etc/krb5.conf sunmvm28:/etc/krb5.conf
在 sunmvm20 上运行初始化数据库命令。其中 -r 指定对应 realm。
$ kdb5_util create -r 0HKJ.COM -s
在 sunmvm20 节点上运行:
$ chkconfig --level 35 krb5kdc on
$ chkconfig --level 35 kadmin on
$ service krb5kdc start
$ service kadmin start
8. 创建 kerberos 管理员
关于 kerberos 的管理,可以使用 kadmin.local 或 kadmin,至于使用哪个,取决于账户和访问权限:
如果有访问 kdc 服务器的 root 权限,但是没有 kerberos admin 账户,使用 kadmin.local
如果没有访问 kdc 服务器的 root 权限,但是用 kerberos admin 账户,使用 kadmin
在 sunmvm20 上创建远程管理的管理员:
手动输入两次密码
$ kadmin.local -q "addprinc root/admin"
$ echo -e "root\nroot" | kadmin.local -q "addprinc root/admin"
抽取密钥并将其储存在本地 keytab 文件 /etc/krb5.keytab 中。这个文件由超级用户拥有,所以必须是 root 用户才能在 kadmin shell 中执行以下命令:
kadmin.local -q "ktadd kadmin/admin"
# 查看生成的keytab
klist -k /etc/krb5.keytab
# 列出Kerberos中的所有认证用户,即principals
kadmin.local -q "list_principals"
# 添加认证用户,需要输入密码
kadmin.local -q "addprinc user1"
# 使用该用户登录,获取身份认证,需要输入密码
kinit user1
# 查看当前用户的认证信息ticket
klist
# 更新ticket
kinit -R
# 销毁当前的ticket
kdestroy
# 删除认证用户
kadmin.local -q "delprinc user1"
Cloudera Manager 添加 Kerberos
在此之前,请确保以下前序工作完成:
KDC已经安装好并且正在运行
将KDC配置为允许renewable tickets with non-zerolifetime,我们在之前修改kdc.conf文件的时候已经添加了max_life和max_renewable_life这个2个属性,前者表示服务端允许的Service ticket最大生命周期,后者表示服务端允许的Service ticket更新周期。这2个属性必须分别大于等于客户端对应的配置ticket_lifetime和renew_lifetime。我们假设,不这样进行配置:ticket_lifetime = 8d, max_life = 7d, renew_lifetime = 25h, max_renew_life = 24h,那么可能造成的结果就是当service持有的票据超过24小时没有去更新,在第24.5小时的时候去进行更新,请求会遭到拒绝,报错:Ticket expired while renewing credentials,永远无法进行正常更新。对于Cloudera来说,因为更新机制被透明(Cloudera有renew进程会去定期更新),即使我们手动使用`modprinc -maxrenewlife 1week krbtgt/[email protected] 进行更新,也无济于事。
在Cloudera Manager Server上安装openldap-clients
为Cloudera Manager创建了超级管理员principal,使其能够有权限在KDC中创建其他的principals,如上面创建的cloudera-scm;
再次确认完毕后进入如下步骤:
1.启用Kerberos
2.确认完成启用Kerberos前的准备
3.KDC信息
要注意的是:这里的 Kerberos Encryption Types 必须跟KDC实际支持的加密类型匹配(即kdc.conf中的值)
4.KDB5信息
5.KDC Account Manager
6.导入KDC Account Manager 凭据
7.Kerberos Principals
8.Set HDFS Port
9.重启服务
之后 Cloudera Manager 会自动重启集群服务,启动之后会提示 Kerberos 已启用。在 Cloudera Manager 上启用 Kerberos 的过程中,会自动做以下的事情:
集群中有多少个节点,每个账户就会生成对应个数的 principal ;
为每个对应的 principal 创建 keytab;
部署 keytab 文件到指定的节点中;
在每个服务的配置文件中加入有关 Kerberos 的配置;
启用之后访问集群的所有资源都需要使用相应的账号来访问,否则会无法通过 Kerberos 的 authenticatin。
除此之外,对于特定的服务需要做额外配置,本文只介绍HDFS、YARN、HBase,其余服务请参照官方文档自行进行配置。
此时直接用CM生成的principal访问HDFS会失败,因为那些自动生成的principal的密码是随机的,用户并不知道而通过命令行的方式访问HDFS需要先使用kinit来登录并获得ticket
所以使用kinit hdfs/[email protected]需要输入密码的时候无法继续
用户可以通过创建一个[email protected]的principal并记住密码从命令行中访问HDFS
[root@master ~]# kadmin.local -q "addprinc hdfs"
[root@master ~]# kinit hdfs
[root@master ~]# hdfs dfs -ls
Found 4 items
drwxr-xr-x - hdfs supergroup 0 2017-08-29 12:00 .Trash
drwx------ - hdfs supergroup 0 2017-08-29 10:49 .staging
drwxr-xr-x - hdfs supergroup 0 2017-08-29 10:35 QuasiMonteCarlo_1503974105326_258590930
drwxr-xr-x - hdfs supergroup 0 2017-08-29 10:35 QuasiMonteCarlo_1503974128088_828012046
# kinit hdfs
# hadoop jar /opt/cloudera/parcels/CDH/lib/hadoop-mapreduce/hadoop-mapreduce-examples.jar pi 10 100
异常信息1:
Diagnostics: Application application_1504017397148_0002 initialization failed (exitCode=255) with output: main : command provided 0
main : run as user is hdfs
main : requested yarn user is hdfs
Requested user hdfs is not whitelisted and has id 986,which is below the minimum allowed 1000
原因:
Linux user 的 user id 要大于等于1000,否则会无法提交Job
例如,如果以hdfs(id为986)的身份提交一个job,就会看到以上的错误信息
解决方法:
1.使用命令 usermod -u 修改一个用户的user id
2.修改Clouder关于这个该项的设置,Yarn->配置->min.user.id修改为合适的值(如0),默认为1000
异常信息2:hdfs用户被禁止运行 YARN container
Diagnostics: Application application_1504019347914_0001 initialization failed (exitCode=255) with output: main : command provided 0
main : run as user is hdfs
main : requested yarn user is hdfs
Requested user hdfs is banned
原因:
yarn的设置中将hdfs用户禁用了
解决方法:
修改Clouder关于这个该项的设置,Yarn->配置->banned.users 将hdfs用户移除
# beeline --verbose=true
beeline > !connect jdbc:hive2://master:10000/default;principal=hive/[email protected];
Error: Could not open client transport with JDBC Uri: jdbc:hive2://master:10000/default;principal=hive/[email protected];: Peer indicated failure: GSS initiate failed (state=08S01,code=0)
java.sql.SQLException: Could not open client transport with JDBC Uri: jdbc:hive2://master:10000/default;principal=hive/[email protected];: Peer indicated failure: GSS initiate failed
Caused by: org.apache.thrift.transport.TTransportException: Peer indicated failure: GSS initiate failed
在使用jdbc+kerberos时,主要注意几个问题
1.链接字符串格式,其中user,password并不生效
jdbc:hive2://
比如Connection con = DriverManager.getConnection("jdbc:hive2://host:10000/cdnlog;principal=hdfs/host@KERBEROS_HADOOP", "user1", "");
在传入hiveserver2时,用户并不是user1
2.在有tgt cache时,传入的用户为当前tgt的用户(可以通过klist查看)
3.principal的名称和hiveserver2的主机名需要一致
4.For Beeline connection string, it should be "!connect jdbc:hive2://
# kadmin.local -q "addprinc hive"
# kinit hive
# beeline --verbose=true
beeline > !connect jdbc:hive2://master:10000/default;principal=hive/[email protected];
scan complete in 4ms
Connecting to jdbc:hive2://master:10000/default;principal=hive/[email protected];
Connected to: Apache Hive (version 1.1.0-cdh5.11.1)
Driver: Hive JDBC (version 1.1.0-cdh5.11.1)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://master:10000/default>
HUE出错
kinit: Ticket expired
while
renewing credentials
这是因为krbtgt/[email protected]的[renewlife]被设置成了0,这一点可以通过kadmin.local -q "getprinc krbtgt/[email protected]" 看出来。
将krbtgt/[email protected]的[renewlife]修改为7days即可,方法
1 |
kadmin.local -q "modprinc -maxrenewlife 1week krbtgt/[email protected]" |