深度剖析 360 命令執行系統 Qcmd

分類:技術 時間:2017-01-13

女主宣言

“天下武功,無堅不摧,唯快不破”。今天小編妹妹要帶大家看看“運維攻城獅”是如何玩轉自動化,輕松管理上萬臺服務器的。

PS:豐富的一線技術、多元化的表現形式,盡在“ HULK一線技術雜談 ”,點關注哦!

自動化運維工作在360私有云 HULK 云平臺(后面簡稱為 HULK 云平臺)中被稱為命令執行系統,在 HULK 云平臺運行的4年中,命令執行系統的技術和需求也在發生著變化,可以這么說,命令系統是 HULK 云平臺服務和模塊的運行根本。

早期的私有云平臺模塊規劃中,將整個命令執行系統包括調度模塊和執行模塊統稱為 Qcmd。

本文會對 Qcmd 的設計、原理、應用和線上使用做下說明。

背景

HULK 云平臺對于命令執行系統的要求比較簡單,只需要批量對主機執行腳本,并將返回結果進行呈現。之前線上一直在使用 SaltStack 作為自動化的工具,之所以使用 SaltStack 就是看中可以對批量主機執行命令,并且性能也不錯。

但是隨著網絡的復雜性、機器數量增多以及 HULK 云平臺對命令執行需求的變化,漸漸的 SaltStack 的缺點就突顯出來了:

  • SaltStack 使用的 Pub/Sub 方式,對網絡和執行的主機數量要求“非常高”,如果任務超時沒有返回,基本上只能重新執行,非常耽誤時間

  • 當 Minions 數量超過一定程度,管理和維護起來非常麻煩,輕易不敢重啟 Master

  • 線上 SaltStack 的版本不統一,對新功能兼容很差(例如zmq_filtering)

  • Minions 維護成本較高,最重要的體現就是升級比較困難

當初我們對 SaltStack 也采用了一些優化方案,但是大都無法真正解決問題,當遇到任務超時,還是需要手動登陸主機去查看該命令執行的情況, 針對任務超時的情況,思考許久,發現如果不改變 SaltStack 底層的通訊方式,那么任務超時的情況還是無法避免。

SaltStack 執行命令的過程其實就是下發消息到 Minions,那么我們是否可以用更穩定的消息傳遞方式來解決消息丟失的問題呢?

最終,我們決定采用異步通訊的方式去代替 Pub/Sub,開發語言我們選擇 Golang 來代替 Python。

目標

當然在做一個項目之前我們都會明確一些目標,Qcmd 也不例外:

  1. 消息傳遞成功率:解決消息傳遞丟失率高的問題是 Qcmd 的第一目標

  2. 性能:能支持大批量主機執行命令

  3. 集群高可用:高可用我們還是采用了 Multi-Master 方式

  4. 消息加密:采用 AES-CBC

  5. 常用接口:Master 常用接口

  6. 維護成本:是否支持自升級

  7. 分布式:分布式我們已經在上層兼容,后面會具體說明

整體設計

上面是 Qcmd 多機房命令下發的流程:

  1. 任務分發模塊由 HULK 命令系統控制

  2. 通過從 Redis 中讀取數據,各個機房完成自身的工作,互相不關聯

  3. Master 從 Task 到 Minions 都是采用了異步,上圖中 Master 到 Minion異步下發,是指 Minion 主動 Subscribe Master 中的消息

Qcmd設計

Master內部消息傳遞設計:

之前也提到了,Master 下發執行命令的過程其實就是消息傳遞。

上圖是 Master 內部消息的傳遞流程,Pub 是指 Master 提供給外部調用發布消息的接口,每一個 Topic 和 Channel 對應一個 Minion,Topic 和 Channel 是一對一的關系。

當調用 Pub 接口的時候,首先 Master 會進行數據校驗和過濾,然后將合法的信息進行序列化、加密等動作,最后會將處理后的消息發送到相應的 Topic 和 Channel。

Master Subscribe設計:

上圖中是 Master 內部 Subscribe 的邏輯設計,當有消息通過 Pub 接口進入,會先對消息進行處理,將處理后的消息根據匹配的 Minons Id 去獲取對應的Topic,然后使用 PutMessage,將消息寫入 Topic 的 MsgChan,每個 Topic 在創建的時候都會產生一個叫 MessageDump 的 Goroutine,MessageDump 的作用就是將 MsgChan 中的消息及時發送到 Channel 中。

