聊聊宿主機管理
2020年,機器上線需要在八個服務間反復橫跳,而且全程手動操作。伴隨滴滴業(yè)務規(guī)模上云,彈性云新增大量物理機,上線操作至少有百次,這時暴露了一個問題:如果按這個速度上線機器,需要大量人力投入到上機器中。因此,彈性云急需一個平臺來管理宿主的上下線。
圖片
從無到有
DevOps,標準先行
在 DevOps 實踐中,標準化是非常重要的一環(huán)。彈性云的所有機器都是圍繞服務樹管理的。由于之前是由人工管理,彈性云機器在服務樹上的掛載情況非常混亂。因此,為了機器管理更標準,彈性云首先定義了服務樹節(jié)點標準和規(guī)范,將宿主機生命周期與服務樹節(jié)點進行關聯(lián)。具體而言:
- 機器上線:機器由 backup 節(jié)點掛載到 kube-node-init 節(jié)點初始化,然后掛載到線上 kube-node 節(jié)點進行報警關聯(lián);
- 機器維修:線上機器掛載到 maintain 節(jié)點進行維修,維修完成掛載 kube-node-init 節(jié)點進行上線;
- 機器下線:容器漂移后,線上機器掛載到 pre-offline.backup 節(jié)點進行關機退換。
圖片
流程拆解,需求分析
標準定義好后,就是對平臺需求進行分析,我們首先將宿主機上線、下線和維修的流程進行拆解,如下圖所示:
圖片
通過分析拆解后的流程,我們得出機器管理平臺至少需要具備以下功能:
- 整個流程耗時較長且為流式任務,所以任務需要異步執(zhí)行。
- 平臺依賴許多第三方服務,需要支持跳過、重試、暫停等功能,以靈活應對下游異常場景。
- 各流程之間有重復的步驟,步驟需要能被自由組合,以提升程序的靈活性。
- 按照 double-check 原則,任務需要以工單形式展現(xiàn)。
架構設計,代碼開發(fā)
在軟件開發(fā)中,程序分層是一種常見的軟件架構模式,它可以使軟件系統(tǒng)更模塊化、可擴展和易于維護。需求明確后就可以進入開發(fā)流程,從平臺的產品形態(tài)來看,平臺將來的使用流程是:用戶創(chuàng)建工單,審批通過后用戶執(zhí)行工單,程序感知到執(zhí)行動作,執(zhí)行任務,程序實時反饋任務進度,任務異常時通知用戶,用戶介入處理,任務執(zhí)行完成后,工單結束。因此,平臺可以分成4層:
- 準入層:用戶訪問控制,機器準入控制。
- 控制層:工單控制,工單創(chuàng)建、執(zhí)行、關閉等。
- 調度層:任務調度、分發(fā)。
- 執(zhí)行層:組合步驟,執(zhí)行任務,反饋狀態(tài)。
組內服務大多由 go 語言開發(fā),所以此次開發(fā)也選擇了 go 語言。準入層、控制層可以使用常見的 web 框架,調度層和執(zhí)行層需要一個異步任務調度框架。
在 go 語言中,優(yōu)秀的 web 框架很多,但是調度框架卻少得可憐。在對比了幾個框架后,最終選擇了 star 最多的異步任務框架 machinery。但是在使用過程中發(fā)現(xiàn),雖然 machinery 支持任務流、任務重試等功能,但是對任務暫停、跳過等功能缺乏支持,需要再封裝一些功能。在經歷了一段時間的嘗試后,我發(fā)現(xiàn)讀代碼比寫代碼要難上許多,再加上 go 原生對并發(fā)和異步支持比較好,最終決定調度層還是自己實現(xiàn)一個。雖然最終的開發(fā)周期有所加長,但是程序的可維護性和可擴展性會更好些。就這樣,第一版宿主生命周期管理服務 (mmachine) 在 2 個月后上線了。
圖片
宿主下線,維修
在第一版宿主生命周期管理中只上線了機器上線的功能,基本上實現(xiàn)了機器上線由人工到無人值守的轉變,但是機器的下線,維修還是由人工支持。
由于歷史原因,彈性云部分服務間通過容器 IP 進行通信,所以部分容器無法變 IP 漂移,在機器下線時很難把機器上的容器漂空。人工下線時會把可漂容器漂移走,不可漂容器在聯(lián)系業(yè)務側進行服務遷移,從經驗來看,人工 push 業(yè)務服務遷移都要花費很長時間,如果通過程序來 push,那效果比人工也不會好太多。
那么一臺機器,要達到什么狀態(tài),就認為這個機器可以下線且不會對在線業(yè)務造成影響呢?于是我們定義了一個新的標準-1、2、10原則。在機器下線時,對于未漂移容器的集群進行反查:
- 當機器存在副本數(shù)小于5且非 running 容器數(shù)大于1的集群,機器不可被下線;
- 當機器存在副本數(shù)大于5小于20且非 running 容器數(shù)大于2的集群,機器不可被下線;
- 當機器存在副本數(shù)大于20個且非 running 容器數(shù)大于總副本數(shù)10%的集群,機器不可被下線。
機器下線時,首先對機器上的容器進行漂移,在正式下線前對機器進行兜底檢查,在不打破1、2、10原則的前提下,彈性云會對機器進行關機操作。
得益于調度器設計的靈活性,將機器下線和機器上線的步驟整合后就成為了機器維修的流程(下線-報修-上線),而且機器維修需操作的機器比較明確所以自動化程度也相對較高,幾乎不需要人工介入處理,具體策略如下:
- 報修:周一至周五每個機房報修 1 臺機器。
- 上線:每周一、三、五掃描維修完成機器,上線機器。
效率提升
在第一階段彈性云完成了宿主生命周期管理服務(mmachine)從0到1的建設,機器上線耗時也從天級別縮短到小時級別,但是在服務使用過程中我們發(fā)現(xiàn)服務還有很多可優(yōu)化點。
上線流程優(yōu)化
在第一版的機器上線流程中,所有機器都在一個工單中。然而,一臺機器上線失敗將會影響整個工單的進度。例如,如果在上線 100 臺機器時,有1臺機器重裝失敗,那么其他 99 臺機器必須等失敗機器修復完成才能繼續(xù)上線。這嚴重影響了機器上線的效率。實際上,機器上線并沒有相互依賴性,因此可以將上線流程由串行改為并行,以大大縮短單臺機器的上線時間。因此,我們重新設計了上線工單,以減少機器相互影響所帶來的時間消耗。
然而,如果將上線流程改為并行,那么下游服務也需要支持并行。但在重構過程中,我們發(fā)現(xiàn)有兩個關鍵點無法并行處理:
- 機器上線需要進行重裝,而重裝操作必須在所有機器都完成后才能結單。
- 上線依賴部署系統(tǒng)來初始化腳本,而部署系統(tǒng)不支持單模塊的并發(fā)操作。
因此,我們與系統(tǒng)部門合作,將每臺機器的重裝狀態(tài)暴露出來,并將初始化腳本由部署系統(tǒng)改為使用 Zeus 執(zhí)行,解決了下游無法并行處理的問題,并將上線流程升級為每臺宿主對應一個任務流,各個任務流之間相互獨立,經過優(yōu)化后,彈性云的宿主上線耗時由之前的小時級縮短到分鐘級。
備機管理
雖然機器上線的流程得到了極大的縮短,但在真實機器交付的過程中,機器上線只是整個交付過程中的一步。從發(fā)現(xiàn)資源不足到機器上到線上的完整流程包括以下幾個步驟:"資源不足->申請機器->交付機器->重裝機器->上線->調度容器"。當線上流量突增時,通過這個流程補充機器無異于遠水救近火。然而,從彈性云的視角來看,交付流程可以簡化為"資源不足->加入資源->調度容器",只要能提前完成"加入資源"這一步,就能實現(xiàn)分鐘級的資源交付。
通過分析,我們發(fā)現(xiàn)系統(tǒng)部門有部分用于日常資源交付的備機。同時,彈性云的離線集群計算資源相對緊缺。離線集群在彈性云中屬于隔離集群,而隔離集群和公共集群的本質是通過 Kubernetes 的 taint 特性來控制的。如果備機一直運行在離線隔離集群中,當線上資源不足時,只需移除備機上的 taint,即可將其加入公共集群,從而實現(xiàn)分鐘級的資源交付。此外,離線容器對穩(wěn)定性要求不高,因此當備機需要用于非彈性云業(yè)務線交付時也可以快速退回。因此,彈性云與系統(tǒng)部門合作開發(fā)了備機管理模塊,具體功能如下:
- 自動上線:當備機交付到彈性云備機池后,它們會被自動上線到離線資源池。離線服務檢測到有空閑容量自動擴容服務。
- 快速補充:當線上資源不足時,備機管理模塊通過修改 taint 將機器轉移到彈性云的公共資源池中。
- 快速退還:當系統(tǒng)部門需要備機時,可以快速縮容離線服務并將機器退回。
通過這種方式,彈性云的容量得到了保障,公司的備機池得到了充分利用,備機的利用率也得到了提升。
云上管理
隨著云原生在公司的開展,彈性云機器管理也迎來了新的挑戰(zhàn)。在 IDC 內,物理機的單次上線數(shù)量通常不超過幾百臺,而云上的彈性伸縮每天需要擴縮數(shù)千臺虛擬機。IDC 內物理機的上線頻率、數(shù)量與云上存在顯著差異,而且云上資源用于承載核心鏈路的流量,因此擴容效率也需要更快。隨著云上機器數(shù)量的增加,問題也逐漸暴露出來:
- 全流程服務有 8 個下游服務,而不同的下游服務具有不同的限速策略。
- 機器初始化時間過長,單次初始化耗時超過 5 分鐘。
- 單次上線超過千臺機器時,工單可能會卡死。
為了解決限速的問題,根據(jù)不同限速策略全流程做了最大限度地兼容。例如:當掛載的機器超過 200 臺時,全流程會將機器按每組 200 臺進行分組掛載,并確保容器的檢查頻率不超過 10 毫秒/臺。
對于耗時問題,利用云上的鏡像功能,將需要部署的服務提前打入鏡像中。這樣在上線虛擬機時,無需對機器進行初始化,大大縮短了機器上線的時間。然而,這種情況下的機器上線流程與之前完全不同。得益于調度器最初的設計便利性,我們?yōu)樵粕咸摂M機上線單獨增加了一套任務流,并將上線流程從 23 步精簡到 10 步,大幅縮短了機器上線的時間。
圖片
對工單卡死的問題,通過排查發(fā)現(xiàn)瓶頸主要出現(xiàn)在 etcd 和 MySQL 上。在調度器設計之初,為了確保步驟執(zhí)行的連貫性,調度器會持續(xù)獲取未關閉的 MySQL 任務并嘗試在 etcd 上獲取鎖。已獲取到鎖的進程執(zhí)行任務,未獲取到鎖的任務會不斷嘗試獲取。在高并發(fā)情況下,這種模式可能導致鎖丟失。因此,針對任務,我們在數(shù)據(jù)庫中新增了 isRunning 字段,用于判斷任務是否已在運行。對正在運行的任務,調度器不再獲取任務列表,也不再嘗試搶鎖。此外,我們對數(shù)據(jù)庫關鍵字段添加了索引以減少任務查詢耗費的時間。雖然這樣做會損失部分任務執(zhí)行的連貫性,但卻換來了穩(wěn)定性的極大提升。通過一系列優(yōu)化措施,云上虛機的上線效率也提升到了1.5分鐘/千臺,滿足了日常彈性伸縮的需求。
成本優(yōu)化
彈性云成本主要集中在三部分,即服務器費用、定價服務費用和人力費用。其中,服務器費用每個月占了總成本的大部分。為了降低成本,彈性云可以采取容器治理和宿主縮容等措施來減少服務器定價支出,并降低對彈性云平臺服務器的投入。彈性云機器資源可分為三類:線上實際使用資源、線上 buffer 資源和低負載(閑置)資源。通過對這些資源進行優(yōu)化,有效降低了彈性云機器方面的成本。
圖片
機器下線加速
經過之前的優(yōu)化,彈性云機器的上線耗時已基本符合預期。由于機器下線和各業(yè)務的穩(wěn)定性相關,下線耗時仍處于一個較高的水位。隨著各類成本優(yōu)化項目的開展,彈性云在2023年預計退還大量機器,但根據(jù)以往的經驗來看,完全退還這些機器可能需要約2年時間,這個速度顯然無法滿足需求。機器下線耗時較長的原因主要有兩個:
- 機器下線時需要按機器串行漂移容器,每臺宿主機器漂移容器約需10分鐘,每天最多可漂移50臺機器。
- 彈性云存在一些容器無法漂移,并且還存在許多無主容器。在機器下線時,這些無主容器沒有人處理,由于不清楚其影響范圍,這些機器也不能輕易關機。
為了提升容器漂移速度,我們對下線流程進行了優(yōu)化。將漂移方式由“按機器串行漂移”改造為“按集群并行漂移”,在不打破1、2、10原則的前提下盡可能地漂移容器。在確保穩(wěn)定性的前提下,容器漂移速度由每天50臺提升到了每小時100臺。針對無主容器,我們與 SRE 及各業(yè)務線同學合作進行清理,并對長期無人處理的容器制定了下線標準,即:
- 每天向負責人發(fā)送通知,連續(xù)三次通知后,對不符合兜底策略的集群負責人進行拉群通知。
- 在拉群通知后觀察一天,對仍未處理的集群,關閉對應宿主機并觀察三天。
- 如果在三天內用戶反饋異常,我們將在一小時內對容器進行恢復操作。如果三天后仍然無人反饋,將進行機器退還操作。
通過新的漂移流程和下線標準,可以有效提升彈性云機器的下線宿主,同時也能確保各優(yōu)化項目的穩(wěn)定推進。
圖片
低負載資源治理
彈性云2022年低負載時間大于10天的機器存在不少,優(yōu)化低負載機器的數(shù)量能降低部分彈性云成本,低負載資源在彈性云可分為以下兩類:
- 預期內低負載:新機房交付還未投入使用、控制面機器利用率較低等
- 預期外低負載:機器交付忘記上線、測試后忘記退還等原因導致機器處于閑置狀態(tài),部分機器過保、維修后無法上線且未進行置換、退換等。
全流程為此開發(fā)了閑置資源管控模塊,自動對閑置機器操作人進行通知。指定用戶可對預期內低負載機器進行豁免,而長期未豁免的機器將自動退還。這樣可以最終消化存量的預期外低負載機器并減少新增情況。
總結
在彈性云的發(fā)展過程中,宿主機的生命周期管理是一個重要的問題。最初,機器的上線操作是手動進行的,導致上線速度緩慢。
為了解決這個問題,彈性云開發(fā)了宿主生命周期管理平臺(mmachine)。通過不斷優(yōu)化和改進,mmachine 縮短了機器上線的耗時,提高了效率,并通過定制下線標準、并發(fā)漂移等方式,縮短了機器下線周期,在保障穩(wěn)定性的前提前下,加速退還彈性伸縮、機器置換等項目節(jié)省下來的資源。通過自動報修、低負載治理等模塊,mmachine 將資源充分利用起來,提升了彈性云平臺的整體資源利用率,降低了彈性云服務器的成本。