kerberos下HBase访问Zookeeper的ACL问题

最近公司HBase(CDH-4.6.0)遇到了一个麻烦问题,觉得有必要记录下整个解决的过程。


问题起因

用户在跑mapreduce任务,从hdfs读取文件想写入到hbase table的时候失败了(这是hbase提供的一种mapred能力)。这个问题发现在A环境(一个测试环境),自从启用了kerberos之后。运行了用户给的程序和自己写的sample之后,发现程序最后挂在NullPointerException上。这个NPE指示的是服务端的一个叫currentKey的变量为null。

org.apache.hadoop.hbase.ipc.ExecRPCInvoker$1@58e395e8,java.io.IOException: java.io.IOException: java.lang.NullPointerException
at  org.apache.hadoop.hbase.security.token.AuthenticationTokenSecretManager.createPassword(AuthenticationTokenSecretManager.java:129) 
at org.apache.hadoop.hbase.security.token.AuthenticationTokenSecretManager.createPassword(AuthenticationTokenSecretManager.java:57)
at org.apache.hadoop.security.token.Token.<init>(Token.java:70)
at org.apache.hadoop.hbase.security.token.AuthenticationTokenSecretManager.generateToken(AuthenticationTokenSecretManager.java:162)
at org.apache.hadoop.hbase.security.token.TokenProvider.getAuthenticationToken(TokenProvider.java:91) 
at sun.reflect.GeneratedMethodAccessor56.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.hadoop.hbase.regionserver.HRegion.exec(HRegion.java:5610)
at org.apache.hadoop.hbase.regionserver.HRegionServer.execCoprocessor(HRegionServer.java:3918)
at sun.reflect.GeneratedMethodAccessor39.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.hadoop.hbase.ipc.SecureRpcEngine$Server.call(SecureRpcEngine.java:311)
at org.apache.hadoop.hbase.ipc.HBaseServer$Handler.run(HBaseServer.java:1428)
AuthenticationTokenSecretManager:
  @Override
  protected byte[] createPassword(AuthenticationTokenIdentifier identifier) {
    long now = EnvironmentEdgeManager.currentTimeMillis();
    AuthenticationKey secretKey = currentKey;  //currentKey赋给secretKey
    identifier.setKeyId(secretKey.getKeyId()); //NPE在这里抛出的,也就是currentKey为null
    identifier.setIssueDate(now);
    identifier.setExpirationDate(now + tokenMaxLifetime);
    identifier.setSequenceNumber(tokenSeq.getAndIncrement());
    return createPassword(WritableUtils.toByteArray(identifier),
        secretKey.getKey());
  }

问题定位

既然currentKey为null,那我们就去找它在哪里赋值的。阅读源码之后,了解到整个过程是这样的:

1.在开启kerberos之后,每个RegionServer都会有一个AuthenticationTokenSecretManager用来管理token。

2.这些manager中,只有一个leader,只有它能生产token,然后放到zookeeper里。其它manager通过感知zookeeper的变化来同步leader生产的token。leader通过竞争产生,谁先在ZK上创建 /hbase/tokenauth/keymaster 节点,谁就是leader。

AuthenticationTokenSecretManager$LeaderElector:
    public void run() {
      zkLeader.start();
      zkLeader.waitToBecomeLeader();  //没有成为leader的人会一直阻塞在这里,直到感知到当前leader挂掉才会开始新一轮竞争
      isMaster = true;
      while (!stopped) {
        long now = EnvironmentEdgeManager.currentTimeMillis();
        // clear any expired
        removeExpiredKeys(); //清除过期的token,同时也把它从ZK上移除
        if (lastKeyUpdate + keyUpdateInterval < now) {  //默认的周期是1天
          // roll a new master key
          rollCurrentKey();  //就是这个函数产生新的token,替换currenKey
        }
        
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值