天天看點

Qunar萬億級Elasticsearch叢集節點遷移實戰

作者:閃念基因

1.背景綜述

Qunar 的實時日志平台使用的是 ELK 架構,其中 Elasticsearch 叢集(以下簡稱:ES 叢集)和 kibana 平台在機房 A,Logstash 叢集在機房B。

目前機房 A 在使用過程中存在以下一些問題隐患:

  • 機房 A 目前為飽和狀态,批量新增機器難以支援
  • 機房 A 主要由 Hadoop、ES 叢集組成,業務互動會産生大量跨機房流量,峰值會影響到業務

基于上述因素,與 Ops 同僚溝通後,決定整體遷移 ES 叢集到機房 B。這樣不僅可以解決上述兩個問題,和寫入端的 Logstash 叢集也同在一個機房,網絡通信更有保障。

此文主要介紹 ES 叢集節點遷移實戰過程中的一些實踐與探索演進經驗,對于日常的平台開發與運維也能有所借鑒和參考。

2.遷移方案

2.1 ES日志平台架構

Qunar-ES 日志平台主要存儲全司實時日志,通過 filebeat、fluent-bit 等采集工具将日志采集到 kafka 後,由 Logstash、Flink 按照不同 topic 寫到對應的索引中。一個 appcode 的日志對應到 ES 就是一個索引。

其中 Logstash 層還負責日志資料的 filter 邏輯,平台這邊給業務使用者提供了專門的 logstash-debugger 來進行 logstash的filter 測試與開發。

kibana 對接 ES 叢集資料提供給全司,按照 space=>user=>role=>index pattern 的模式來管理使用者的權限。以下是整體的實時日志平台架構圖:

Qunar萬億級Elasticsearch叢集節點遷移實戰

ES 日志叢集目前是公司最大的一個獨立 ES 叢集,文檔數達到了萬億級,存儲量也在 PB+,節點數(ES 節點非機器數)也在500+,如圖:

Qunar萬億級Elasticsearch叢集節點遷移實戰

叢集使用了多種類型的節點,master 、data 節點獨立部署,角色分離,使用專門的 coordinate node 作為協調節點作為 data node 與外部請求的橋梁,在 coordinate node 外部增加了一層網關 gateway 層,直接接收使用者請求,可以對請求進行審計與處理。叢集架構圖如下:

Qunar萬億級Elasticsearch叢集節點遷移實戰

2.2 遷移難點

  • 如何保證遷移中的服務可用性與使用者無感覺

叢集規模大,寫入量大,使用範圍廣,遷移過程中,穩定和服務可用性是第一要務。如何保障穩定性是首先要解決的難點

  • 如何提升遷移效率

遷移效率有兩個方面:

  1. 遷移的速度:主要取決于遷移政策和持續的調優。遷移的總資料在PB級,單機器(機械硬碟)也到了10TB+,優化遷移效率,提升速度是後續持續研究的重點。
  2. 遷移的人工成本:遷移過程中,每個流程環節都需要人工介入,如何能提升自動化率,降低人工成本,也是研究提高生産力的方向。

2.3 遷移方案

整體方案:按照機櫃梳理出機房A的機器順序,按批次進行節點資料遷移,将機器服務下線,搬遷到機房B中,重新部署,組網,并部署,啟用。反複執行,直到全部遷移完成。可以參考以下流程圖:

Qunar萬億級Elasticsearch叢集節點遷移實戰

而從節點類型和服務次元來看,主要有以下幾類,也是按照從 Data Node依次往後進行遷移:

· Data Node

· Coordinate Node

· Master Node

· Kibana

· Service

本期遷移重點和難點都集中在資料節點的遷移,故而後續大量篇幅都在講解資料節點遷移的演進變化。

3.遷移過程

3.1 初步嘗試(11月)

做好以上前置準備事宜後,開始第一階段的遷移工作,此階段曆時1個月。此階段主要重點在于以下三件事:

a. 手動遷移節點

b. 調參保證穩定性

c. 整理問題,确立後續工作側重點

