雲計算十字真言及其在小博無線的實踐
本文正在參加“最佳上雲實踐”評選,來給我們投票吧:https://yq.aliyun.com/activity/158(編號28)
小博無線2013年10月上雲以來,已在雲端飛行了三年整。作為小博技術團隊的早期成員之一,我有幸參與了雲端係統從單台主機進化為今天數十台主機, 上百個負載均衡, 數百個容器的略具規模的係統的全過程。本文是這三年來我們使用雲計算平台的經驗總結。
由於小博無線的整個雲端係統是搭建在阿裏雲計算平台上,本文中討論的所有工具都是基於阿裏雲的。然而,正如編程思想和實踐方法是與具體編程語言無關的,使用雲計算工具的思想和實踐方法也是獨立於工具存在的。
總的來說,雲計算平台作為承載互聯網業務的基礎設施,要把它用好,不外從兩方麵考慮:
- 高可用: 保證公司的業務流和現金流持續正常流動,不受服務不可用或服務質量下降的影響。
- 高利用: 在保證效果的前提下,盡可能少的購買資源並把購買的計算資源充分利用起來,不閑置,不浪費,將成本降至最低。
我們這三年來為了達成這兩方麵的探索和實踐可以總結為下麵這張圖:
圖中的5種基本實踐,本文將它們稱為"雲計算十字真言":
"冗餘, 漂移, 伸縮, 熔斷, 扁平"
冗餘
首先,隻有通過冗餘部署消除單點,才能實現高可用。 [1]
工具
雲磁盤和對象存儲
儲存在雲磁盤和對象存儲(OSS)中的數據都是自動冗餘的。
負載均衡(SLB)
SLB是我們最常用的工具,不僅能消除單點,還可通過增加後端節點來水平擴展業務。負載均衡自身的冗餘采用跨可用區的雙節點主備。
雲數據庫
我們使用了多個RDS和Redis實例, 它們的冗餘也是通過類似於負載均衡的雙節點主備來實現的。但與其他一些雲計算平台需要手動創建兩個實例並完成主備配置不一樣的是,阿裏雲的雲數據庫采用隱式主備,備用節點對用戶不可見。新建一個RDS或Redis實例時阿裏雲會自動創建好主節點和備用節點,並監控主節點狀態,當主節點故障時無需用戶幹預,運維機器人會自動進行主備切換,保證高可用。
實踐
- 所有基於TCP (http/https)或UDP的服務接口不能通過單台主機開放,必須通過負載均衡開放
- 雲主機(ECS)隻負責流量分擔和業務計算,不保存持久化數據
- 使用數據庫保存持久化數據, ECS通過訪問數據庫讀寫數據
- 給每個消息隊列至少分配兩個生產者和兩個消費者
一種高可用建站模式
綜合上麵介紹的工具和實踐方法,可以推出一種比較通用的高可用建站模式。
- DNS解析為負責流量接入的公網SLB
- 反向代理服務器組負責依據請求路徑區分出不同的業務類型,再根據業務類型將請求反向代理到業務對應的內網SLB
- 業務請求通過內網SLB最終達到計算節點,計算節點讀寫數據庫並返回處理結果
- 圖中第1,3,5層的SLB和RDS的冗餘由阿裏雲隱式實現,第2,4層的ECS需要我們顯式多點部署才能實現冗餘
漂移
冗餘可以有效的解決由於單點故障而停服的問題。然而,對於由n個服務節點組成的係統,每出現一個故障節點,係統容量就下降1/n。考慮僅有兩個服務節點的情形,其中一個點出現故障時,係統容量就會下降一半,這時係統的可用性已相當脆弱,服務質量也有可能由於容量縮水而大幅下滑。如何令係統在出現部分節點失效的狀況下仍能保持設計容量?一種行之有效的辦法就是新加入健康節點去替換失效節點,讓本來分布在失效節點上的流量漂移到新節點上。
工具
容器
要讓服務能夠漂起來,應先將服務容器化。Docker可以把一個服務的軟件運行時環境,代碼以及配置通過一個Dockerfile全部打包為一個image來統一部署和回滾,非常方便易用。
容器調度
我們選用的容器調度方案是Mesos + Marathon。Mesos將多台ECS的CPU和內存資源統一管理,無需關注容器具體部署到哪幾台主機上。Marathon可以為每種服務配置多個服務節點並配合健康檢查來實現高可用。如果健康檢查發現一個服務節點無法正常提供服務,Marathon就自動新建一個服務節點來代替這個失效節點,令健康的節點個數始終等於配置值,讓流量從失效節點漂移到新節點上。
SLB API
因為所有服務都通過負載均衡開放,所以我們需要使用SLB API來添加健康的新節點並移除失效的舊節點。
運維機器人
說到運維機器人,業內最著名的運維機器人恐怕要數Netflix的ChaosMonkey, 此猴最喜歡做的事情就是隨機關閉一些正常運行的雲主機。而我們開發的運維機器人具備的第一個功能卻是自動重啟已死機的ECS,所以我們給她取了一個和ChaosMonkey正好相反的名字 - TidyMaid
我們這一節介紹的"漂移",以及後麵兩節介紹的"伸縮"和"熔斷",都離不開TidyMaid。
實踐
無感知上線
利用漂移,可以實現在終端用戶完全無感知的情況下完成線上係統的變更。具體操作步驟如下:
- 創建新版本容器
- 調用API AddBackendServers將新版本容器所在的ECS加入SLB後端服務器組
- 調用API DescribeHealthStatus輪詢新加入的ECS的健康狀態,直到新節點在SLB的狀態為"健康"
- 調用API SetBackendServers將舊版本容器所在的ECS的分發權重設為0,等待1分鍾
- 銷毀舊版本容器
- 調用API RemoveBackendServers從後端服務器組移除舊版本容器所在的ECS
為了實現無感知上線,我們先將舊節點的分發權重設置為0,負載均衡就會停止向舊節點導入流量,再等待1分鍾讓此前正在處理中的流量處理完畢,然後銷毀舊節點,回收資源。每次上線變更,服務容器所在的ECS會發生變化,同時,線上流量在Mesos集群中漂移。
漂移帶來自由
流量漂移的方法不僅保持了係統平穩運行所需的設計容量,還為開發和運維帶來了新的自由。
舉個例子,本來防止內存泄露一直是服務器程序設計的一大難題,現在流量可以無感知漂移後,我們可以通過監控容器的資源占用並利用運維機器人銷毀使用內存過多的容器來釋放被泄露的內存。當容器被銷毀後,由於節點個數小於配置值,容器調度器會自動新建容器並讓流量漂移過去。緩慢的內存泄露往往極難調查並且周期性影響服務質量,但現在已無大礙。
再舉一例,當流量可以漂移後,ECS層麵的穩定性也就不那麼重要了,我們完全有能力在僅能穩定運行數小時的雲主機上構建出能穩定運行數月的服務。當ECS死機時,運行在上麵的業務節點都會由於健康檢查失敗而被標記為失效狀態,此時容器調度器自動新建容器來讓流量漂移過去,同時,運維機器人會自動重啟死機的ECS,讓它恢複活力。
伸縮
使用漂移解決了保持設計容量的問題後,又遇到新問題: "到底為每個業務分配多少資源才合適?"
流量通常是一個關於時間的函數,存在高峰和低穀。資源預留太少,安全邊際不夠,在高峰時段可能由於容量不夠而影響服務質量。但如果總是按高峰時段的流量來為服務分配資源,在低穀時段卻又很浪費。我們通過伸縮來優雅的解決資源分配的問題。
讓資源分配隨流量變化,流量變大時擴容,流量變小時縮容, 這就是伸縮。
實踐
擴容一般分為兩類:
- 水平擴容: 節點配置不變,通過增加服務節點個數擴容
- 垂直擴容: 節點個數不變,通過提高服務節點配置擴容
我們將服務容器的CPU利用率監控起來,如果過去15分鍾的CPU平均值高於80%,監控係統就通知運維機器人水平擴容一個節點。反之,如果CPU平均值低於40%就縮容一個節點。最少可縮至兩個節點。
同樣,將內存利用率也監控起來,如果過去15分鍾的內存使用超過80%, 監控係統就通知運維機器人將分配給容器的可用內存增加20%, 節點配置的內存達到2G後,考慮到單節點所需資源太多會導致難以匹配到有足夠多空閑資源的主機,改用水平擴容。如果過去15分鍾的內存使用低於40%, 就將分配給容器的可用內存減少20%,讓出資源給其他服務使用。
一種自動運維模式
運維自動化的關鍵在於完善監控體係和功能接口化。監控發現異常後,觸發運維機器人的接口進行相應的維護操作。需要注意的是,許多自動化功能必需雲計算平台的接口支持,比如漂移和伸縮,如果沒有SLB API的支持,都是無法實現的。
具體到伸縮的實現,我們使用Zabbix監控各容器的資源占用,資源占用過高或過低的狀況都會觸發Zabbix調用TidyMaid對應的Web API請求伸或縮,TidyMaid再調用Marathon和阿裏雲對應的Web API完成伸縮操作。
熔斷
綜合運用冗餘,漂移和伸縮,可以大幅提高係統的可用性。但是,任何係統都無法做到100%可用,當係統出現故障時,如何讓局部故障的影響停留在局部而不至於擴散出去影響全局?這就需要利用熔斷機製。如何在不同的業務場景下對不同的故障進行優雅熔斷,是非常具體,有時甚至是極具挑戰性的問題。在這裏我隻簡單介紹一下兩種比較常用的模式。
前後端分離
前後端分離具有天然的熔斷效果,當局部數據不可用時,不會影響整體頁麵渲染。
依賴監控與功能開關
如果功能模塊A依賴外部接口B,給模塊A設計一個開關接口,同時將B監控起來,一旦發現B不可用,運維機器人就調用A的關閉接口將功能A下線,等監控發現B重新可用後,運維機器人再調用A的打開接口將功能A上線。
在"漂移"一節介紹的無感知上線方案中的上線功能和SLB API就是一個很好的例子。由於上線功能依賴SLB API,當SLB API不可用時,我們就會熔斷上線功能,等SLB API可用後再重新接回。整個熔斷和接回的過程都由TidyMaid自動完成,無需手動幹預。
扁平
最後,為了提高資源利用率,應將各類業務容器無差別的分配到各個雲主機上,而不是將各個主機按功能的不同分開使用,這種無差別統一管理資源的思想就是扁平。
實踐
從4層負載均衡遷移到7層
在前麵"冗餘"一節介紹的高可用建站模式中,如果內網SLB使用4層轉發,當nginx服務器組的容器和業務計算服務器組的容器分布在同一個ECS上的時候,就會由於網絡打環而無法完成請求處理。對此,我們一開始是將Mesos集群中的ECS分為兩組,一組機器專門跑nginx容器, 另一組跑業務計算容器,後來則通過將內網SLB從4層遷移到7層,消除了分組,實現了扁平。
經典網絡中的反例
大多數的三方API服務存在訪問IP白名單的限製,因此在經典網絡中往往需要創建專門的服務器組來代理三方API請求。但在VPC中,由於請求可以通過NAT網關轉發,將網關的公網IP加入白名單即可,無需額外創建專門的代理服務器組。
[1]: 消除單點的具體實踐方法在"應該如何使用阿裏雲"係列文章中有更多介紹,感興趣的讀者可訪問: https://bbs.aliyun.com/read/179606.html?spm=5176.bbsr179606.0.0.Zd9Ph6
最後更新:2017-11-21 18:03:48