假設遠程提交任務給Hadoop 可能會遇到 "org.apache.hadoop.security.AccessControlException:Permission denied: user=..." , 當然,假設是spark over YARN, 也相同會遇到相似的問題,比如:
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 獲取username。對於類unix 從com.sun.security.auth.UnixPrincipal 中獲得username,然后再看該用戶屬於哪個group,從而完畢登陸認證。
基本理解了問題的根源,那么這個“org.apache.hadoop.security.AccessControlException:Permission denied: user=...”異常信息是怎么產生的呢?遠程提交,假設沒有hadoop 的系統環境變量。就會讀取當前主機的username,結果Hadoop集群中沒有該用戶。所以杯具了。
至於問題的解決,以mac 為例。 將
export HADOOP_USER_NAME = hdfs
加入到 ~/.bash_profile 中。
$ source ~/.bash_profile
接下來。繼續提交任務到 hadoop 集群,everything is OK。