從機器清單(已排好序)中選取機器,以5台(單個機器有兩個資料節點)為機關,進行exclude._name 操作:

PUT _cluster/settings
{
  "transient" :{
      "cluster.routing.allocation.exclude._name" : "data1_node1,data2_node1,data1_node2,data2_node2,data1_node3,data2_node3,data1_node4,data2_node4,data1_node5,data2_node5"
 }
}           

Tips:

遷移節點資料最直接的方法就是官方提供的exclude操作,這個操作是叢集級的,可以直接通過"_cluster/settings"進行修改,執行操作後,叢集會将比對到的節點的分片reroute(同步)到其他節點上。通過exclude分為以下三種操作:

· exclude._name:将比對的node名稱對應的節點資料遷移,多個node名稱逗号分割

· exclude._ip:将比對的node的ip對應的節點資料遷移,多個ip用逗号分割

· exclude._host:将比對的node的主機名對應的節點資料遷移,多個host用逗号分割

運作一段時間,發現存在一些問題:

因為是日志叢集,屬于寫多讀少的場景,中午到晚上是寫入高峰,淩晨到早上屬于寫入低峰,在觀測監控和機器報警中發現,節點在寫入高峰時期會出現大量的load飙高情況(相較于exclude之前),而在低峰,相對要少很多,如圖:

Qunar萬億級Elasticsearch叢集節點遷移實戰

appcode 日志堆積數也會有所上升:

Qunar萬億級Elasticsearch叢集節點遷移實戰

分析後,總結原因有幾下幾點:

a.添加 exclude_name 後,叢集多了很多 relocating shards,此時會出現大量的分片遷移操作,通過_cat/recovery 可以看到期間的分片進行的過程。

b.白天叢集是寫入高峰,壓力不算小,此時還需要同步資料,會造成 exclude name 對應的節點,因為要大量的遷出資料,會進行大量的磁盤讀操作,同時,還有很多分片還在進行目前的寫入操作,磁盤 io 很容易趨近于100%(使用的是機械盤)。

c.遷入分片的節點也因為讀取量的飙升,導緻了磁盤的 io 上漲。繼而影響同步兩側的節點紛紛 load 飙高,影響的就是會有個别的 appcode 寫入堆積。

調整過程:

根據峰值調整 exclude_node 的批次量,做如下調整

  • 高峰時期:調整到2個機器節點同時 exclude。
  • 低峰時期:保持5個節點同時 exclude。

調整以後,除白天寫入尖峰會有一些 load 飙高外,基本趨于平穩,堆積也大大回落。

3.2 自動化遷移(11月~1月)

有了第一個階段的經驗,熟悉了節點遷移的基本流程和操作。以上作為自動化的前提準備,于是開始了相關的架構設計和實作工作,具體架構圖如下:

Qunar萬億級Elasticsearch叢集節點遷移實戰

主要設計思路如下:

1. 判斷叢集目前狀态。達标才可以繼續下一步操作,否則就等下一次檢測。标準很簡單:

* status:叢集狀态為 Green

* load:叢集 load>30節點不超過7個;load>50的節點不能超過3個(基于日常叢集情況)

2. 判斷 relocating shards count:

* 哪些節點遷移完成:如有,則統計數量

* 目前在遷移的 shard 數量

如果有節點遷移完成,且正在遷移的 shard 數量在40以内,可以進行新節點批次遷移,否則說明尚有多數分片在同步中,需等待下一次判斷

3. 下線遷移完的機器節點。根據第二步得到的機器清單,下線前,需再次校驗是否機器節點無索引分片

4. 擷取下一批 exclude 的清單(順序)

5. 根據時間峰值進行 exclude(基于之前的經驗)

* 高峰:2個機器節點

* 低峰:5個機器節點

注:

*實際遷移的機器節點數為:需要遷移的節點數 X - 已經遷移完成的節點數 Y

*這樣可以保持系統一直遷移機器數一直穩定在峰值對應的數量

