天天看點

從 "org.apache.hadoop.security.AccessControlException:Permission denied: user=..." 看Hadoop 的使用者登陸認證

版權聲明:本文為半吊子子全棧工匠(wireless_com,同公衆号)原創文章,未經允許不得轉載。 https://blog.csdn.net/wireless_com/article/details/51192713

如果遠端送出任務給Hadoop 可能會遇到 "org.apache.hadoop.security.AccessControlException:Permission denied: user=..." , 當然,如果是spark over YARN, 也同樣會遇到類似的問題,例如:

 An error occurred while calling None.org.apache.spark.api.java.JavaSparkContext.

: org.apache.hadoop.security.AccessControlException: Permission denied: user=abel, access=WRITE, inode="/user/abel/.sparkStaging/application_1460633311001_0032":hdfs:hdfs:drwxr-xr-x

hadoop 的使用者鑒權是基于JAAS的,其中hadoop.security.authentication屬性 有simple 和kerberos 等方式。如果hadoop.security.authentication等于”kerberos”,那麼是“hadoop-user-kerberos”或者“hadoop-keytab-kerberos”,否則是“hadoop-simple”。 當使用者登陸的時候,若org.apache.hadoop.security.User為空,那麼說明尚未登入過,調用靜态方法getLoginUser()建立org.apache.hadoop.security.UserGroupInformatio執行個體,在getLoginUser()中又會調用HadoopLoginModule的login()和commit()方法。

在使用了kerberos的情況下,從javax.security.auth.kerberos.KerberosPrincipal的執行個體擷取username。在沒有使用kerberos時,首先讀取hadoop 的系統環境變量,如果沒有的話,對于windows 從com.sun.security.auth.NTUserPrincipal 擷取使用者名,對于類unix 從com.sun.security.auth.UnixPrincipal 中獲得使用者名,然後再看該使用者屬于哪個group,進而完成登陸認證。

基本了解了問題的根源,那麼這個“org.apache.hadoop.security.AccessControlException:Permission denied: user=...”異常資訊是怎麼産生的呢?遠端送出,如果沒有hadoop 的系統環境變量,就會讀取目前主機的使用者名,結果Hadoop叢集中沒有該使用者,是以杯具了。

至于問題的解決,以mac 為例, 将

export HADOOP_USER_NAME = hdfs 

添加到 ~/.bash_profile 中,

 $ source  ~/.bash_profile 

接下來,繼續送出任務到 hadoop 叢集,everything is OK。 

繼續閱讀