天天看點

容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

介紹

有幾個關于如何在 Docker 中運作 Apache Hadoop ®(本文中稱為“Hadoop”)的線上參考,用于示範和測試目的。在之前的一篇博文中,我們描述了如何将Uber 的生産 Hadoop基礎設施容器化,該基礎設施跨越 21,000 多台主機。

HDFS NameNode 是大型多租戶 Hadoop 叢集中對性能最敏感的元件。我們已将 NameNode 容器化推遲到容器化之旅的末尾,以利用從容器化其他 Hadoop 元件中學到的知識。在這篇博文中,我們将分享我們如何将 HDFS NameNode 容器化并為 32 個叢集建構零停機遷移的經驗。

動機

以下是促使我們在優步将 HDFS NameNode 容器化的激勵因素:

  1. 整合到單個部署單元,Docker®容器:在整個 Uber,我們采用了Crane,Uber 的下一代基礎設施堆棧。作為這項工作的一部分,我們正在将容器标準化為部署單元。我們正在維護一個混合部署模型——所有 DataNode 都被容器化,而 HDFS 控制平面節點(NameNodes、ZKFC、JournalNodes)在裸機上使用 Debian 包部署。在 Docker 容器上進行整合意味着減少建構管道的數量并簡化部署過程,進而減少團隊的認知開銷。
  2. 采用下一代硬體:我們現有的 NameNode 伺服器已達到生命周期的盡頭,而 Uber 的 HDFS 叢集需求已經超出了現有伺服器的容量。我們與 Uber Metal 工程團隊中的合作夥伴密切合作,設計和開發了滿足 NameNode 性能要求的伺服器。新一代伺服器與我們建構的新區域中的 Crane 相容。是以,采用這些新伺服器也意味着對容器進行标準化以與 Crane 相容。

挑戰

在我們進行 NameNode 容器化和硬體更新工作的初始階段時,我們預見到以下三個核心技術挑戰:

  1. 服務發現:HDFS 是 Uber 整個批處理分析堆棧的存儲層。大多數用戶端使用一對寫死的 NameNode 主機名(在 hdfs-site.xml 中)通路 HDFS。超過 75 萬個日常分析作業/查詢和數以千計的服務使用 Uber 的此類用戶端(語言、版本、自定義用戶端)的變化使得以可靠的方式執行需要主機名和/或 IP 位址更改的任何遷移變得很麻煩。由于意外行為,任何主機名/IP 更改都會帶來破壞特定用戶端集的風險。HDFS 叢集中的不同元件之間存在一個較小版本的服務發現問題:NameNodes、JournalNodes、ZKFC、DataNodes、HDFS Routers、Observer Namenodes。我們必須設計一種方法來标準化用戶端對 HDFS 及其元件的通路,并使它們能夠适應元件的主機/IP 更改。
  2. 解決性能問題: 每個叢集有 5 億多個塊,我們的 NameNode 配置了超過 250GB 的 Java ®堆大小。Docker中的 Java 因記憶體管理方面的差異而臭名昭著。是以,NameNode 的容器化帶來了額外的風險,可能會降低叢集性能及其服務流量的能力。在遷移過程中,我們不得不小心翼翼地監控堆使用情況和其他重要名額。這導緻我們運作多次負載測試疊代并調整多項設定以遵守我們的 SLA 保證。
  3. 零停機遷移:在優步,我們對遷移期間服務的可用性保持高标準。使用 SLA 将低延遲攝取(某些資料集在 3-6 小時内)到資料湖中,我們無法承受生産 Hadoop 叢集的長時間停機。在過去的 6 年裡,我們在 Hadoop 上執行的任何遷移或更新都沒有停機。為確定我們不會因這項工作而出現任何停機時間,我們必須設計一種遷移政策來避免停機時間并定義復原标準以實作快速緩解。我們将在本博文的後半部分介紹我們是如何構思遷移政策的。

建築學

舊設定涉及HDFS 控制平面元件(Namenodes、JournalNodes 等)的裸機部署。部署過程允許以各種形式在主機上進行更改,包括主機配置、二進制檔案、叢集配置和自動化腳本。部署的可變性經常導緻節點/叢集之間的分歧和手動錯誤。額外的操作開銷、随叫随到的問題和跟蹤更改一直阻礙着我們對 HDFS 控制平面和 HDFS 用戶端進行更改的速度。這種情況還導緻其他需要主機級更新的工作(例如作業系統和核心更新)出現延誤。這種經驗對我們的 HDFS 控制平面新架構和遷移政策産生了重大影響。

