应用情景:
集群的hdfs,hbase,都安装了kerberos,且hadoop版本低于2.9.0,并做了HA高可用
1.spark streaming程序submit时不通过--keytab --principal指定keytab 文件和principal,程序内部不用UserGroupInformation对kerberos认证。
提交程序前,需要在提交客户端服务器klist查看票据是否过期,如过期,需要重新kinit更新票据。
此种情况下程序运行7天后(hbase默认的token最大生命期为7天,对应hbase-site.xml参数为hbase.auth.token.max.lifetime)因token过期无法入phoenix库,SparkStreaming程序陷入阻塞状态。
2.spark streaming程序submit时通过--keytab --principal指定keytab 文件和principal,程序内部不用UserGroupInformation对kerberos认证。
提交程序前,不需要在提交客户端服务器klist查看票据是否过期,直接提交即可。
此种情况下运行结果与1一样,程序运行7天后因token过期无法入phoenix库,SparkStreaming程序陷入阻塞状态。
3.spark streaming程序submit时不通过--keytab --principal指定keytab 文件和principal,通过--files karb5.conf,user.keytab的方式把认证文件一并提交供程序内部使用UserGroupInformation对kerberos认证,如果使用连接池,需要创建连接池时也使用doAs包裹。
a.初始化kerberos认证
private def initKerberos() {
conf = new Configuration() //HBaseConfiguration.create();
val keytab = app_conf.getString("keytab.file.name") // 测试模式
val krb5 = app_conf.getString("krb5.conf.name")
System.setProperty("java.security.krb5.conf", krb5);
conf.set("keytab.file", keytab)
// 这个可以理解成用户名信息,也就是Principal
conf.set("kerberos.principal", app_conf.getString("kerberos.principal"))
conf.set("hadoop.security.authorization", "true")
conf.set("hadoop.security.authentication", "kerberos")
conf.set("hbase.security.authentication", "kerberos")
conf.set("hbase.zookeeper.quorum", app_conf.getString("hbase.zookeeper.quorum"))
conf.set("hbase.zookeeper.property.clientPort", "2181")
conf.set("hbase.master.kerberos.principal",app_conf.getString("hbase.master.kerberos.principal"))
conf.set("hbase.regionserver.kerberos.principal", app_conf.getString("hbase.regionserver.kerberos.principal"))
UserGroupInformation.setConfiguration(conf)
try{
ugi1 = UserGroupInformation.loginUserFromKeytabAndReturnUGI(app_conf.getString("kerberos.user.name"), keytab)
}
catch {
case e: IOException => {
// TODO Auto-generated catch block
e.printStackTrace()
}
}
}
b.连接池创建kerberos方式
if (ugi1 == null) {
initKerberos
}
HikariDataSource cpds = ugi1.doAs(new PrivilegedExceptionAction[HikariDataSource]() {
def run: HikariDataSource = {
cpds = new HikariDataSource(config)
cpds
}
}
c.获取kerberos连接的方法
def getKerberosConn: Connection = {
var conn: Connection = null
if (ugi1 == null) {
initKerberos
}
conn = ugi1.doAs(new PrivilegedExceptionAction[Connection]() {
def run: Connection = {
conn = getConnection
conn
}
})
conn
}
d.调用获取kerberos连接
if (ugi1 == null) {
initKerberos
}
ugi1.checkTGTAndReloginFromKeytab()
conn = getKerberosConn
第三种方法经测试可以在过期后更新hbase的token保持连接可用
小结:1.krb5.conf文件的影响范围仅仅是此文件所在的服务器(kerberos客户端),比如此服务器登陆hbase shell,提交程序到yarn(未加--keytab)等。使用--keytab 提交与先kinit再提交效果一样。
2.如果想要在测试集群验证程序kerberos认证是否成功不需要等待默认的7天(太久了,花儿都谢了),需要根据程序访问的hbase,hdfs(可在CM中修改并重启使其生效)修改对应的token配置,
hdfs-site.xml的token相关配置:
dfs.namenode.delegation.token.max-lifetime = 600000(毫秒)
dfs.namenode.delegation.key.update-interval = 180000
dfs.namenode.delegation.token.renew-interval = 180000
hbase-site.xml
hbase.auth.key.update.interval=240000
hbase.auth.token.max.lifetime=1200000
3.经过单独测试hbase shell客户端token超时只与所在服务器krb5.conf的配置有关,与hdfs-site.xml设置的token时间无关。
参考链接:
https://blog.csdn.net/co_zjw/article/details/81974845
https://issues.apache.org/jira/browse/HDFS-9276
http://support.huawei.com/enterprise/zh/doc/DOC1100006822?section=j00k