按照這樣的架構實作的自動化遷移,在第二個階段運作比較順暢,變化也是十分明顯:

  • 節省人力成本(不用去手動操作),同時為第三個階段的優化架構留出了演進基礎
  • 保證遷移節點數量保持恒定

3.3 疊代調優(1月~2月)

之前的第二個階段解決了自動化的問題,節省了遷移效率,在自動化穩定運作的同時,也在探索提升穩定性與遷移速率,在1~2月期間,主要做了以下幾個方面的探索與實踐

3.3.1 total_shards_per_node

index.routing.allocation.total_shards_per_node:設定單個索引在單個節點上最多的分片數(包括主副本)。預設無限量

調整原則:保證單個索引在單個節點上保留最少的分片數,以避免資料分片傾斜的情況,已提升整體穩定性。

total_shards_per_node 的調整邏輯如下:

total_shards_per_node: shard_num/(nodes_count * 0.95(buffer系數) * 0.5)           

需要注意的是:

buffer 系數是一定要有的,否則一旦有節點當機故障,就會一批分片出現 unassigned 情況,無法配置設定。

索引設定可以使用 template 進行控制,友善控制與修改。

索引級個性化的 template 參考如下:

{
  "order": 99,
  "index_patterns": [
    "log_appcode-*"
 ],
  "settings": {
    "index": {
      "number_of_shards": "278",
      "routing": {
        "allocation": {
          "total_shards_per_node": "2"
       }
     },
      "refresh_interval": "60s"
   }
 },
  "mappings": {
    "properties": {
        #索引獨立的結構       
   }
 }
}
 
 
注:上面這個template 模闆設定的索引分片單個節點最多配置設定兩個分片。           

3.3.2 node_left.delayed_timeout

index.unassigned.node_left.delayed_timeout : 節點脫離叢集後多久配置設定unassigned shards(預設1min),相當于延遲恢複配置設定多久的時間。

這個參數相當重要,尤其是大叢集中,節點當機重新開機時有發生,如果不做設定,節點對應的數百副本分片就會進行恢複操作,期間會耗費大量的 IO 資源,影響叢集穩定性。而且叢集重新開機後,還會進一步做 rebalance 以平衡分片。

索引恢複主要有6個階段,如下:

1.INIT:剛開始恢複的階段

2.INDEX:恢複Lucene檔案

3.VERIFY_INDEX:驗證Lucene index中是否有分片損壞

4.TRANSLOG:重放Translog,同步資料

5.FINALIZE:執行refresh操作

6.DONE:更新分片狀态,完成操作

當機器當機重新開機後,機器對應的所有分片會短暫成為 UNASSIGNED SHARD 狀态,預設60s後叢集 UNASSIGNED SHARD 進行恢複操作,此時會把原本當機機器的未配置設定分片(副本)配置設定到其餘節點,因為是副本分片同步,需要從主分片進行同步資料,比從本地恢複慢了不少,且極為影響性能。過程類似于:

Qunar萬億級Elasticsearch叢集節點遷移實戰

基于此,針對 node_left 的設定做了兩次的嘗試:

a. index.unassigned.node_left.delayed_timeout: 120m

将所有的索引 template 設定延遲配置設定時間設定為120分鐘。

當遇到節點當機後,不會再次出現大量分片遷移的過程,當節點重新開機後,分片會從節點本地進行恢複,效率高,性能影響小。

但是如果是節點故障當機,無法啟動時,會出現在 delyed_timeout 時間到達後,進行集中大量的分片恢複,如果節點分片多,同樣會有性能方面的影響和損耗。

b. index.unassigned.node_left.delayed_timeout: random time

在調大延遲配置設定時間後,還會出現集中分片恢複的情況,主要是因為對于單一節點的索引分片都是同一時間變成的 unassigned,也會在同一時間進行恢複。

基于此,将 delayed_timeout 設定為随機數值,在建立索引的時候,設定為100~300min區間的随機數,類似如下:

delayed_timeout = random.randint(100, 300)
PUT /index/_settings
{
  "settings": {
    "index.unassigned.node_left.delayed_timeout": delayed_timeout
 }
}           