很明顯,從長遠來看,以前運作 Namenodes 的模式不會很好。我們從開展研究開始這項工作,其中涉及研究現有名額、運作基準和可行性分析。我們最初的方法涉及獨立(并行)進行 NameNode 硬體更新及其容器化。随着我們在項目的原型階段增強了信心,我們決定将所有努力結合起來并嘗試在一次遷移中進行。為實作這一目标,我們制定了工作戰略,重點關注以下三個進階并行工作流:

  1. 容器部署
  2. 維護服務發現
  3. 規模負載測試

容器部署

Hadoop 工作者

HDFS 控制平面元件需要一組檔案和機密,以及最少的内務管理自動化才能運作。為了滿足這些要求,我們開發了一個名為 Hadoop Worker 的新程式(也部署為容器)。Hadoop Worker 是首批在配置後部署在主機上的 Docker 容器之一。它執行以下操作:

  • Hadoop Worker 知道主機的叢集屬性。它與叢集管理系統(在本部落格中進行了描述)一起使用來填充“主機檔案”(即 dfs.hosts 和 dfs.hosts.exclude)。Worker 定期更新這些檔案以協助叢集管理系統從叢集中添加或停用 DataNode。
  • 它與 Keytab Distribution 系統(在本部落格中進行了描述)一起使用,以生成和設定 HDFS 控制平面元件所需的必要密鑰表。
  • 它為 HDFS 叢集執行一組内務處理任務,例如出于合規原因保留審計日志的備份,以及出于災難恢複和分析目的備份 NameNode fsimage。

HDFS Docker 容器

HDFS 控制平面由一組元件組成:NameNode、ZKFC 和 JournalNodes。每個元件都在其自己的 Docker 容器中運作,該容器位于 3 個主機上:host1:(nn + jn + zkfc),host2:(nn + jn + zkfc),host3:(jn)。我們重用了為 DataNodes 開發的同一個 Docker 鏡像。我們以這樣一種方式對其進行了調整,即可以使用适當的 Docker 運作指令輸入在前台(而不是守護程序)啟動所需的控制平面元件。Docker 鏡像由 Hadoop 二進制檔案、所有 HDFS 叢集的配置和用于解析 UserGroupInformation的自定義高性能NSS 庫組成。必要的環境變量被提供給 Docker run 指令以在部署期間自動配置 *-site.xml 檔案。

我們使 NameNode 以外的容器(包括 Hadoop Worker 和 sidecars)變得輕量級,并将它們的記憶體使用控制在相當小的 ~5GB 範圍内。這使我們能夠将主機上剩餘的可用記憶體提供給 NameNode 容器。例如,最大的生産叢集的 NameNode(擁有 675M+ 塊)在具有 384GB 記憶體的主機上配置了 320GB JVM 堆大小。

圖 1:HDFS NameNode 主機上的容器部署

邊車容器

除了 HDFS 容器,我們還推出了執行輔助任務的邊車容器。其中一個名為jmx-exporter(基于prometheus/jmx_exporter)的 sidecar 處理來自本地 HDFS 容器的 JMX 端點的解析資料,并将它們作為名額公開,以支援我們的監控儀表闆和警報系統。我們還有另一個 sidecar 容器,auditlog-streamer,它從 NameNode 跟蹤審計日志并将它們發送到主機之外進行實時分析。

為了使設定開發人員友好,我們開發了一個 CLI 工具(圍繞 Docker)來執行 HDFS 控制平面節點的常見操作指令。

容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 2:開發人員友好的 CLI

維護服務發現

HDFS 叢集設定由以下主要元件組成:NameNodes(使用 ZKFC)、JournalNodes、ObserverNameNodes、DataNodes;除了直接或通過 HDFS 路由器通路叢集的 HDFS 用戶端。這些元件中的每一個都基于 DNS 查找互相發現。Uber 的所有 HDFS 叢集都通過 Kerberos 進行保護。是以,身份驗證流程涉及DNS 查找。

在過去的幾年裡,我們多次遇到這樣的問題,即在遷移期間更改 NameNode 的主機名和/或 IP 位址導緻大量用戶端(緩存 IP 位址)失敗,或導緻叢集内的身份驗證問題。從過去的經驗中吸取教訓,我們希望盡可能無縫地遷移 HDFS 控制平面節點。為實作這一目标,我們開始草拟由不同 HDFS 元件執行的基于 DNS 的發現。

容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 3:由不同 HDFS 元件執行的基于 DNS 的發現

根據分析,我們設計了兩大類變化:

1.大量用戶端通路NameNodes(或ObserverNameNodes)

具有大量執行個體(用戶端和資料節點)的元件必須使用單個 DNS 記錄解析為多個節點以進行 NameNode 發現。這確定了當有任意數量的 IP 位址可通過 DNS A 記錄解析時,查找 Active NameNode 的邏輯有效。這将啟用遷移過程,例如在啟用 NameNode HA 的叢集中删除現有備用 NameNode 主機之前添加第三個 NameNode 主機。但是,這意味着改變數以萬計的 DataNodes 和 HDFS 用戶端分布在多個批處理和長期運作的應用程式和服務中。

我們更新了HDFS用戶端邏輯,當IP位址解析出現異常時,用戶端重新解析DNS A記錄,確定Kerberos認證正常進行。我們還更新了 DataNode 邏輯,以便它們可以在解析 DNS A 記錄後發現所有 NameNode(包括 Observer NameNode)并與之通信。DataNodes的更新在團隊的掌控之中。

在優步,我們标準化了支援 3 種不同語言(Java、Golang 和 Python)的 HDFS 用戶端。有了支援具有多個 IP 位址的 DNS A 記錄的新更新檔,我們釋出了所有 3 種語言的新用戶端版本。Uber 的絕大部分代碼庫都托管在特定語言的 monorepos 中。我們利用 monorepos 将大多數用戶端更新到新版本。然而,我們不得不在整個公司範圍内投入大約 5 個月的時間來讓所有服務所有者确認并推出他們與更新後的用戶端的服務。從這一點開始,NameNode 的任何底層主機遷移對 DataNode 或 HDFS 用戶端都是透明的。

2. HDFS 控制平面元件之間的發現

如果單個主機的 A 記錄或 IP 位址發生變化,則互相互動的控制平面元件不得失敗。這是因為 Crane 基礎架構中的任何主機都是可替代的——在主機上運作的服務必須可移植到具有不同主機名(A 記錄和 IP)的另一台主機。

我們更新了控制平面元件互相通信的邏輯以支援 DNS CNAME,這樣 IP 位址或 A 記錄的更改就不會導緻失敗。當節點跨主機移動時,DNS CNAME 通過配置更新。

容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 4:用于在 HDFS 元件中發現的 DNS 記錄

作為執行 HDFS 控制平面(NameNodes、JournalNodes 等)實際遷移之前的準備步驟的一部分,我們在所有叢集和應用程式中推出了這兩項重大更改。這使我們能夠靈活地繼續遷移,而不會造成 HDFS 的任何停機和中斷。

規模負載測試

HDFS NameNode 每秒(每秒 RPC 請求)總共看到每個叢集 50k 或每個區域 500k+(每個區域約 10 個生産叢集)操作。随着涉及将 NameNode 移動到新伺服器和容器中的重大遷移,我們對各種操作場景進行了嚴格的負載測試,包括 NameNode 故障轉移、DataNode 停用等。我們選擇使用開源性能測試工具Dynamometer,結合 Uber 的内部負載生成工具 HailStorm。該設定涉及以下内容:

  • 用于在測試 NameNode 上重放生産流量的測力計。生産流量模式來源于現有生産叢集中 NameNode 的審計日志。
  • HailStorm 是使用自定義多程序 Load Generator 設定的。Load Generator 可以生成具有高并發性的任意負載,就好像它們來自數百個不同的 Hadoop 使用者一樣。
  • 測試在新伺服器上使用 Docker 容器部署的 NameNode,連接配接到我們用于生産 NameNode 的監控系統。
容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 5:負載測試設定

該測試設定為我們提供了足夠的靈活性來調整以下三個次元的參數:

  1. 基于我們在 Uber 維護的不同類型的 HDFS 叢集的負載配置檔案(例如,臨時檔案叢集的大量寫入和批處理分析叢集的大量讀取流量)
  2. 負載因子(或重播率因子)可以通過對審計日志中觀察到的生産流量使用乘數來增加測試名稱節點上的負載
  3. 測試持續時間,1 小時到 1 天

我們使用上述參數和收集的名額的各種組合運作了幾次負載測試疊代。值得一提的名人包括:

  • 以 2 倍重放率因子重放 1 小時的生産流量,以評估測試 NameNode 是否能夠處理額外的工作負載。
  • 重制 1 天的生産流量行為以及 HailStorm 測試,以模拟計劃批處理工作負載的典型周期性峰值流量。HailStorm 測試在每小時 10 分鐘的視窗内對 NameNode 施加高達每秒約 100,000 次操作的壓力。下面的圖 6 和圖 7 展示了該測試疊代的結果。
