接上篇《HBase + Kerberos配置示例(一)》,我们继续剩下的配置工作。
我在kbhbase1这个机器上已经安装好了hadoop,zookeeper,hbase,为了简单起见所有在东西都跑在这台机器上。同时检查了在没在启用kerberos的情况下,hbase工作正常。
#vim /etc/sysconfig/selinux 设置SELINUX=disabled,并重启
从Oracle网站下载JCE(Java Cryptography Extension)补丁,此补丁与AES-256加密有关。下载解压之后,把得到的两个jar文件local_policy.jar,US_export_policy.jar拷贝到$JAVA_HOME/ jre/lib/security下进行覆盖。
创建keytab
这样就会在kerberos服务器上创建一个用户root/[email protected],其中名字中/之后的部分应该是固定写法,即主机名+kerberos realm,红色部分则可以随意。xst命令会在当前目录下生成这个root.keytab文件。拷贝root.keytab文件到hadoop的配置目录,在我的机器上是:/usr/local/hadoop-2.6.0/etc/hadoop
修改core-site.xml
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://kbhbase1.mh.com:9000</value> </property> <property> <name>hadoop.security.authentication</name> <value>kerberos</value> <!-- Giving value as "simple" disables security.--> </property> <property> <name>hadoop.security.authorization</name> <value>true</value> </property> </configuration>
修改hadoop-env.sh
关于JSVC,默认指向hadoop安装目录的libexec下,但我的libexec下并没有jsvc文件(我的hadoop是直接下载的tar.gz包,不是rpm安装),google搜索jsvc,然后在apache网站下载源代码包以及bin包,我下的是commons-daemon-1.0.15-src.tar.gz及commons-daemon-1.0.15-bin.tar.gz,先解压src包后进入src/native/unix目录依次执行 ./configure命令, make命令,这样会在当前目录下生成一个叫jsvc的文件,把它拷贝到hadoop目录下的libexec下。 再解压bin包,然后把得到的commons-daemon-1.0.15.jar 文件拷贝到hadoop安装目录下share/hadoop/hdfs/lib下,同时删除自带版本的commons-daemon-xxx.jar包。
修改hdfs-site.xml
<configuration> <property> <name>dfs.namenode.name.dir</name> <value>file:/root/hadoopdata/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/root/hadoopdata/datanode</value> </property> <property> <name>dfs.namenode.secondary.http-address</name> <value>kbhbase1.mh.com:9001</value> </property> <property> <name>dfs.block.access.token.enable</name> <value>true</value> </property> <!-- NameNode security config --> <property> <name>dfs.https.address</name> <value>kbhbase1.mh.com:50470</value> </property> <property> <name>dfs.https.port</name> <value>50470</value> </property> <property> <name>dfs.namenode.keytab.file</name> <value>/usr/local/hadoop-2.6.0/etc/hadoop/root.keytab</value> <!-- path to the HDFS keytab --> </property> <property> <name>dfs.namenode.kerberos.principal</name> <value>root/[email protected]</value> </property> <property> <name>dfs.namenode.kerberos.https.principal</name> <value>root/[email protected]</value> </property> <!-- Secondary NameNode security config --> <property> <name>dfs.secondary.https.address</name> <value>kbhbase1.mh.com:50495</value> </property> <property> <name>dfs.secondary.https.port</name> <value>50495</value> </property> <property> <name>dfs.secondary.namenode.keytab.file</name> <value>/usr/local/hadoop-2.6.0/etc/hadoop/root.keytab</value> <!-- path to the HDFS keytab --> </property> <property> <name>dfs.secondary.namenode.kerberos.principal</name> <value>root/[email protected]</value> </property> <property> <name>dfs.secondary.namenode.kerberos.https.principal</name> <value>root/[email protected]</value> </property> <!-- DataNode security config --> <property> <name>dfs.datanode.data.dir.perm</name> <value>700</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>/usr/local/hadoop-2.6.0/etc/hadoop/root.keytab</value> <!-- path to the HDFS keytab --> </property> <property> <name>dfs.datanode.kerberos.principal</name> <value>root/[email protected]</value> </property> <property> <name>dfs.datanode.kerberos.https.principal</name> <value>root/[email protected]</value> </property> <property> <name>dfs.web.authentication.kerberos.principal</name> <value>root/[email protected]</value> </property> <property> <name>dfs.datanode.require.secure.ports</name> <value>false</value> </property> </configuration>
由于暂时不需要mapreduce,所以相关的设置我就没配。
启动hadoop hdfs
namenode,secondarynamenode可以起来,不过datanode没起来,仔细看start-dfs.sh的输出:
Attempting to start secure cluster, skipping datanodes. Run start-secure-dns.sh as root to complete startup.
所以需要执行start-secure-dns.sh(或者使用hadoop datanode命令启动),在我的机器上,起来之后,使用jps查看,datanode进程有进程号,但没有名字。
如遇到:
WARN security.UserGroupInformation: Exception encountered while running the renewal command. Aborting renew thread. ExitCodeException exitCode=1: kinit: Ticket expired while renewing credentials
具体看hadoop日志,会有若干个CheckSum错误,则需要在kdc上:
关于kerberos ticket的一些解释
一个ticket有lifetime,如果需要更长的时间,那么就需要重复地去renew它,每renew一次,就延长一个lifetime。renew就是可以不用输入密码就延长一个ticket的使用时间。 不过,renew这个操作本身也有时间限制,这取决于参数renew_lifetime,比如这个参数设置成7d,那么也就是说从ticket创建那时开始之后的7天内,你都可以做renew操作(每次renew操作需在ticket尚未过期前做)。
创建keytab
把生成的zookeeper.keytab 放到/usr/local/zookeeper-3.4.6/conf下
修改jaas.conf
Server { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true keyTab="/usr/local/zookeeper-3.4.6/conf/zookeeper.keytab" storeKey=true useTicketCache=false principal="zookeeper/[email protected]"; };
修改java.env
修改zoo.cfg
tickTime=2000
dataDir=/root/zookeeperdata
clientPort=2181
initLimit=5
syncLimit=2
server.1=kbhbase1.mh.com:2888:3888
kerberos.removeHostFromPrincipal=true
kerberos.removeRealmFromPrincipal=true
authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider
jaasLoginRenew=3600000
创建keytab
将生成的文件拷贝到hbase配置目录/usr/local/hbase-0.98.9-hadoop2/conf
修改hbase-env.sh
修改hbase-site.xml
<configuration> <property> <name>hbase.rootdir</name> <value>hdfs://kbhbase1.mh.com:9000/hbase</value> <description>The directory shared by region servers.</description> </property> <property> <name>hbase.zookeeper.property.clientPort</name> <value>2181</value> <description>Property from ZooKeeper's config zoo.cfg. The port at which the clients will connect. </description> </property> <property> <name>zookeeper.session.timeout</name> <value>120000</value> </property> <property> <name>hbase.zookeeper.quorum</name> <value>kbhbase1.mh.com</value> </property> <property> <name>hbase.tmp.dir</name> <value>/root/hbasedata</value> </property> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <property> <name>hbase.security.authentication</name> <value>kerberos</value> </property> <property> <name>hbase.rpc.engine</name> <value>org.apache.hadoop.hbase.ipc.SecureRpcEngine</value> </property> <property> <name>hbase.regionserver.kerberos.principal</name> <value>hbase/[email protected]</value> </property> <property> <name>hbase.regionserver.keytab.file</name> <value>/usr/local/hbase-0.98.9-hadoop2/conf/hbase.keytab</value> </property> <property> <name>hbase.master.kerberos.principal</name> <value>hbase/[email protected]</value> </property> <property> <name>hbase.master.keytab.file</name> <value>/usr/local/hbase-0.98.9-hadoop2/conf/hbase.keytab</value> </property> </configuration>
修改zk-jaas.conf
Client { com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true useTicketCache=false keyTab="/usr/local/hbase-0.98.9-hadoop2/conf/hbase.keytab" principal="hbase/[email protected]"; };
启动hbase
启动hbase 如遇:
2015-04-11 14:20:58,538 FATAL [master:kbhbase1:60000] master.HMaster: Unhandled exception. Starting shutdown. org.apache.hadoop.security.AccessControlException: Permission denied: user=hbase, access=WRITE, inode="/hbase":root:supergroup:drwxr-xr-x
我的hbase是直接从tar.gz包解压安装的,所有的都有linux的root跑。这个错误信息表示在hbase使用的默认用户“hbase”没有对hdfs文件系统中的/hbase目录的访问权限。 尝试使用
或使用
遇到
rmr: Permission denied: user=admin, access=WRITE, inode="/":root:supergroup:drwxr-xr-x
这里的user,应该是我之前kinit的用户,这个错误也就是说,我当前在kbhbase1这台机器上使用的kerberos身份证是admin/admin,而hdfs的/hbase目录属于root用户,所以没有权限对它进行更改权限的操作。 所以我添加了一个root/admin
这就ok了 启动成功之后,可以用hbase shell来试一下,当然,在执行hbase shell前,事先要有kinit一下,你可以使用刚才建的root/admin,或者别的。
在kbjavatest1安装kerberos客户端,从kbhbase1上拷贝hbase-site.xml到本机的某个目录。连接kadmin工具创建用户javatest,并生成keytab文件:
创建java project,添加对hbase jar的引用,编写java代码,运行时注意把刚才拷贝来的hbase-site.xml放到运行的classpath中(eclipse可以通过Run Configurations>>Classpath配置)
public class Test1 { public static void main(String[] args) throws IOException { // TODO Auto-generated method stub Configuration conf = HBaseConfiguration.create(); conf.set("hadoop.security.authentication", "kerberos"); UserGroupInformation.setConfiguration(conf); UserGroupInformation.loginUserFromKeytab("[email protected]", "/root/Downloads/javatest.keytab"); // HTable t = new HTable(conf, "test"); Scan s = new Scan(); ResultScanner rs = t.getScanner(s); try{ for(Result r:rs){ for(Cell cell:r.rawCells()){ System.out.println("Row: "+new String(CellUtil.cloneRow(cell))); System.out.println("CF: "+new String(CellUtil.cloneFamily(cell))); System.out.println("Qualifier: "+new String(CellUtil.cloneQualifier(cell))); System.out.println("Value: "+new String(CellUtil.cloneValue(cell))); } } }finally{ t.close(); } System.out.println("Done!"); }