HDFS 2.x 升級 3.x 在車好多的實踐

語言: CN / TW / HK

本文來自車好多大資料離線儲存團隊相關同事的投稿,本文作者: 車好多大資料離線儲存團隊:馮武、王安迪。

升級的背景

HDFS 叢集作為大資料最核心的元件,在公司承載了DW、AI、Growth 等重要業務資料的儲存重任。隨著業務的高速發展,資料的成倍增加,HDFS 叢集出現了爆炸式的增長,使用率一直處於很高的水位。同時 HDFS檔案數持續增長導致Namenode 壓力過大、RPC 過多,整體效能下降。 作為叢集 admin ,保證叢集穩定、提高資源利用率為公司降本增效是我們最主要的責任。面對儲存增長帶來的挑戰,我們做了一些工作:

1、HDFS 賬單。

通過統計使用者使用的HDFS 資源,形成使用者賬單。根據賬單來push 使用者清理自己的資料,下沉HDFS治理壓力。

2、HDFS小檔案合併工具

為使用者提供解決 HDFS 小檔案的工具,push 使用者對owner 的目錄進行合併,下沉HDFS治理壓力。

3、資料冷熱分析。

根據FSImage分析HDFS目錄中資料的冷熱程度,為使用者提供清理資料的參考依據。

4、建設HDFS 冷叢集

前面幾個措施雖然緩解了一部分壓力,但是有些資料,雖然是冷資料但是需要長週期儲存不能刪除,該如何降低這部分資料的儲存成本?我們想到了 HDFS 3.x 的EC 特性。相比傳統的3 副本,在相同的容錯能力下,資料儲存代價由300% 降低到150% (RS-6-3),可以顯著降低HDFS 冷資料的儲存成本,達到降本增效的目標。 我們內部使用的版本是 HDP-2.6.5 對應 Apache 2.7.3 版本,無法支援這些新特性。我們為此基於HDFS 3.1 EC 建設了HDFS 冷叢集, 資料節點採用了儲存增強機型,用來儲存歸檔的冷資料。

隨著使用的頻繁,冷、熱叢集分離的方案,確實節約了很大一部分儲存資源,也暴露出了很多問題,最為明顯的有以下幾個:

1、冷資料讀取代價大

由於冷資料和 熱資料分佈在兩套HDFS 叢集,為了避免使用者讀取兩套叢集資料增加的使用難度,我們選用了冷資料轉熱的方案。即,當用戶提出要讀取冷資料,需要將要讀取的資料通過distcp 恢復到熱叢集。這種方案受限於資料大小、網路寬頻(跨機房部署),所以讀取冷資料響應時間不能保證。 往往使用者提出需求後需要admin在配合上需要投入很多精力。

2、計算資源浪費

儘管都是使用了大儲存機型,儲存利用率提升了,但是冷叢集幾乎沒有計算任務,導致計算資源、網路資源長期利用率低,造成不少的浪費。

基於以上思考,升級HDFS 到3.x 後主要有3個方面的收益:

  • 使用 EC 既可以叢集內部轉換成EC,又能把計算資源利用起來,能較好的解決我們當前 冷資料 的痛點
  • 使用 HDFS RBF 可以有效緩解檔案數增長的壓力
  • 整合 Namenode一致性讀 後可以較好的解決 Presto 大規模查詢 HDFS 造成 RPC 延時的問題,為Namenode 減負

另外 HDFS 3.x 還有 Storage Policy、DataNode Disk Balance等重要特性可以發揮很大的價值,為此我們開始了HDFS的升級調研。

升級目標

此次升級目標主要有四點:

  • 解決 冷資料壓力 和 小檔案壓力,降本增效
  • 升級需要採用熱升級,不影響業務的正常執行
  • 有完備的降級方案,升級有異常時可迅速降級(回退)
  • 保證HDFS升級後和現有元件相容,不影響其他元件的正常服務

升級方案

升級元件

HDFS or 升級HDFS + YARN

首先,從需求出發,目前對HDFS升級需求很強烈,升級後有很大收益;對YARN的升級需求很小,當前版本基本滿足目前需求。再從升級複雜度考慮,如果在只升級HDFS的情況下,需要考慮HDFS 新舊相容性及HDFS Server 和 HDFS Client 的相容性, 上層計算元件通過HDFS Client 和 HDFS 互動,理論上在解決HDFS Client 和 Server 端的相容性後上層元件都具備相容能力;如果升級HDFS + YARN ,還需要考慮YARN 和 執行在YARN 上面的眾多計算框架的相容性,當前 Hive,Tez,Spark 等元件版本較低,需要投入很多時間精力去保證元件間相容,升級的困難程度將大大增加。 綜合考慮 收益 和 投入,決定YARN 放到在將來成熟的時機升級,這次只升級HDFS來解決當前痛點。

升級方式

官方推薦的升級方式有兩種:Express 和 Rolling,Express 升級過程是停止現有服務,然後使用新版本啟動服務,會影響業務正常執行;Rolling 升級過程是滾動升級,不停服務,對使用者無感知。業務不能接受停服,我們優先選擇 RollingUpgrade方案。

