本文主要記錄 cdh hadoop 叢集上配置 hdfs 內建 kerberos 的過程,包括 kerberos 的安裝和 hadoop 相關配置修改說明。
系統環境:
作業系統:centos 6.6
hadoop版本:<code>cdh5.4</code>
jdk版本:<code>1.7.0_71</code>
運作使用者:root
叢集各節點角色規劃為:
cdh1作為master節點,其他節點作為slave節點,我們在cdh1節點安裝kerberos server,在其他節點安裝kerberos client。
确認添加主機名解析到 <code>/etc/hosts</code> 檔案中。
注意:hostname 請使用小寫,要不然在內建 kerberos 時會出現一些錯誤。
在 cdh1 上安裝包 krb5、krb5-server 和 krb5-client。
在其他節點(cdh1、cdh2、cdh3)安裝 krb5-devel、krb5-workstation :
kdc 伺服器涉及到三個配置檔案:
配置 kerberos 的一種方法是編輯配置檔案 /etc/krb5.conf。預設安裝的檔案中包含多個示例項。
說明:
<code>[logging]</code>:表示 server 端的日志的列印位置
<code>[libdefaults]</code>:每種連接配接的預設配置,需要注意以下幾個關鍵的小配置
<code>default_realm = javachen.com</code>:設定 kerberos 應用程式的預設領域。如果您有多個領域,隻需向 [realms] 節添加其他的語句。
<code>ticket_lifetime</code>: 表明憑證生效的時限,一般為24小時。
<code>renew_lifetime</code>: 表明憑證最長可以被延期的時限,一般為一個禮拜。當憑證過期之後,對安全認證的服務的後續通路則會失敗。
<code>clockskew</code>:時鐘偏差是不完全符合主機系統時鐘的票據時戳的容差,超過此容差将不接受此票據。通常,将時鐘扭斜設定為 300 秒(5 分鐘)。這意味着從伺服器的角度看,票證的時間戳與它的偏差可以是在前後 5 分鐘内。
<code>udp_preference_limit= 1</code>:禁止使用 udp 可以防止一個 hadoop 中的錯誤
<code>[realms]</code>:列舉使用的 realm。
<code>kdc</code>:代表要 kdc 的位置。格式是 <code>機器:端口</code>
<code>admin_server</code>:代表 admin 的位置。格式是 <code>機器:端口</code>
<code>default_domain</code>:代表預設的域名
<code>[appdefaults]</code>:可以設定一些針對特定應用的配置,覆寫預設配置。
<code>javachen.com</code>: 是設定的 realms。名字随意。kerberos 可以支援多個 realms,會增加複雜度。大小寫敏感,一般為了識别使用全部大寫。這個 realms 跟機器的 host 沒有大關系。
<code>master_key_type</code>:和 <code>supported_enctypes</code> 預設使用 <code>aes256-cts</code>。java 使用 <code>aes256-cts</code> 驗證方式需要安裝 jce 包,見下面的說明。為了簡便,你可以不使用<code>aes256-cts</code> 算法,這樣就不需要安裝 jce 。
<code>acl_file</code>:标注了 admin 的使用者權限,需要使用者自己建立。檔案格式是:<code>kerberos_principal permissions [target_principal] [restrictions]</code>
<code>supported_enctypes</code>:支援的校驗方式。
<code>admin_keytab</code>:kdc 進行校驗的 keytab。
關于aes-256加密: 下載下傳的檔案是一個 zip 包,解開後,将裡面的兩個檔案放到下面的目錄中:<code>$java_home/jre/lib/security</code>
為了能夠不直接通路 kdc 控制台而從 kerberos 資料庫添加和删除主體,請對 kerberos 管理伺服器訓示允許哪些主體執行哪些操作。通過編輯檔案 /var/lib/kerberos/krb5kdc/kadm5.acl 完成此操作。acl(通路控制清單)允許您精确指定特權。
将 kdc 中的 <code>/etc/krb5.conf</code> 拷貝到叢集中其他伺服器即可。
請确認叢集如果關閉了 selinux。
在 cdh1 上運作初始化資料庫指令。其中 <code>-r</code> 指定對應 realm。
出現 <code>loading random data</code> 的時候另開個終端執行點消耗cpu的指令如 <code>cat /dev/sda > /dev/urandom</code> 可以加快随機數采集。該指令會在 <code>/var/kerberos/krb5kdc/</code> 目錄下建立 principal 資料庫。
如果遇到資料庫已經存在的提示,可以把 <code>/var/kerberos/krb5kdc/</code> 目錄下的 principal 的相關檔案都删除掉。預設的資料庫名字都是 principal。可以使用 <code>-d</code> 指定資料庫名字。
在 cdh1 節點上運作:
關于 kerberos 的管理,可以使用 <code>kadmin.local</code> 或 <code>kadmin</code>,至于使用哪個,取決于賬戶和通路權限:
如果有通路 kdc 伺服器的 root 權限,但是沒有 kerberos admin 賬戶,使用 <code>kadmin.local</code>
如果沒有通路 kdc 伺服器的 root 權限,但是用 kerberos admin 賬戶,使用 <code>kadmin</code>
在 cdh1 上建立遠端管理的管理者:
系統會提示輸入密碼,密碼不能為空,且需妥善儲存。
檢視目前的認證使用者:
也可以直接通過下面的指令來執行:
建立一個測試使用者 test,密碼設定為 test:
擷取 test 使用者的 ticket:
銷毀該 test 使用者的 ticket:
更新 ticket:
抽取密鑰并将其儲存在本地 keytab 檔案 /etc/krb5.keytab 中。這個檔案由超級使用者擁有,是以您必須是 root 使用者才能在 kadmin shell 中執行以下指令:
在 kerberos 安全機制裡,一個 principal 就是 realm 裡的一個對象,一個 principal 總是和一個密鑰(secret key)成對出現的。
這個 principal 的對應物可以是 service,可以是 host,也可以是 user,對于 kerberos 來說,都沒有差別。
kdc(key distribute center) 知道所有 principal 的 secret key,但每個 principal 對應的對象隻知道自己的那個 secret key 。這也是“共享密鑰“的由來。
對于 hadoop,principals 的格式為 <code>username/[email protected]</code>。
通過 yum 源安裝的 cdh 叢集中,namenode 和 datanode 是通過 hdfs 啟動的,故為叢集中每個伺服器節點添加兩個principals:hdfs、http。
在 kcd server 上(這裡是 cdh1)建立 hdfs principal:
<code>-randkey</code> 标志沒有為新 principal 設定密碼,而是訓示 kadmin 生成一個随機密鑰。之是以在這裡使用這個标志,是因為此 principal 不需要使用者互動。它是計算機的一個伺服器帳戶。
建立 http principal:
建立完成後,檢視:
keytab 是包含 principals 和加密 principal key 的檔案。keytab 檔案對于每個 host 是唯一的,因為 key 中包含 hostname。keytab 檔案用于不需要人工互動和儲存純文字密碼,實作到 kerberos 上驗證一個主機上的 principal。因為伺服器上可以通路 keytab 檔案即可以以 principal 的身份通過 kerberos 的認證,是以,keytab 檔案應該被妥善儲存,應該隻有少數的使用者可以通路。
建立包含 hdfs principal 和 host principal 的 hdfs keytab:
建立包含 mapred principal 和 host principal 的 mapred keytab:
注意: 上面的方法使用了xst的norandkey參數,有些kerberos不支援該參數。 當不支援該參數時有這樣的提示:<code>principal -norandkey does not exist.</code>,需要使用下面的方法來生成keytab檔案。
在 cdh1 節點,即 kdc server 節點上執行下面指令:
這樣,就會在 <code>/var/kerberos/krb5kdc/</code> 目錄下生成 <code>hdfs-unmerged.keytab</code> 和 <code>http.keytab</code> 兩個檔案,接下來使用 <code>ktutil</code> 合并者兩個檔案為 <code>hdfs.keytab</code>。
使用 klist 顯示 hdfs.keytab 檔案清單:
驗證是否正确合并了key,使用合并後的keytab,分别使用hdfs和host principals來獲驗證書。
如果出現錯誤:<code>kinit: key table entry not found while getting initial credentials</code>, 則上面的合并有問題,重新執行前面的操作。
拷貝 hdfs.keytab 檔案到其他節點的 /etc/hadoop/conf 目錄
并設定權限,分别在 cdh1、cdh2、cdh3 上執行:
由于 keytab 相當于有了永久憑證,不需要提供密碼(如果修改kdc中的principal的密碼,則該keytab就會失效),是以其他使用者如果對該檔案有讀權限,就可以冒充 keytab 中指定的使用者身份通路 hadoop,是以 keytab 檔案需要確定隻對 owner 有讀權限(0400)
先停止叢集:
在叢集中所有節點的 core-site.xml 檔案中添加下面的配置:
在叢集中所有節點的 hdfs-site.xml 檔案中添加下面的配置:
如果想開啟 ssl,請添加(本文不對這部分做說明):
如果 hdfs 配置了 qjm ha,則需要添加(另外,你還要在 zookeeper 上配置 kerberos):
如果配置了 webhdfs,則添加:
配置中有幾點要注意的:
<code>dfs.datanode.address</code>表示 data transceiver rpc server 所綁定的 hostname 或 ip 位址,如果開啟 security,端口号必須小于 <code>1024</code>(privileged port),否則的話啟動 datanode 時候會報 <code>cannot start secure cluster without privileged resources</code> 錯誤
principal 中的 instance 部分可以使用 <code>_host</code> 标記,系統會自動替換它為全稱域名
如果開啟了 security, hadoop 會對 hdfs block data(由 <code>dfs.data.dir</code> 指定)做 permission check,方式使用者的代碼不是調用hdfs api而是直接本地讀block data,這樣就繞過了kerberos和檔案權限驗證,管理者可以通過設定 <code>dfs.datanode.data.dir.perm</code> 來修改 datanode 檔案權限,這裡我們設定為700
啟動之前,請确認 jce jar 已經替換,請參考前面的說明。
在每個節點上擷取 root 使用者的 ticket,這裡 root 為之前建立的 root/admin 的密碼。
擷取 cdh1的 ticket:
如果出現下面異常 <code>kinit: password incorrect while getting initial credentials</code>,則重新導出 keytab 再試試。
然後啟動服務,觀察日志:
驗證 namenode 是否啟動,一是打開 web 界面檢視啟動狀态,一是運作下面指令檢視 hdfs:
如果在你的憑據緩存中沒有有效的 kerberos ticket,執行上面指令将會失敗,将會出現下面的錯誤:
datanode 需要通過 jsvc 啟動。首先檢查是否安裝了 jsvc 指令,然後配置環境變量。
在 cdh1 節點檢視是否安裝了 jsvc:
然後編輯 <code>/etc/default/hadoop-hdfs-datanode</code>,取消對下面的注釋并添加一行設定 <code>jsvc_home</code>,修改如下:
将該檔案同步到其他節點:
分别在 cdh2、cdh3 擷取 ticket 然後啟動服務:
觀看 cdh1 上 namenode 日志,出現下面日志表示 datanode 啟動成功:
本文介紹了 cdh hadoop 內建 kerberos 認證的過程,其中主要需要注意以下幾點:
配置 hosts,<code>hostname</code> 請使用小寫
確定 kerberos 用戶端和服務端連通
替換 jre 自帶的 jce jar 包
為 datanode 設定運作使用者并配置 <code>jsvc_home</code>
啟動服務前,先擷取 ticket 再運作相關指令