容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 6:在負載測試期間監控 RpcQueueTimeNumops

容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 7:在負載測試期間監視 RpcQueueTimeAvgTime

在測試期間,我們密切監視從測試 NameNode JMX 端點收集的關鍵名額。我們密切關注 NameNode rpc-metrics、 RpcQueueTimeNumOps 和 RpcQueueTimeAvgTime 等。通過生成的負載測試,我們觀察到新伺服器上的容器化 NameNode 可以處理高達每秒約 110k 操作的峰值負載。同時,在 24 小時内将延遲始終保持在 100 毫秒以下。這些結果非常令人滿意,它讓我們有足夠的信心繼續遷移。

建構遷移

這項工作中最具挑戰性的部分是提出一個對 Hadoop 的 1000 多個客戶透明的無縫遷移戰略。經過多次設計讨論和失敗嘗試後,我們設計了下面圖 8 中描述的遷移政策。每個 HDFS 叢集都有 3 個伺服器來托管控制平面節點。整個過程包括 4 個步驟,其中每個節點都努力從一台主機移動到另一台主機。

容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 8:遷移過程

遷移可能導緻的事件會對整個批處理分析堆棧産生重大影響。是以,我們對遷移過程非常細緻。受The Checklist Manifesto這本書的啟發,團隊共同定義了一個詳盡的項目清單,以在遷移的每個階段進行驗證。整個檢查清單有 60 多個項目,包括但不限于:檢查容器版本、驗證元件健康名額、確定元件間連接配接以及證明服務日志。我們開發了腳本來運作清單的各個部分,以減少工程師的認知開銷。

這個政策被證明是非常有益的:

  1. 該清單幫助定義了遷移的每個步驟的成功和失敗标準。
  2. 在遷移過程的任何階段都可以進行復原。清單和标準提供了明确的指導方針,以決定是復原還是向前修複。
  3. 該過程保證在任何時間點,叢集中都有一個 Active NameNode,并且使用Quorum Journal Manager的叢集的可用性不會受到影響。此外,它保證通路 HDFS 的用戶端不會因為節點被遷移到不同的主機而出現降級。

包括測試、暫存、預生産和生産叢集,我們有 32 個叢集要遷移。通過這種政策,我們能夠在遷移結束時每周遷移 4 個叢集。整個遷移過程耗時約 3 個月,包括解決我們未預料到的問題所花費的時間。整個遷移已完成,對生産 Hadoop 客戶沒有影響。

讓我們感到驚訝的問題

就像其他大型系統檢修一樣,我們在遷移過程中遇到了讓我們措手不及的問題。以下是值得注意的:

  1. 異構硬體引入的故障:自 2018 年底以來,我們通過引入 ObserverNameNodes 來擴充 HDFS,以支援來自 Presto 等服務的天文數量的讀取請求Ⓡ. 我們的遷移過程涉及 HDFS 元件在不同代硬體上的階段。在遷移的 D 階段,我們看到了活動 NameNode 性能和延遲方面的重大改進。然而,對于我們一些最繁忙的叢集,我們注意到在舊硬體上運作的備用 NameNode 和 ObserverNameNode 在消耗來自 JournalNodes 的編輯日志方面開始顯着落後(而且在舊硬體上運作的 JournalNodes 可能無法趕上活動 NameNode 編輯日志寫入,我們沒有遇到這種情況,但這可能是一種可能性)。這導緻用戶端從陳舊的 ObserverNameNode 讀取資料時出現用戶端故障。發生這種情況是因為叢集中的不同元件使用了異構硬體。為了緩解這個問題,
  2. Kerberos 繼續讓我們感到驚訝:作為我們擴充 HDFS 戰略的一部分,我們為一部分用例引入了基于 HDFS路由器的聯邦。我們的主要重點是讓服務發現在 HDFS 叢集内工作,并為直接通路 HDFS 的用戶端工作。但是,我們錯過了使用 Kerberos 進行身份驗證以通路 HDFS NameNode 的路由器。當 NameNode 從一台主機移動到另一台主機時,路由器會看到主體名稱發生變化(hdfs/${hostname-fqdn} 主體)。當路由器輪詢 NameNode 健康狀态時,這會導緻 NameNode主體驗證失敗。當我們強化遷移政策時,這個問題出現在我們的預生産環境中。
  3. 自動化幹擾遷移:在優步,我們已經實作了 HDFS 資料節點的高度自動化。DataNodes 不斷地通過自動化退役,而無需任何人工參與來平衡叢集容量、主機更新和硬體維修。在任何給定時間點看到 DataNode 停用是很常見的(參見下面的圖 9)。與 NameNode 遷移重疊的自動 DataNode 退役增加了 NameNode 的啟動時間。我們發現,由于 DataNode 退役,NameNode 無法獲得必要的塊報告百分比。這導緻 NameNode 長時間處于安全模式。為了緩解這種情況,我們在遷移 NameNode 時暫停了 DataNode 自動化。
