接上篇《HBase + Kerberos配置示例(一)》,我們繼續剩下的配置工作。
環境準備
- 安裝hadoop/zookeeper/hbase
我在kbhbase1這個機器上已經安裝好了hadoop,zookeeper,hbase,為了簡單起見所有在東西都跑在這臺機器上。同時檢查了在沒在啟用kerberos的情況下,hbase工作正常。
- 禁用selinux
#vim /etc/sysconfig/selinux 設定SELINUX=disabled,並重啟
- 安裝JCE
從Oracle網站下載JCE(Java Cryptography Extension)補丁,此補丁與AES-256加密有關。下載解壓之後,把得到的兩個jar檔案local_policy.jar,US_export_policy.jar拷貝到$JAVA_HOME/ jre/lib/security下進行覆蓋。
Hadoop配置
建立keytab
- kadmin: addprinc -randkey root/kbhbase1.mh.com@MH.COM
- kadmin: xst -k root.keytab root/kbhbase1.mh.com
這樣就會在kerberos伺服器上建立一個使用者root/kbhbase1.mh.com@MH.COM,其中名字中/之後的部分應該是固定寫法,即主機名+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
- export HADOOP_SECURE_DN_USER=root
- export JSVC_HOME=/usr/local/hadoop-2.6.0/libexec/
關於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/_HOST@MH.COM</value> </property> <property> <name>dfs.namenode.kerberos.https.principal</name> <value>root/_HOST@MH.COM</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/_HOST@MH.COM</value> </property> <property> <name>dfs.secondary.namenode.kerberos.https.principal</name> <value>root/_HOST@MH.COM</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/_HOST@MH.COM</value> </property> <property> <name>dfs.datanode.kerberos.https.principal</name> <value>root/_HOST@MH.COM</value> </property> <property> <name>dfs.web.authentication.kerberos.principal</name> <value>root/_HOST@MH.COM</value> </property> <property> <name>dfs.datanode.require.secure.ports</name> <value>false</value> </property> </configuration>
由於暫時不需要mapreduce,所以相關的設定我就沒配。
啟動hadoop hdfs
- # start-dfs.sh
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上:
- kadmin.local: modprinc -maxrenewlife 1week root/kbhbase1.mh.com@MH.COM
關於kerberos ticket的一些解釋
一個ticket有lifetime,如果需要更長的時間,那麼就需要重複地去renew它,每renew一次,就延長一個lifetime。renew就是可以不用輸入密碼就延長一個ticket的使用時間。 不過,renew這個操作本身也有時間限制,這取決於引數renew_lifetime,比如這個引數設定成7d,那麼也就是說從ticket建立那時開始之後的7天內,你都可以做renew操作(每次renew操作需在ticket尚未過期前做)。
Zookeeper配置
建立keytab
- kadmin: addprinc -randkey zookeeper/kbhbase1.mh.com@MH.COM
- kadmin: xst -k zookeeper.keytab zookeeper/kbhbase1.mh.com
把生成的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/kbhbase1.mh.com@MH.COM"; };
修改java.env
- export JVMFLAGS="-Djava.security.auth.login.config=/usr/local/zookeeper-3.4.6/conf/jaas.conf"
- export JAVA_HOME="/usr/lib/jvm/jdk7"
修改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
HBase配置
建立keytab
- kadmin: addprinc -randkey hbase/kbhbase1.mh.com@MH.COM
- kadmin: xst -k hbase.keytab hbase/kbhbase1.mh.com
將生成的檔案拷貝到hbase配置目錄/usr/local/hbase-0.98.9-hadoop2/conf
修改hbase-env.sh
- export JAVA_HOME=/usr/lib/jvm/jdk7/
- export HBASE_OPTS="-XX:+UseConcMarkSweepGC -Djava.security.auth.login.config=/usr/local/hbase-0.98.9-hadoop2/conf/zk-jaas.conf"
- export HBASE_MANAGES_ZK=false
修改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/_HOST@MH.COM</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/_HOST@MH.COM</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/kbhbase1.mh.com@MH.COM"; };
啟動hbase
- start-hbase.sh
啟動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目錄的訪問許可權。 嘗試使用
- # hadoop fs -chmod -R 777 /hbase
或使用
- # hadoop fs –rmr /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
- kadmin: addprinc root/admin
- # kinit root/admin
- # hadoop fs -chmod -R 777 /hbase
這就ok了 啟動成功之後,可以用hbase shell來試一下,當然,在執行hbase shell前,事先要有kinit一下,你可以使用剛才建的root/admin,或者別的。
Java測試程式
在kbjavatest1安裝kerberos客戶端,從kbhbase1上拷貝hbase-site.xml到本機的某個目錄。連線kadmin工具建立使用者javatest,並生成keytab檔案:
- kinit admin/admin
- kadmin: addprinc -randkey javatest
- kadmin: xst -k javatest.keytab javatest
建立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("javatest@MH.COM", "/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!"); }
送書了,送書了,關注公眾號“程式設計師雜書館”,送出O'Reilly《Spark快速大資料分析》紙質書(亦有一批PDF分享)! —— 2018年12月