調整後,在故障當機觀測,會發現恢複分片是一個持續間斷過程,而非之前的突增突降。如圖對比:

Qunar萬億級Elasticsearch叢集節點遷移實戰
Qunar萬億級Elasticsearch叢集節點遷移實戰

3.3.3 單機器單節點遷移

資料節點的實體機的配置為:32core 128g 14TB(為主,還有9TB、18TB)

單實體機部署兩個節點(data1,data2)執行個體,每個節點占用16core 64g資源,磁盤共用。

之前兩個階段的遷移是以實體機為機關進行遷移,批次遷移多台實體機資料,期間會因為大量的資料同步傳輸導緻磁盤io問題,是以需要在高低峰進行批次調整,以保證穩定性。但是批次量無法提升,導緻速率不太理想。

此次更換為單機器單節點遷移,exclude_node 中隻選擇同批次機器的data1,等 data1節點遷移完成後,遷移 data2。cluster exclude 設定如下:

PUT _cluster/settings
{
  "transient" :{
      "cluster.routing.allocation.exclude._name" : "data1_node1,data1_node2,..."
 }
}           

使用單節點遷移後,單批次節點在高峰期可以增加50%,低峰時期增加80%。在遷移過程中,叢集整體寫入,與同步節點的 cpu、磁盤 io 均比較穩定,當 data1遷移完成後,批次節點的 load 整體會控制在10以内,穩定性得到相應的提升。

3.3.4 cluster_concurrent_rebalance

cluster.routing.allocation.cluster_concurrent_rebalance: 用來控制叢集内并發分片的 rebalance 數量,預設為2

ES叢集的 cluster_concurrent_rebalance 參數長期使用的在10(節點數多,增加分片的同步效率)

在遷移節點過程中,同步的節點會非常多,出現很多的 relocating shards,且同時還會有 rebalance 的分片,在遷移之後,還會繼續做 rebalance。

此處為了減少 rebalance 的頻率與周期,設定 cluster_concurrent_rebalance 為0,相當于一直都不做 rebalance。

但是如果長期不進行 rebalance,分片會出現傾斜不均衡的情況,基于此,進行了3.3.4 手動 reroute 操作,來調整分片的均衡。

注:

cluster.routing.rebalance.enable:none 可以等同于cluster.routing.allocation.cluster_concurrent_rebalance:0。都相當于不做任何的分片均衡

每周建立索引後,進行reroute

(1)rebalance 本身存在的問題

rebalance 節點主要有 decider 控制器來決定的,而非目前分片使用的情況,這樣會造成一個情況,機器在 rebalance 後整體分片數均衡,但是寫入不均衡(有些分片是當周分片正在寫入資料,有些分片是上周分片,均衡之後可能會出現一些節點的當周分片數很多,導緻寫入壓力大,磁盤 io 高,反而沒有達到真正的均衡)

現象是會有一些節點在高峰期出現持續高 load,磁盤 io 趨近100%的情況。不得不做一些手動的 reroute 分片,來緩解節點壓力,遇到持續增高,可能會出現 node_left 重新開機的現象。

(2)cluster_concurrent_rebalance為0帶來的問題

因為3.3.3 中将 cluster_concurrent_rebalance 調為0,叢集不會做分片均衡操作,新增索引分片會按照 decider 進行排程,最極端的情況會将某些分片數少的節點配置設定超過一倍的分片數。舉個例子:

周中新上的機器節點 node-300,到了周末統一建立索引的時候,由于 node-300基本沒有分片(除少數新增索引外),會有大量的分片建立到 node-300中。

ES 叢集建立完次周索引後,分片數在10w,資料節點數大緻為450,平均到單個資料節點的分片大緻為220+。而新周的索引分片數大約在5w+,對應的分片數為110+,而 node-300的新周索引分片數即為220+,相當于是其餘節點的1倍以上。

上述兩個現象直覺導緻的現象都是因為個别節點分片不均衡,導緻性能受到影響,繼而會出現 node_left 的情況。

