任何撰寫 YARN 應用程式的人都需要了解這個流程,才能撰寫短暫的應用程式或長駐服務。他們也需要在早期開發階段開始在安全叢集中進行測試,才能撰寫實際可用的程式碼。
YARN 資源管理員 (RM) 和節點管理員 (NM) 合作執行使用者的應用程式,並具有該使用者的身分和存取權限。
(主動)資源管理員
在叢集中尋找空間來部署應用程式的核心,即應用程式主控程式 (AM)。
要求該節點上的 NM 分配一個容器,並在其中啟動 AM。
與 AM 通訊,以便 AM 可以要求新的容器,並操作/釋放目前的容器,以及提供有關已分配和正在執行的容器的通知。
節點管理員
本地化資源:從 HDFS 或其他檔案系統下載到本機目錄。這是使用附加到容器啟動內容的委派權杖來完成的。(對於非 HDFS 資源,使用其他憑證,例如叢集組態檔中的物件儲存登入詳細資料)
以使用者身分啟動應用程式。
監控應用程式並向 RM 報告失敗。
若要在叢集中執行程式碼,YARN 應用程式必須
有一個用戶端應用程式,設定 ApplicationSubmissionContext
,詳細說明要啟動的內容。這包括
有一個應用程式主控程式,在啟動時,會向 YARN RM 註冊並偵聽事件。任何希望在其他容器中執行工作的 AM 都必須向 RM 提出要求,並在分配時建立一個 ContainerLaunchContext
,其中包含要執行的命令、執行命令的環境、要本地化的二進位檔和所有相關的安全憑證。
即使 NM 處理本地化程序,AM 本身也必須能夠擷取啟動時提供的安全憑證,以便它本身可以與 HDFS 和任何其他服務一起使用,並將部分或全部這些憑證傳遞給啟動的容器。
YARN 應用程式所需的委派權杖必須從以驗證使用者身分執行的程式取得。對於 YARN 應用程式,這表示啟動應用程式的使用者。這是 YARN 應用程式中必須執行的用戶端部分
UserGroupInformation
登入。ApplicationSubmissionContext
中的 ContainerLaunchContext
。需要哪些權杖?通常,至少需要一個權杖來存取 HDFS。
應用程式必須向它打算互動的所有檔案系統要求委派權杖,包括叢集的主要 FS。FileSystem.addDelegationTokens(renewer, credentials)
可用於收集這些權杖;對於不發出權杖的檔案系統(包括非 Kerberos HDFS 叢集),這是一個空操作。
與其他服務(例如 Apache HBase 和 Apache Hive)通訊的應用程式必須使用這些服務的函式庫從這些服務要求權杖,以取得委派權杖。所有權杖都可以新增至同一組認證,然後儲存至位元組緩衝區以供提交。
應用程式時序伺服器也需要委派權杖。這會在 AM 啟動時自動處理。
當應用程式主控程式啟動,以及任何觸發使用者登入的 UGI/Hadoop 作業呼叫時,UGI 類別會自動載入儲存在環境變數 HADOOP_TOKEN_FILE_LOCATION
所指定檔案中的所有權杖。
這會在不安全的叢集和安全叢集上發生,即使應用程式使用 keytab,也會在安全叢集上發生。為什麼?因為用於驗證應用程式與 YARN RM 的 AM/RM 權杖總是透過這種方式提供。
這表示您在安全和不安全的叢集之間有相對類似的流程。
在 AM 啟動期間,登入 Kerberos。呼叫 UserGroupInformation.isSecurityEnabled()
會觸發此作業。
透過呼叫 UserGroupInformation.getCurrentUser().getCredentials()
列舉目前使用者的認證。
篩選出 AMRM 權杖,產生一組新的認證。在不安全的叢集中,認證清單現在會是空的;在安全叢集中,它們將包含
將所有要啟動的容器的認證設定為此(可能是空的)認證清單。
如果要更新的令牌的篩選清單不為空,請啟動執行緒以更新它們。
令牌會過期:它們的使用壽命有限。應用程式若要在令牌過期日期後使用令牌,必須在令牌過期前更新令牌。
Hadoop 會在需要時自動設定委派令牌更新執行緒,即 DelegationTokenRenewer
。
應用程式有責任更新 AMRM 和時序令牌以外的所有令牌。
以下是不同的策略
不要依賴應用程式的使用壽命短到不需要更新令牌。對於使用壽命總是可以用分鐘或數十分鐘來衡量的應用程式,這是一個可行的策略。
啟動背景執行緒/執行器以定期更新令牌。這是大多數 YARN 應用程式所執行的動作。
AM/RM 令牌會自動更新;RM 會在配置
訊息中傳送新的令牌給 AM。請參閱 AMRMClientImpl
類別以查看此程序。您的 AM 程式碼不需要擔心此程序
即使應用程式定期更新令牌,如果 AM 發生故障並重新啟動,它會從原始的 ApplicationSubmissionContext
重新啟動。那裡的令牌可能已過期,因此即使在向其他服務傳遞憑證之前,本機化也可能會失敗。
如何解決此問題?YARN 資源管理員會在需要時為節點管理員取得新的令牌。
更精確地說
這主要是長駐服務的問題(請參閱下方)。
非受控應用程式主控程式並非在 RM 和 NM 設定的容器中啟動,因此無法在啟動時自動擷取 AM/RM 令牌。YarnClient.getAMRMToken()
API 允許非受控 AM 要求 AM/RM 令牌。請參閱 UnmanagedAMLauncher
以取得詳細資訊。
HADOOP_USER_NAME
在非安全叢集上,應用程式將以節點管理員帳戶的身分執行,例如 yarn
或 mapred
。預設情況下,應用程式會以該使用者存取 HDFS,且具有不同的起始目錄,以及在稽核記錄和檔案系統擁有者屬性中識別的不同使用者。
可透過讓客戶端識別預期應用程式執行的 HDFS/Hadoop 使用者的身分來避免此問題。這不會影響作業系統層級的使用者或應用程式對本機的存取權限。
當 Kerberos 已停用時,Hadoop 會先從環境變數 HADOOP_USER_NAME
,然後從作業系統層級的使用者名稱(例如系統屬性 user.name
)擷取使用者的身分。
YARN 應用程式應透過設定此環境變數來傳播啟動應用程式的使用者的使用者名稱。
Map<String, String> env = new HashMap<>(); String userName = UserGroupInformation.getCurrentUser().getUserName(); env.put(UserGroupInformation.HADOOP_USER_NAME, userName); containerLaunchContext.setEnvironment(env);
請注意,此環境變數會在所有透過 Hadoop 函式庫與 HDFS 對話的應用程式中擷取。也就是說,如果已設定,則此環境變數會是 HBase 和在已設定此環境變數的 YARN 容器環境中執行的其他應用程式所擷取的身分。
HADOOP_TOKEN_FILE_LOCATION
Apache Oozie 可以透過取得所有相關憑證、將其儲存到本機檔案系統中的檔案,然後在環境變數 HADOOP_TOKEN_FILE_LOCATION
中設定此檔案的路徑,在安全叢集上啟動應用程式。這當然是 YARN 在啟動容器中傳遞的相同環境變數,且內容類似:包含憑證的位元組陣列。
不過,在此情況下,環境變數會在執行 YARN 客戶端的環境中設定。此客戶端必須使用已儲存在命名檔案中的令牌資訊,而不是取得任何自己的令牌。
載入令牌檔案是自動的:UGI 會在使用者登入期間執行此動作。
然後,客戶端負責將相同的憑證傳遞到 AM 啟動內容中。這可以透過傳遞目前的憑證來完成。
credentials = new Credentials( UserGroupInformation.getCurrentUser().getCredentials());
可以將應用程式時間軸伺服器部署為安全服務,在這種情況下,應用程式將需要相關的權杖來進行驗證。如果在安全叢集中啟用了 ATS,則會在 YarnClientImpl
中自動處理此程序。類似地,AM 端的 TimelineClient
YARN 服務類別會透過 ATS 的 SPNEGO 驗證 REST API 自動管理權杖更新。
如果您需要透過 Oozie 為 YARN 應用程式啟動準備一組委派權杖,則可以透過時間軸客戶端 API 來完成。
try(TimelineClient timelineClient = TimelineClient.createTimelineClient()) { timelineClient.init(conf); timelineClient.start(); Token<TimelineDelegationTokenIdentifier> token = timelineClient.getDelegationToken(rmprincipal)); credentials.addToken(token.getService(), token); }
應用程式可能希望在終止其 AM 時取消其持有的權杖。這可確保權杖不再有效。
這不是強制性的,而且由於無法保證 YARN 應用程式會正常關閉,因此無法保證在應用程式終止期間權杖會永遠存在。但是,它確實減少了權杖被竊取的漏洞時間。
所有權杖更新都有時間限制,時間一到權杖就不會更新,導致應用程式停止運作。這介於 72 小時到 7 天之間。
任何打算長期執行的 YARN 服務必須具備更新憑證的策略。
以下是策略
會為應用程式在每個節點上使用提供一個 Keytab。
這是透過
UserGroupInformation.loginUserFromKeytab()
載入憑證。Keytab 必須位於安全的目錄路徑中,只有服務(和其他受信任帳戶)可以讀取它。分發成為叢集運作團隊的責任。
這實際上是所有靜態 Hadoop 應用程式取得其安全憑證的方式。
將 Keytab 上傳到 HDFS。
啟動 AM 時,Keytab 會列為要本機化到 AM 容器的資源。
應用程式主控程式會設定為 Keytab 的相對路徑,並使用 UserGroupInformation.loginUserFromKeytab()
登入。
當 AM 啟動容器時,它會將 Keytab 的 HDFS 路徑列為要本機化的資源。
它將 HDFS 委派權杖新增到容器啟動內容,以便可以將 keytab 和其他應用程式檔案本機化。
啟動的容器必須透過 UserGroupInformation.loginUserFromKeytab()
自行登入。UGI 負責登入,並排程背景執行緒定期讓使用者重新登入。
Hadoop IPC 和 REST API 會自動處理權杖建立,容器會透過 Kerberos 保持登入狀態,直到其整個期間結束為止。
這可以避免在整個叢集中為特定服務安裝 keytab 的管理工作。
它確實需要用戶端有權存取 keytab,而且因為它會上傳到分散式檔案系統,所以必須透過適當的路徑權限/ACL 來加以保護。
由於所有容器都可以存取 keytab,因此執行在容器中的所有程式碼都必須受信任。惡意程式碼(或逃離某種沙盒的程式碼)可以讀取 keytab,因此可以在金鑰過期或被撤銷之前存取叢集。
這是 Apache Slider(孵化中)實作的策略。
用戶端會將 keytab 上傳到 HDFS。
啟動 AM 時,Keytab 會列為要本機化到 AM 容器的資源。
應用程式主控程式會設定為 keytab 的相對路徑,並使用 UserGroupInformation.loginUserFromKeytab()
登入。UGI 程式碼路徑仍會自動載入檔案參考,方法是透過 $HADOOP_TOKEN_FILE_LOCATION
,這就是 AMRM 權杖的取得方式。
當 AM 啟動容器時,它會取得該容器所需的所有委派權杖,並將它們新增到容器的容器啟動內容。
啟動的容器必須從 $HADOOP_TOKEN_FILE_LOCATION
載入委派權杖,並使用它們(包括更新),直到無法再更新為止。
AM 必須實作一個 IPC 介面,允許容器要求一組新的委派權杖;這個介面本身必須使用驗證,理想情況下還要使用有線加密。
在委派權杖即將過期之前,執行在容器中的程序必須透過 IPC 通道向應用程式主控程式要求新的權杖。
當容器需要新的權杖時,AM 會使用 keytab 登入,並向各種叢集服務要求新的權杖。
(請注意,更新作業有另一種方向:從 AM 到容器,同樣是透過 AM 和容器之間實作的任何 IPC 通道)。演算法的其餘部分:AM 透過 IPC 將重新產生的權杖傳遞給容器。
這是 Apache Spark 1.5+ 使用的策略,容器和 AM 之間使用基於 Netty 的通訊協定來進行權杖更新。
由於只有 AM 可以直接存取 keytab,因此它的曝險程度較低。執行在容器中的程式碼只能存取委派權杖。
但是,這些容器可以透過容器啟動時傳入的權杖存取 HDFS,因此可以存取用於啟動 AM 的 keytab 副本。雖然 AM 可以刪除啟動時的 keytab,但這麼做會讓 YARN 無法在任何故障後成功重新啟動 AM。
對於嚴格的作業團隊來說,這個策略可能是唯一可以接受的策略:執行在持有 Kerberos TGT 的帳戶上的用戶端程序會與所有需要的叢集服務協商新的委派權杖,然後透過某些 RPC 介面將權杖推播到應用程式主控程式。
這需要定期重新執行客戶端程序;cron 或 Oozie 作業可以執行此作業。AM 需要實作 IPC API,可透過此 API 提供更新的權杖。(請注意,由於 Oozie 可以自行收集權杖,因此更新程式應用程式在每次執行時所需要執行的動作,就是設定與 AM 的 IPC 連線,並傳遞目前使用者的憑證)。
YARN 提供一種直接的方法,讓每個 YARN 應用程式 SPNEGO 驗證網頁:RM 在資源管理員代理程式中實作 SPNEGO 驗證,並將 Yarn 應用程式的 Web UI 存取權限限制為僅限 RM 代理程式。有兩種方法可以執行此作業
YARN 應用程式的 Web 伺服器應在設定其 Web UI 時載入 AM 代理程式篩選器(請參閱 AmFilterInitializer
類別);此篩選器會將來自 RM 代理程式主機以外任何主機的所有 HTTP 要求重新導向至 RM 代理程式,客戶端應用程式/瀏覽器必須重新對其發出要求。客戶端會針對 RM 代理程式的主體(通常為 yarn
)進行驗證,並在驗證後轉發其要求。
此選項已知有下列弱點
AM 代理程式篩選器只會檢查 RM 代理程式的 IP/主機,因此執行於這些主機上的任何應用程式都可以不受限制地存取 YARN 應用程式的 Web UI。這就是為什麼在安全叢集中,代理程式主機必須執行於未執行最終使用者程式碼的叢集節點上(亦即未執行 YARN 節點管理員,因此未排程 YARN 容器;也不支援最終使用者登入)。
RM 代理程式與 Yarn 應用程式之間的 HTTP 要求目前未加密。也就是說:不支援 HTTPS。
預設情況下,YARN 應用程式 Web UI 並未加密 (例如 HTTPS)。由應用程式提供 HTTPS 支援。這可以完全獨立執行,使用來自公用 CA 或 RM 或 JVM 設定為信任來源的有效 HTTPS 憑證。或者,RM 可以作為有限 CA,並提供應用程式可使用的憑證,而該憑證僅被 RM 代理程式接受,而不被其他用戶端 (例如 Web 瀏覽器) 接受。這很重要,因為無法保證應用程式不會竊取任何已發行的憑證或執行其他惡意行為。RM 發行的憑證將 (a) 過期,(b) 主旨包含 CN=<application-id>
,而不是典型的 CN=<hostname|domain>
,以及 (c) 由 RM 生成的自簽名 CA 憑證發行。
若要讓應用程式利用此功能,它只需將提供的金鑰庫載入其所選的 Web 伺服器。金鑰庫的位置可在 KEYSTORE_FILE_LOCATION
環境變數中找到,其密碼則在 KEYSTORE_PASSWORD
環境變數中。只要 yarn.resourcemanager.application-https.policy
未設定為 NONE (請參閱下表),且提供了 HTTPS 追蹤網址,這將可用。
此外,應用程式可透過 HTTPS 雙向驗證來驗證 RM 代理程式實際上是 RM。除了提供的金鑰庫外,RM 代理程式的用戶端憑證還提供了一個信任庫。透過載入此信任庫並在其所選的 Web 伺服器中啟用 needsClientAuth
(或等效功能),AM 的 Web 伺服器應自動要求用戶端 (即 RM 代理程式) 提供受信任的憑證,否則將會連線失敗。這可確保只有用戶端驗證過的 RM 代理程式才能存取它。
yarn.resourcemanager.application-https.policy |
行為 |
---|---|
NONE |
RM 什麼都不會做。 |
LENIENT |
RM 將產生並提供金鑰庫和信任庫給 AM,AM 可以自由地在追蹤網址 Web 伺服器中使用它來進行 HTTPS。RM 代理程式仍允許 HTTP 連線到選擇不使用 HTTPS 的 AM。 |
STRICT |
這與 LENIENT 相同,但 RM 代理程式只允許 HTTPS 連線到 AM;HTTP 連線將被封鎖,並向使用者顯示警告頁面。 |
預設值為 OFF
。
與 YARN 應用程式的已註冊 Web UI 在同一個連接埠上執行的 YARN REST API 會在 RM 代理程式中透過 SPNEGO 驗證自動驗證。
除非在 YARN 應用程式本身中實作,否則在不同埠上提出的任何 REST 端點(以及任何網路 UI)都不支援 SPNEGO 驗證。
以下是 YARN 應用程式在 YARN 集群中成功啟動必須執行的核心動作檢查清單。
[ ]
用戶端透過 UserGroupInformation.isSecurityEnabled()
檢查安全性是否已啟用
在安全叢集中
[ ]
如果未設定 HADOOP_TOKEN_FILE_LOCATION
,用戶端會取得本機檔案系統的委派權杖,並將 RM 主體設定為更新者。
[ ]
如果未設定 HADOOP_TOKEN_FILE_LOCATION
,用戶端會取得 YARN 應用程式中所有其他服務的委派權杖。
[ ]
如果設定了 HADOOP_TOKEN_FILE_LOCATION
,用戶端會使用目前使用者的憑證作為要新增至容器啟動內容的所有權杖的來源。
[ ]
用戶端會在 AM ContainerLaunchContext.setTokens()
上設定所有權杖。
[ ]
建議:如果在用戶端的環境中設定,用戶端會在 AM 的容器啟動內容中設定環境變數 HADOOP_JAAS_DEBUG=true
。
在不安全的叢集中
[ ]
將本機使用者名稱傳播至 YARN AM,因此透過 HADOOP_USER_NAME
環境變數傳播 HDFS 身分。
[ ]
在安全叢集中,AM 會從 HADOOP_TOKEN_FILE_LOCATION
環境變數中擷取安全性權杖(由 UGI 自動執行)。
[ ]
權杖組的副本會經過篩選,以移除 AM/RM 權杖和任何時序權杖。
[ ]
會啟動執行緒或執行器,以定期更新執行緒。
[ ]
建議:應用程式完成時,AM 會取消權杖。
[ ]
要傳遞至容器的權杖會透過 ContainerLaunchContext.setTokens()
傳遞。
[ ]
在不安全的叢集中,傳播 HADOOP_USER_NAME
環境變數。
[ ]
建議:如果在 AM 的環境中設定,AM 會在容器啟動內容中設定環境變數 HADOOP_JAAS_DEBUG=true
。
[ ]
呼叫 UserGroupInformation.isSecurityEnabled()
來觸發安全性設定。
[ ]
會啟動執行緒或執行器,以定期更新執行緒。
[ ]
應用程式開發人員已選擇並實作令牌更新策略:共用 keytab、AM keytab 或用戶端側令牌更新。
[ ]
在安全叢集中,keytab 已存在於 HDFS 中(並已檢查),或存在於用戶端的本機 FS 中,後者必須上傳並新增至要本機化的資源清單。
[ ]
如果儲存在 HDFS 中,應檢查 keytab 權限。如果 keytab 可由目前的使用者以外的原則讀取,請發出警告,並考慮實際上讓啟動失敗(類似於一般的 ssh
應用程式)。
[ ]
用戶端取得 HDFS 委派令牌,並附加至 AM 容器啟動內容
[ ]
AM 透過 loginUserFromKeytab()
以 keytab 中的原則身分登入。
[ ]
(AM 從 HADOOP_TOKEN_FILE_LOCATION
環境變數中擷取 AM/RM 令牌)。
[ ]
對於已啟動的容器,keytab 會傳播,或 AM 會取得/附加所有必要的委派令牌至容器啟動內容,以及 NMs 所需的 HDFS 委派令牌。
要確定 YARN 應用程式在安全叢集中運作,方法很簡單。執行方式為:在安全叢集中進行測試。
即使是單一 VM 叢集,也可以設定啟用安全性。如果這麼做,我們建議將安全性調至最嚴格,使用 SPNEGO 驗證的 Web UI(以及 RM Proxy),以及 IPC 纜線加密。將 kerberos 令牌到期時間設定在 1 小時內,將會及早找出 kerberos 到期問題,因此也建議這麼做。
[ ]
應用程式在安全叢集中啟動。
[ ]
已啟動的應用程式以提交作業的使用者身分執行(提示:記錄 AM 中的 user.name
系統屬性)。
[ ]
在安全叢集中驗證 Web 瀏覽器互動。
[ ]
測試 REST 用戶端互動(GET 作業)。
[ ]
Kerberos 令牌到期後,應用程式繼續執行。
[ ]
如果使用者缺乏 Kerberos 憑證,應用程式不會啟動。
[ ]
如果應用程式支援時序伺服器,請驗證它在安全叢集中發布事件。
[ ]
如果應用程式與其他應用程式整合,例如 HBase 或 Hive,請驗證互動在安全叢集中運作。
[ ]
如果應用程式與遠端 HDFS 叢集通訊,請驗證它可以在安全叢集中這麼做(即用戶端在啟動時為此擷取任何委派令牌)
如果您沒有在安全的 Hadoop 集群中測試您的 YARN 應用程式,它將無法運作。
而且沒有這些測試:您的使用者將會發現您的應用程式無法在安全的集群中運作。
在考慮要投入多少開發工作到 Kerberos 支援時,請牢記這點。