對應 RollingUpgrade 中, 有兩種回退方式:Rollback 和 RollingDowngrade , Rollback 會把軟體版本連同資料狀態回退到升級前的那一刻 ,會造成資料丟失; RollingDowngrade 只回退軟體版本,資料不受影響。在不容忍資料丟失的前提下,我們優先選擇 RollingDowngrade 的回退方案。

最後確定的升級&回退方案如下圖:

HDFS 2.x 升級 3.x 在車好多的實踐
如果想及時瞭解Spark、 Hadoop或者HBase相關的文章,歡迎關注微信公眾號: iteblog_hadoop

詳情參見:Hadoop 官方文件

遇到的問題

版本選擇

目前HDFS 最新版本為3.3.x ,但是3.3.x 剛出不具備在生產環境部署的條件。初步調研發現,HDFS 版本小於 3.1.3 和 3.2.1 時,在Namenode滾動升級和滾動降級時存在因為EC導致的相容性問題(詳見 HDFS-14396 ,HDFS-13596 ),所以小於3.1.3 和 3.2.1 的不予考慮。 綜合考慮需求後,在3.2.1 和 3.1.3 中選用了更穩定的3.1.3 版本。

版本相容性

我們當前Hadoop版本為HDP-2.6.5,和3.1.3版本之間存在較大的差距,升級存在較多風險。我們在相容性方面進行了深入研究,主要有以下幾個方面需要考慮:

  • 新舊版本Namenode的元資料要相容,保證服務升級失敗後可以降級到舊版本,包括FSImage和EditLog。
  • 新舊版本Datanode 資料格式要相容,這樣Datanode在升級失敗時可以滾動降級到舊版本。
  • 新版本Namenode 和 舊版本Datanode 要相容,升級過程中會存在舊版本Datanode和新版本Namenode 共存的情況
  • 由於HDFS作為Hbase、YARN、Hive、Spark等的依賴元件使用,每個元件的 HDFS Client 都散落在全公司使用方,而且由於歷史原因版本、配置繁雜,我們很難做到統一升級。所以我們最終只選擇升級HDFS 服務端,包括Namenode/Journalnode/zkfc/Datanode,來降低這次升級的阻力和難度。所以需要保證HDP-2.6.5的 Client 可以正常訪問3.1.3的Namenode和Datanode服務。

經調研測試,主要有兩處不相容:

1、 DatanodeProtocol.proto 協議不相容

//  hdfs-3.1.3 版本
message HeartbeatResponseProto {
  repeated DatanodeCommandProto cmds = 1; // Returned commands can be null
  required NNHAStatusHeartbeatProto haStatus = 2;
  optional RollingUpgradeStatusProto rollingUpgradeStatus = 3;
  optional RollingUpgradeStatusProto rollingUpgradeStatusV2 = 4;
  optional uint64 fullBlockReportLeaseId = 5 [ default = 0 ];
}
  
// hdp-2.6.5 版本
message HeartbeatResponseProto {
  repeated DatanodeCommandProto cmds = 1; // Returned commands can be null
  required NNHAStatusHeartbeatProto haStatus = 2;
  optional RollingUpgradeStatusProto rollingUpgradeStatus = 3;
  optional uint64 fullBlockReportLeaseId = 4 [ default = 0 ];
  optional RollingUpgradeStatusProto rollingUpgradeStatusV2 = 5;
}

我們可以看到兩個版本 HeartbeatResponseProto 的第4、5個引數不同。 當 Datanode 向 Namenode 傳送心跳時,攜帶了requestBlockReportLease=true 引數, Namenode 根據自身忙碌程度決定是否在心跳中返回 fullBlockReportLeaseId 來接收Datanode 的BlockReport ,從而實現Datanode 的BlockReport 限速(詳情參見: HDFS-7923)。 當新版本 Namenode 返回一個fullBlockReportLeaseId 時,被舊版本Datanode 當成rollingUpgradeStatusV2 來解析,最終導致Datanode BlockReport 無法進行。

這個問題的原因在於, 3.1.3 版本 commit 了 HDFS-9788 ,用來解決低版本升級時相容問題,而 HDP-2.6.5 沒有commit 。

解決這個問題主要有兩個辦法:

  • 在當前版本HDP-2.6.5 上回退 HDFS-7923 的修改來達到協議相容;
  • 在3.1.3 上回退 HDFS-9788 的修改來保持和HDP-2.6.5 相容。

綜合考慮,HDFS-9788 只是為了解決hdfs升級時相容低版本的問題,我們當前目標是升級到HDFS 3.x , 至於相容低版本的功能我們不需要。所以我們選擇了第二種方法。