分析了上述兩個原因,決定從寫入的分片均衡 來入手。

因為是日志叢集,索引是以周次元建立,每周日淩晨提前進行建立次周索引(tips:如果不提前建立,會在次周切換索引時,引發大量的 pending_tasks,造成叢集寫入大面積堆積),隻要保證次周寫索引的分片在索引節點均衡即可。

(3)reroute new shard 調整分片均衡

在建立完新周索引後,可以對分片進行調整,流程圖如下:

Qunar萬億級Elasticsearch叢集節點遷移實戰

針對以上流程做一下簡要說明:

1.主要的思路是:計算次周總的分片數/可用資料節點,得到平均分片,然後将分片多的遷移到分片少的節點。

2.因為是空索引,遷移時間基本可以忽略不計。

3.需要注意的是可用資料節點,從_cluster/health 可以擷取到對應的可用 data node 數量,但是還需要将_cluster/settings exclude._name 中對應的節點數排除出去方是真實可用的數量。

4.同步完後,可以達到寫索引的平衡(整體分片數不一定均衡)。

執行完同步腳本後分片均衡,以上問題順利解決。

(4)reroute new node

以上所有的措施已經能解決最核心的兩個問題:穩定性、遷移速度。

按照當時遷移速度估算,可以在剩餘1個月内完成全部的節點遷移,但是是否有更快更好的方法做遷移麼?

在上個優化點 reroute new shard 調整分片均衡 中得到靈感,新分片遷移是很快的,因為沒有資料,基本不費時間且對性能沒有任何影響。那能否用于在遷移節點上來呢?答案是可以的:

在 reroute new shard 基礎上,做了改進,并根據機器配置,做了差異化的處理(包括遷移節點和平衡分片),設計圖如下:

Qunar萬億級Elasticsearch叢集節點遷移實戰

以上設計圖有幾點需要了解:

1.順序:先進行節點遷移=》然後進行分片平衡

2.時間:一般會提前1-2天建立次周索引,可以在建立索引後進行以上流程操作

3.節點遷移增加新節點相當于是将需要遷移的分片遷移到新節點上,因為是新節點,基本上不會有 reroute 沖突

4.可以根據機器的配置進行門檻值的調整,比如遷移節點後計算節點分片門檻值為80(每個節點平均80個次周分片),可以将高配置的機器門檻值提高:

  • 48c的機器 門檻值增加20%
  • 32c的機器 門檻值降低20%

如果有 ssd 機器,可以在原有門檻值上進一步提升,也可以做點對點分片均衡調整,将高配置節點、分片數較少節點統一作為被同步節點,将配置低節點、分片數遠高于門檻值節點作為同步節點,進行 reroute。

分片均衡,可以參考以下用法:

POST _cluster/reroute
{
  "commands": [
   {
      "move": {
        "index": "log_appcode-2023.18",
        "shard": 59,
        "from_node": "data2_node1",
        "to_node": "data2_node10"
     }
   }
 ]
}           

在做完以上步驟後,等到次周開始,叢集寫入都切到了新的索引後,可以進行 exclude 節點操作,此時由于批次節點都沒有寫入索引,遷移同步分片會非常快,且對性能影響非常小。

總結:

  1. 用了這個方法,可以說,速度提升了2倍以上,并提前了一周多完成了節點的遷移。
  2. reroute new shard 思路還适用于平時的平台開發維護,後來也用到了 ES日志叢集的拆分工程中,至于 Qunar-ES 叢集拆分實踐,可以留做後續專門獨立做一個分享。

3.3.5 coordinate node遷移

coordinate node 主要用來做協調作用,負責接收叢集的讀寫請求,繼而傳遞到資料節點進行實際的資料互動。

本身協調節點不進行存儲,主要需要 cpu、記憶體的資源。

ES日志叢集的協調機器大緻在40+,分批次每周5台遷移即可,遷移完成,需要對 Logstash 的 output 端進行重刷服務。

Tips:

建議小叢集可以不用單獨的協調節點

大叢集協調節點建議如下配置(隻做協調作用):

Qunar萬億級Elasticsearch叢集節點遷移實戰

協調節點數:資料節點數 比例建議為:1:8~10

如果有大批量的備用機器(可以沒有獨立硬碟)可以作為協調備份節點,可以先上對等批次的機器節點到叢集,重刷 Logstash 的 output 端連接配接,之後将對應數量的節點服務下線,這樣可以達到1~2批次内完成所有協調節點遷移工作。

3.3.6 master node遷移

master 節點遷移相對來說比較簡單,隻需要找到臨時機器部署在機房 B,部署好對應服務,把機房 A 的 master 服務下掉,把機房 B 的 new master 節點起來即可。

注:

  • 唯一需要注意的點是,由于整個叢集的遷移是不停服務的,而 elasticsearch.yml 的 master 與 discovery 子產品配置的 master 選舉的節點清單已經寫的是機房 A 的機器節點,一旦用了機房 B 的 master 服務,是無法感覺對應的 node。
  • master 節點需要一個一個遷移,如果低于需要的最小數量,叢集恐無法使用
  • master 的 node 名稱感覺問題可以通過以下來做:
  • 将 new master 節點 =》 host 到 old master 節點上,效果就是如下:
Qunar萬億級Elasticsearch叢集節點遷移實戰

當然也可以通過負載和服務發現架構來實作動态調整 master 節點。

做完以上步驟,ES 叢集就全部遷移到新機房了,後續就是對應的服務遷移與适配。

4.總結

最終在近三個月的時間裡,不斷的嘗試中,完成了叢集整體遷移,并且提前了一周多的時間,也做到了零故障。

期間遇到元旦峰值,也得到了鍛煉和考驗。

總結下大規模 ES 叢集節點遷移主要的要點有以下:

戰略層面

  • 制定遷移計劃:針對不同的節點類型制定不同的方案(提前制定好可預見的問題與應對方案,這點非常重要)
  • 能用自動化代替人工的,盡量多走自動化,提升效率,複用性高,穩定性好
  • 熟悉對應的底層原理與系統參數,可以更好的指導技術層面的優化與實踐

技術層面

  • total_shards_per_node
  • node_left.delayed_timeout
  • 單機器單節點遷移
  • reroute遷移演進

相信以上的經驗和一些技術要點,不僅在叢集節點遷移可以參考,同樣也适用與大規模叢集開發與維護。可以說,就是有了不斷的叢集平台維護開發的經驗與總結,才逐漸總結出各種優化方法。

小感想:

有時候系統性的優化或者方案,從來都不是一蹴而就的,都要通過不斷的嘗試與調整,在對系統原理的把控上,進行方案的優化,進而取得持續的進步。

5.參考文獻

  1. https://www.elastic.co/cn/blog/how-many-shards-should-i-have-in-my-elasticsearch-cluster
  2. https://www.elastic.co/guide/en/elasticsearch/reference/7.7/allocation-total-shards.html
  3. https://www.elastic.co/guide/en/elasticsearch/reference/7.7/delayed-allocation.html
  4. https://www.elastic.co/guide/en/elasticsearch/reference/7.7/index-modules-translog.html
  5. https://www.elastic.co/guide/en/elasticsearch/reference/7.7/cluster-reroute.html
  6. https://cloud.tencent.com/developer/article/1334743?cps_key=6a15b90f1178f38fb09b07f16943cf3e
  7. https://blog.csdn.net/laoyang360/article/details/108047071

作者介紹

許睿哲

2020年12月加入去哪兒網-資料平台團隊,目前主要負責公司的 esaas 雲服務與實時日志 ELK 平台的開發、維護與優化。主導參與了公司的es平台的SLA規則的制定與開發、 ES 架構更新遷移與jinkela叢集拆分等工作。

來源:微信公衆号:Qunar技術沙龍

出處:https://mp.weixin.qq.com/s/zpz6k4lXQlvvBx756hyWQA

繼續閱讀