版權聲明:本文為半吊子子全棧工匠(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。