2、 Datanode 資料儲存格式不相容
社群自 HDFS-2.8.0 commit HDFS-8791 後,基於blockid的Block Pool資料塊目錄儲存結構從256x256個目錄變成了32x32個目錄,資料儲存格式發生了變化。這個特性導致了HDP-2.6.5 可以滾動升級到 HDFS-3.1.3 但是不能滾動降級。 HDFS-8791 主要解決Datanode在ext4檔案系統中用256x256個目錄儲存資料塊的效能問題。考慮這個問題在我們叢集並不明顯,決定暫時回退 HDFS-8791 的修改,保持Datanode 資料格式的相容,保證我們在升級Datanode異常時還能降級。至於後續有需要時,可單獨升級Datanode。

其他問題

1、升級過程中,DataNode 在刪除 Block 時,是不會真的將 Block 刪除的,而是先將Block 檔案放到磁碟BlockPool 目錄下一個 Trash 目錄中,為了能夠使用原來的 rollback_fsimage 恢復升級過程中刪除的資料。我們叢集磁碟的水位一直在80%,本來就很緊張,升級期間Trash 中的大量Block檔案會對叢集穩定造成很大威脅。考慮到我們的方案是的回退方式是滾動降級而非Rollback,並不會用到Trash 中的Block。所以我們使用指令碼定時對 Trash 中的 Block 檔案進行刪除,這樣可以大大減少 Datanode 上磁碟的儲存壓力。

2、升級觀察過程中發現舊版本HDFS 在 Kerberos 認證後去連線 3.1.3 建立連線失敗,導致一條資料鏈路故障。因為在3.1.3 版本中增加了 hadoop.security.auth_to_local.mechanism 預設值為hadoop , 不接受帶有 ‘@’ 或者 o'/' 的使用者名稱 ,而舊版本Client 在kinit 之後會攜帶 ‘[email protected]’ 這樣的使用者名稱去建立連線,所以連線失敗。 在修改 hadoop.security.auth_to_local.mechanism = MIT 後解決,詳見:HADOOP-15996 。 反思:考慮叢集本身沒有開啟 Kerberos 認證,在升級測試過程並未把 Kerberos 相關內容劃到測試範圍內,導致一個故障。以後在測試時要 Involve 更多的依賴方,做更全面的Testing。

3、升級後手動 Failover Namenode 失敗,引發Standby Namenode 掛掉。 Namenode Failover 時,Standby Namenode 轉變成 Active 過程中初始化 Quota 的時間超過了zkfc超時時間,所以Standby Namenode 掛掉。初始化 Quota 執行緒數預設值為4 ,增加dfs.namenode.quota.init-threads 後解決。 詳見 :HDFS-8865

測試 & 上線

1、分析升級原理 & 版本差異

在這個過程中,我們詳細閱讀分析了滾動升級的原始碼,確定升級中 NameNode,DataNode 會做哪些動作,以明確風險點。由於 HDP-2.6.5 基於Apache-2.7.3 增加了近 2000個Patch ,HDFS-3.1.3 相比 2.7.3 增加了近4000 個 Patch ,我們需要找出可能存在相容性問題的點進行分析,以確保對升級沒有影響。

2、對比新舊版本配置

新舊版本在配置方面有很大不同,尤其是3.1.3 新增了很多配置,都可能成為升級失敗的關鍵點。這裡需要我們過濾出新舊版本的不同配置進行研究,確保配置引數相容。

3、模擬線上環境全量元件測試

HDFS 是眾多元件的依賴,HDFS的執行狀況隨時影響著其他各種鏈路的穩定。為了儘可能的避免升級風險,保證叢集升級的順利我們模擬線上叢集節點壓力搭建了一套全量元件測試環境。組織所有相關元件admin 模擬線上場景搭建任務鏈路,在任務正常執行情況下,開始按步驟進行升級,並每個步驟進行Check ,直升級完成後所有任務都無異常。

4、多次的演練

升級方案驗證完成形成Checklist 後,逐步在Dev環境、Test環境、Stage 環境進行演練,在增加操作的熟練度同時通過不同環境的大量測試任務檢驗升級方案健壯性。

5、正式升級

商定一個升級時間視窗,並通知使用者注意升級期間任務執行情況。 升級完成觀察一週沒問題後執行 Finalize 操作。

總結

HDFS 在 3.1.3 版本執行穩定,我們計劃在今年完成叢集冷資料的轉EC操作,降低HDFS儲存成本,並在計算元件支援EC檔案讀寫上投入精力調研。後續逐步開啟3.1.3版本新特性,包括RBF、Namenode 一致性讀、DN的維護狀態等功能,來提升HDFS的讀寫效能,繼續為降本增效努力。

參考資料:

[1]https://blog.csdn.net/DiDi_Tech/article/details/103849694
[2]https://issues.apache.org/jira/browse/HDFS-14831
[3]https://issues.apache.org/jira/browse/HDFS-14509
[4]https://issues.apache.org/jira/browse/HDFS-11096
[5] https://issues.apache.org/jira/browse/HDFS-14753



本部落格文章除特別宣告,全部都是原創!
轉載本文請加上:轉載自過往記憶(https://www.iteblog.com/)
本文連結: 【HDFS 2.x 升級 3.x 在車好多的實踐】(https://www.iteblog.com/archives/9900.html)

喜歡 (0) 分享 (0)