• Zookeeper管理多个HBase集群


        zookeeper是hbase集群的"协调器"。由于zookeeper的轻量级特性,因此我们可以将多个hbase集群共用一个zookeeper集群,以节约大量的服务器。多个hbase集群共用zookeeper集群的方法是使用同一组ip,修改不同hbase集群的"zookeeper.znode.parent"属性,让它们使用不同的根目录。比如cluster1使用/hbase-c1,cluster2使用/hbase-c2,等等。
     
        使用以上方法有一个现实的问题:如何避免各集群的相互干扰?因为client的配置权是在用户手上,并不能保证用户永远是配置正确的,那么会产生某个用户访问了不该他访问的hbase集群。此时数据安全性成了很大的问题,甚至可能出现误删除数据。我们需要在zookeeper层屏弊掉该问题。
     
        zookeeper3.x版本起自带了简单的ACL功能(注意3.3.x版本起不再支持按hostname来分配权限)。见:http://zookeeper.apache.org/doc/r3.3.2/zookeeperProgrammers.html#sc_ZooKeeperAccessControl。进行权限配置主要使用digest和ip两种方法。其中digest是用户密码方式,对用户来说使用上并不透明。ip配置最简单,对用户也是透明的,用户并不知道的情况下就能限制它的访问权限。
     
        zookeeper将访问权限分为了五类:READ/WRITE/DELETE/CREATE/ADMIN,其中admin为最高权限。zookeeper的权限是到znode级别的,限制了某一个node的权限并不能限制它的子节点权限。

        不过使用IP做权限配置方案有一个缺陷:必须指定具体的ip,而不能使用通配符或者范围一类的。这样对于大规模的权限设置是非常不方便的一件事,因此作者略调整了一下zookeeper的代码:
      IPAuthenticationProvider.java
     
    Java代码  收藏代码
    1. /** 
    2.  * Licensed to the Apache Software Foundation (ASF) under one 
    3.  * or more contributor license agreements.  See the NOTICE file 
    4.  * distributed with this work for additional information 
    5.  * regarding copyright ownership.  The ASF licenses this file 
    6.  * to you under the Apache License, Version 2.0 (the 
    7.  * "License"); you may not use this file except in compliance 
    8.  * with the License.  You may obtain a copy of the License at 
    9.  * 
    10.  *     http://www.apache.org/licenses/LICENSE-2.0 
    11.  * 
    12.  * Unless required by applicable law or agreed to in writing, software 
    13.  * distributed under the License is distributed on an "AS IS" BASIS, 
    14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    15.  * See the License for the specific language governing permissions and 
    16.  * limitations under the License. 
    17.  */  
    18.   
    19. package org.apache.zookeeper.server.auth;  
    20.   
    21. import org.apache.zookeeper.data.Id;  
    22. import org.apache.zookeeper.server.ServerCnxn;  
    23. import org.apache.zookeeper.KeeperException;  
    24.   
    25. public class IPAuthenticationProvider implements AuthenticationProvider {  
    26.   
    27.     public String getScheme() {  
    28.         return "ip";  
    29.     }  
    30.   
    31.     public KeeperException.Code  
    32.         handleAuthentication(ServerCnxn cnxn, byte[] authData)  
    33.     {  
    34.         String id = cnxn.getRemoteAddress().getAddress().getHostAddress();  
    35.         cnxn.getAuthInfo().add(new Id(getScheme(), id));  
    36.         return KeeperException.Code.OK;  
    37.     }  
    38.   
    39.     // This is a bit weird but we need to return the address and the number of  
    40.     // bytes (to distinguish between IPv4 and IPv6  
    41.     private byte[] addr2Bytes(String addr) {  
    42.         byte b[] = v4addr2Bytes1(addr);  
    43.         // TODO Write the v6addr2Bytes  
    44.         return b;  
    45.     }  
    46.   
    47.     private byte v4addr2Bytes(String part) throws NumberFormatException{  
    48.         try {  
    49.            int v = Integer.parseInt(part);  
    50.            if (v >= 0 && v <= 255) {  
    51.                   byte  b = (byte) v;  
    52.                   return b;  
    53.                 } else {  
    54.                     throw new NumberFormatException("v < 0 or v > 255!");  
    55.                 }  
    56.             } catch (NumberFormatException e) {  
    57.                 throw e;  
    58.             }  
    59.     }  
    60.       
    61.     private byte[] v4addr2Bytes1(String addr) {  
    62.       String parts[] = addr.split("\.", -1);  
    63.       if (parts.length != 4) {  
    64.           return null;  
    65.       }  
    66.       byte b[] = new byte[4];  
    67.       for (int i = 0; i < 4; i++) {  
    68.         try {  
    69.             if(parts[i].split("/").length == 2){  
    70.                 v4addr2Bytes(parts[i].split("/")[0]);  
    71.                 v4addr2Bytes(parts[i].split("/")[1]);  
    72.                 continue;  
    73.             }else{  
    74.             b[i] = v4addr2Bytes(parts[i]);  
    75.             }  
    76.         } catch (NumberFormatException e) {  
    77.           return null;  
    78.             }  
    79.       }  
    80.       return b;  
    81.   }  
    82.       
    83.     public boolean matches(String id, String aclExpr) {  
    84.       String parts[] = aclExpr.split("/"2);  
    85.       byte aclAddr[] = addr2Bytes(parts[0]);  
    86.       if (aclAddr == null) {  
    87.           return false;  
    88.       }  
    89.       byte endAclAddr[] = new byte[aclAddr.length];  
    90.       for(int i = 0; i < aclAddr.length; i ++){  
    91.         endAclAddr[i] = aclAddr[i];  
    92.       }  
    93.       if (parts.length == 2) {  
    94.           try {  
    95.                 int end = Integer.parseInt(parts[1]);  
    96.                 int e = endAclAddr[endAclAddr.length-1]<=0?endAclAddr[endAclAddr.length-1]+256:endAclAddr[endAclAddr.length-1];  
    97.                 if(end <  e|| end < 0 || end > 255)  
    98.                     return false;  
    99.               endAclAddr[endAclAddr.length-1] = (byte)end;  
    100.           } catch (NumberFormatException e) {  
    101.               return false;  
    102.           }  
    103.       }  
    104.       byte remoteAddr[] = addr2Bytes(id);  
    105.       if (remoteAddr == null) {  
    106.           return false;  
    107.       }  
    108.       for (int i = 0; i < remoteAddr.length; i++) {  
    109.         int r = remoteAddr[i]<=0?(int)remoteAddr[i]+256:remoteAddr[i];  
    110.         int a = aclAddr[i]<=0?(int)aclAddr[i]+256:aclAddr[i];  
    111.         int e = endAclAddr[i]<=0?(int)endAclAddr[i]+256:endAclAddr[i];  
    112.         if (r < a || r > e) {  
    113.           return false;  
    114.         }  
    115.       }  
    116.       return true;  
    117.   }  
    118.   
    119.     public boolean isAuthenticated() {  
    120.         return false;  
    121.     }  
    122.   
    123.     public boolean isValid(String id) {  
    124.         return addr2Bytes(id) != null;  
    125.     }  
    126. }  

        支持了使用/做为范围标识,比如进入hbase zkcli,执行:setAcl /test ip:192.168.0.3/10:cd,则将读写权限赋给了192.168.0.3-192.168.0.10这8台机器,其它机器将没有任何权限。
        这样用同一个zookeeper管理多个集群、海量机器将不再有困扰。
        最后写了一个帮助运维同学自动化管理zookeeper集群下多个hbase集群的ACL权限的工具,像以下这样:
    Html代码  收藏代码
    1. java -Djava.ext.dirs=libs/ -cp hbase-tools.jar dwbasis.hbase.tools.client.ZookeeperAcl aclFile.json  
    2. Usage: ZookeeperAcl acljsonfile [-plan]  
    3. /test/t ==> 'ip,'192.168.0.1  
    4. :cdrwa  
    5. /test ==> 'ip,'192.168.0.1/3  
    6. :cdrwa  
    7. /test ==> 'ip,'192.168.0.5  
    8. :cdrwa  
    9. do you really setAcl as above?(y/n)  


        补充:多集群共用zk后,每个集群的启动和停止不应该影响zk的稳定。因此请配置hbase-env.sh中export HBASE_MANAGES_ZK=false
  • 相关阅读:
    检索通讯录,根据输入的电话号码的每一位下拉显示检索结果
    获取手机的具体型号 及 iOS版本号
    在iOS中使用ZBar扫描二维码
    iOS沙盒路径的查看和使用
    ios打开通讯录及点击通讯录时提取相关信息
    获取倒计时距离某一时间点的时间,判断身份证,电话号码格式是否正确的简单封装
    iOS 获取手机的型号,系统版本,软件名称,软件版本
    第三天战略会议
    第二天站略会议总结
    第一天站略会议总结
  • 原文地址:https://www.cnblogs.com/cl1024cl/p/6205188.html
Copyright © 2020-2023  润新知