當 Channel 的 PutMessage 被調用時,會將消息寫入MsgCha(不是 Topic 的MsgChan),當然 Channel 也有一個 MessageDump 去消費其中的消息,并將一條待發的消息寫入 MinionMsgChan。

當 Minion 發起 Subscribe 動作的時候,會使用配置的 ID 做為條件去查詢其所在的 MinionMsgChan,如果有消息,Subscribe 動作會返回數據給 Minion,同時 Minion 會立即發起下一次 Subscribe 請求;如果沒有消息或者消息不合法,會在到達 SubscribeTimeout 后,給 Minion 發送一條空消息,然后進行下一次 Subscribe 動作。

關于消息的合法性,我們需要滿足兩種情況:

第一種:Subscribe 到消息的時間已經超過消息的超時時間設置,判斷為不合法;

第二種:Subscribe 到消息的時間已經超過了 SubscribeTimeout( SubscribeTimeout 最大值由MaxSubscribeTimeout 限制),也會判斷為不合法,這種是為了避免任務超時時間設置過大的情況。

Minion Subscribe設計

上圖是 Minion Subscribe 的流程,當調用 Subscribe 有返回,會將受到的消息丟入 CmdChan 中,同時會進行下一次 Subscribe,CmdDump 從 CmdChan中拿到消息,會對消息進行解密等操作,然后根據不同的 Function 去執行相應的操作。

如果執行的操作在預先設置的超時時間之前返回,那么會直接調用 Return,將結果發送到 Master;如果在規定的時間內沒有執行完,那么會在到達超時時間后觸發 CallBack,將命令執行的狀態返回 Master,等到命令真正執行完畢,會再將結果發送到 Master。

Minion Heartbeat設計:

Minion Heartbeat 的作用是定期向 Master 發送心跳,同時查看 Master 中Minion Key 的狀態。

在 Heartbeat 之前會檢查 Master 當前域名對應的 IP,如果檢測到 IP 發生變化,則觸發 RetryDns 操作:

第一步:斷開與舊的 Master 的連接;

第二步:和新 Master 建立連接,開啟認證等。

如果從 Master 返回的操作是需要重新認證(例如在 Master 將 Minion 的 Key 刪除),會將 Minion 的 Key 發送到 Master。

性能

我們這里找的是線上的 Master(16U32G)做 test.ping 測試,該 Master 有超過 7000 臺 minions,執行 20 次任務,所有 Minions 全部返回,平均耗時 21s左右,下面是執行任務中的 Master 監控圖(取自 Wonder)。

從上圖的數據看出,在全量執行任務的時候,網卡流量并不高,但是 CPU 使用比較高這里 CPU 主要使用對數據進行加密解密操作(每個 Minion 都需要加密和解密操作)。

總結

從 Qcmd 的設計到開發出 Alpha 版只用了2周時間,我們也對自動化運維有了一些自己的看法:

  1. 首先選擇自動化運維工具一定要符合自身的需求,比如HULK云平臺大部分執行的任務主機數量其實不到全部主機的1%,屬于大規模集群下的小批量主機執行場景。如果使用的還是之前使用的 SaltStack,那么每執行一次任務就相當于同時給所有在線的 Minions 發送一次消息。

  2. 在HULK云平臺中對自動化運維工具最大的要求就是執行任務要完全可靠,不能因為網絡和執行的主機數量造成消息丟失,導致任務超時。大家不要小看消息丟失的情況,一旦丟失,那么就需要人為判斷、然后手動處理等等。

從16年10月開始,已經有超過 2 萬臺主機部署了 Qcmd,最大的 Master 節點超過 7 千臺主機,每天執行任務上千次,任務超時的情況已經基本不存在。Qcmd 在下一個版本會將通訊的方式封裝成一個協議,并加重對任務的可控度。

掃描下方

二維碼

了解更多內容


Tags: SaltStack 云平臺

文章來源:http://mp.weixin.qq.com/s/R_6E1t6X3wU3UP-jDTXgow


ads
ads

相關文章
ads

相關文章

ad