容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 9:DataNodes 在 2022 年底假期被自動化退役

概括

容器化 HDFS NameNode 标志着 Uber 資料團隊的一個巨大裡程碑。截至今天,整個 Hadoop 和更大的資料基礎設施都在 Docker 容器中運作。NameNode 等複雜元件、DataNode 和 NodeManagers 等大型機群以及 350,000 多個獨特的日常 YARN 應用程式在容器中運作。将不可變的基礎設施與容器相結合,促進了更好的自動化,團隊每天都能繼續從中受益。

遷移到新硬體以及容器化工作帶來了顯着的性能改進。從下面的圖 10 和 11 可以看出,我們的 Namenode 延遲已經提高了 10 倍(平均約 200 毫秒到約 20 毫秒)。這幫助我們增加了流量并減少了我們為支援更大的用例而進行的整體工程工作。每隔幾年,我們就會發現自己處于某種救火模式的變體中,以控制 NameNode 延遲和擴充 HDFS。由于我們迄今為止所做的工作,我們已經看到随叫随到的負擔大大減少,進而結束了我們的消防季節。

容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 10:遷移前的 RpcQueueTimeAvgTime

容器化野獸——Uber 基礎設施中的 Hadoop NameNode (譯文-來自:Uber)

圖 11:遷移後的 RpcQueueTimeAvgTime

有了更多的喘息時間,我們目前正專注于資料團隊的下一組戰略項目。一個項目是在我們所有的叢集中采用具有通用高密度磁盤的伺服器類型,以提高存儲效率。目前我們在不同的叢集中使用不同的伺服器類型來滿足不同的吞吐量需求。我們還正在進行工作,通過緩存和基于資料通路頻率的叢集内的智能資料托管來提高每 PiB 存儲的 IO。我們還緻力于抽象化 HDFS API 背後的雲對象存儲,以促進 Uber 的雲之旅。

緻謝

這篇文章中描述的工作隻有在 Uber 多個團隊的工程師們的不懈努力下才能實作。我們要感謝所有在我們的旅程中支援我們的人,也感謝所有審閱和協助改進本文的人。

Apache Hadoop® 和 Hadoop® 是 Apache Software Foundation 在美國和/或其他國家/地區的注冊商标或商标。

Debian 是 Software in the Public Interest, Inc. 擁有的注冊商标。Docker 和 Docker 徽标是 Docker, Inc. 在美國和/或其他國家/地區的商标或注冊商标。Docker, Inc. 和其他各方也可能擁有此處使用的其他條款的商标權。

Java 是 Oracle 和/或其附屬公司的注冊商标。

作者:

Mithun (Matt) Mathew

Matt is a Sr. Staff Engineer on the Data team at Uber. He currently leads the initiative to containerize and automate Data infrastructure at Uber. He often forays into the security aspects of Data infrastructure.

Prabhat Jha

Prabhat Jha is a Software Engineer II on the Data (Hadoop) team at Uber. He currently works on deployment and automation of Data infrastructure at Uber, and worked on containerization of NameNode.

Jing Zhao

Jing Zhao is a Sr. Staff Engineer on the Data team at Uber. He is a committer and PMC member of Apache Hadoop and Apache Ratis.

Yuru Liu

Yuru Liu is a Senior Software Engineer on the Data (Hadoop) team at Uber. He currently works on the containerization of HDFS Namenode, HDFS client, and observability of Data infrastructure at Uber.

Nishith Shetty

Nishith Shetty is a Software Engineer II on the Data Infrastructure team at Uber. He currently works on the containerization and automation of HDFS Namenodes.

Fengnan Li

Fengnan Li is an Engineer Manager with the Data Infrastructure team at Uber. He is an Apache Hadoop Committer.

Posted by Mithun (Matt) Mathew, Prabhat Jha, Jing Zhao, Yuru Liu, Nishith Shetty, Fengnan Li

出處:https://www.uber.com/en-US/blog/hadoop-namenode-container/

繼續閱讀