作者:陳諤,網易云基礎服務總經理,現負責網易云計算平臺產品線建設,對分布式系統設計開發、云計算平臺系統架構有一定的經驗和理解。近年來致力于帶領團隊推進公司開發技術棧的標準化、工具化。
網易云基礎服務團隊:網易云基礎服務擁有優質的硬件資源,經驗豐富的研發運維團隊,為各類客戶提供IaaS、PaaS服務。同時深度整合Docker與Kubernetes技術,打造專業的容器服務。
如何讓云成為業務成功的基石而不是障礙,是技術團隊需要不斷思考的問題,Cloud-Native正是一種讓業務技術架構向云而生,充分利用云特性的技術理念與方法論。在近期網易云技術布道系列活動中,網易云基礎服務總經理陳諤帶來了如何從0到1實踐Cloud-Native的精彩分享。
一、什么是Cloud Native?
說到Cloud Native,國內大多數都翻譯成云原生,就是讓云成為成功的基石,而不是障礙。陳諤對于為什么要實現云原生應用深有體會,網易從2012年開始實施云化的戰略,當第一版云計算平臺建好的時候,開始引導公司的項目逐漸向云遷移。這個過程中就遇到了一個問題:用上云之后,并沒有變得效率奇高,甚至有些項目的效率反而有所下降,大家都有很多抱怨。
從那時陳諤就有一個想法,云計算怎樣才能成為公司和開發團隊成功的基石,而不是用上云之后給你制造麻煩。他認為要做到這一點首先要理解云的優勢,規避云的弱點;另一方面要充分利用云的各層能力,幫助你去成功。所以云原生就是采用適合云端的軟件架構和研發模式去做這個事情。
二、如何實踐云原生?
關于如何實踐云原生,陳諤為大家分享了一些建議。假設大家不是類似BAT這樣規模的公司,或者有非常強大的IT團隊,在選擇技術路線時,陳諤建議大家使用公有云,為什么呢?
1、使用公有云
彈性
首先,使用公有云起步的成本非常低,不需要你去租機房、買物理機,每個月幾百塊錢就可以起步了。如果你成功了,在爆發性增長時,公有云也有足夠大的資源彈性幫助你從一臺Scale到幾百臺,而不需要臨時去買服務器。
網絡質量
另一方面,由于公有云的規?;?,網絡質量是自建不可比擬的:
有些公有云出入口的帶寬很大,甚至有些互聯網大廠的公有云平臺,用的基礎設施跟公司整體業務是一體的;
帶寬大的另一個好處是可以抵御DDoS和CC攻擊;
其次,公有云有更強的排障能力。國內的國情,網絡故障是非常難以排查的,需要有專門的IT團隊才能做好。
Managed Cloud Service
云計算有數據庫、中間件這些服務,并且不需要你去關注高可用部署、故障恢復、擴縮容等系統層面的運維,操作系統內核級掌控、中間件源碼級維護也均由云提供商負責,并且有明確的SLA保障。
高可用保障
此外,云計算可以幫你做高級別的高可用保障。日常的高可用保障,比如雙機熱備也好,冷備也好,都比不過公有云提供的多可用區的保障。云的多可用區至少是IDC級別的,在一個可用區內就像一張大網一樣,至少保證三層的連接,保證你的業務都是互通的,整體架構不用考慮跨機房的問題。
云還有多Region的保障,有一些公司會做異地多活的架構,當然這對業務的侵入性是很大的,但至少可以用多Region的設施,來做數據的災備。
另外,云的進化速度很快,會持續地更新,現在大多數都是基于Linux的技術棧,可能會不時地出現bug或安全漏洞,如果自己去跟進是非常困難的,公有云一般都會有專業的團隊,及時跟進和修復這些安全問題,又省下了用戶一筆人員開銷。
公有云的取舍
當然,公有云要支持這么大規模的用戶,本身有一定的取舍。
1)Design For Failure:公有云傾向于更快失?。ㄓ绊懛秶芸兀?、更快恢復。如果你用的是物理機,出現問題時你會關注這個物理機是不是還“活著”。而公有云如果發現一臺機器掛了,會直接進行服務遷移和重啟,因為公有云本身有SLA的承諾,為了保證系統的魯棒性,會更快地把這些疑似故障的節點排除掉。
2)由于公有云這樣的特性,日常業務必須結合公有云能力實施高可用架構:
- 一方面以可用域為基礎,實現高可用;
- 另一方面,將數據狀態和業務邏輯分離,如果業務被遷移走了,只要掛上原來的盤就可以恢復了;
- 節點可重啟或重建。
3)Design For Scale:虛擬化性能稍弱于物理機,公有云更追求交付的性能指標的穩定,避免租戶業務間的影響,支持業務做Scale。對于開發者來說:
- 一方面,要知道你采購的磁盤、網絡能夠提供的性能是什么,根據這些QoS指標去做容量的規劃;
- 另一方面要基于負載均衡、集群管理等能力去做Scale Out,而不是讓機器規格越變越大。
2、項目工程化
除了上面提到的基礎設施,在項目的工程化方面,陳諤也為大家帶來了一些啟示。他認為項目工程化是研發協作與云端運維的基礎,也是很多團隊在起步時可能會忽視的事情。項目的整個流程中,開發、測試、發布的每一步都涉及到公司內角色之間的協作,如果這些步驟做得不流暢,每一個環節的銜接非常困難,效率就會變的非常低,所以項目工程化是對高效構建、發布、運行流程的支持。
合理的版本控制工具
那么,如何做到項目的工程化呢?首先要選擇合理的版本控制工具與策略:
- Git是社區和業界公認的一個比較好的工具;
- 建議每個應用采用單一的Codebase(12Factors-1: Codebase),把整個開發,構建,發布的流程串聯起來,不至于拉下一個base還要決定這里面的代碼哪一部分要拿去構建。
常見的版本控制策略包括:
- 基于Merge的多分支策略,這種模式和多人協作的方式是匹配的,可以看到大家協作產生的代碼從分支到合并的過程,但是分支很多也造成了管理的復雜度很高;
- 如果團隊能切割得比較小,功能比較集中的話,可以采用基于Rebase的單Master分支策略,它沒有Merge信息,管理起來比較簡單。
基于配置的依賴管理
然后可以去做基于配置的依賴管理:
聲明依賴(Maven等),而不是把你的軟件包全拷貝在代碼庫下面,實現自動構建
建議聲明所有的依賴,包括運行環境的初始化,不隱式依賴系統庫(12Factors-2: Dependencies)
接下來要合理拆分模塊,可以按業務拆分模塊,同時實現公共代碼的模塊化。
使用Docker實現環境一致性
之前在網易,對穩定性要求很高的產品,其發布流程通常都很曲折,主要原因在于環境的不一致。陳諤的建議是使用Docker實現環境的一致性,Docker容器完整虛擬化了Linux操作系統,將業務代碼與運行環境裝箱為Docker容器發布到生產環境,差異僅僅為外部注入的配置(如數據庫地址等),容器內部文件在開發環境一旦發布則不再變化,從而保證開發環境與生產環境一致。
3、服務化的思維
工程化是做業務架構,建立一個高效團隊的基礎,接下來要考慮的就是服務化的思維。微服務是當下很流行的概念,采用微服務確實能為應用的迭代和架構帶來很多好處。但服務化的架構會帶來額外的負擔,如果一個項目還處在初期階段,我們的建議則是服務化思維先于服務化架構。
- 運維成本:一旦服務多了,環境搭建、故障診斷、運維的工作量都會成倍增加;
- 服務拆分之后,各個服務間的生命周期是不一致的,要做生命周期的分離,就需要處理更多的異常。服務間存在更多的約束,還是異步的,如依賴關系、版本,要保證消息能夠可靠地到達那里;
- 另一方面,還會有分布式事務的問題,雖然解決起來不難,但是會侵入你的業務。
雖然業務初期,不適合服務化,但應該為后續的服務化做一些準備,否則后面想拆分的時候會變得非常困難:
- 提取Service API,理解業務中的服務抽象;
- 數據庫設計的時候就考慮服務的劃分;
- 避免跨服務事務,對跨服務事務進行標記;
- 如果項目發展起來,遇到的第一個問題通常是數據庫會掛掉,所以在業務初期就做分庫分表是很有必要的;
- 選擇事務支持更好的數據庫,如果你用缺乏事務支持的數據庫做業務的后端,當你要做服務化拆分或分布式事務的時候,可能會比用MySQL的痛苦很多。
4、實施微服務
隨著業務的壯大,是否要采用微服務,就要去衡量微服務帶來的收益是否大于成本?
收益
- 控制迭代更新的影響域,而單體架構很難評估patch的影響范圍;
- 加速迭代,提交代碼心里負擔小,迭代也能加快;
- 隔離局部故障;
- 防止代碼架構層面的腐化,比如開發過程中為了趕進度,可能會把原有的架構推倒重來。如果用微服務架構,最多只需要將自己負責的那個模塊重新設計。
成本
- 更多的依賴(eg: ZooKeeper,MQ),要做一個注冊中心;
- 運維復雜度,幾十個服務發布更新,運維的復雜度必然會上升;
- 技術實現的侵入性,在這個過程中難免要用到一些微服務化的框架,雖然對代碼的侵入性不大,但對架構的侵入性還是不可避免的。
降低實施成本
- 良好的工程化,不要給運維的工作帶來很多困難;
- 使用基于云端托管的PaaS服務;
- 使用基于云端托管的編排服務,幫你去做集群化的運維和管理的工作。
基于Kubernetes簡化微服務實施
利用基于Kubernetes的基礎設施可以簡化微服務,一方面Kubernetes提供了基于域名的服務發現:
- 使用VIP+域名暴露服務:對比“注冊中心”,采用域名服務具有更小的侵入性,更少的依賴
- 支持名稱空間隔離,簡化測試環境部署
Kubernetes還可以做基于iptables的透明RPC分發:
- 無需在程序中訪問注冊中心獲取成員列表進行軟負載均衡;
- 無需內網負載均衡層次增加網絡開銷。
比如,服務A訪問服務B的虛擬IP VIP,利用iptables做DNAT,轉成B中的所有成員,服務A可以直接,并利用probability特性按權重分發請求,比域名做輪轉的負載均衡效果要好,因為iptables可控,域名不可控。
用Kubernetes還可以讓你獲得自動化運維能力:
- 自動擴縮容
- 自動故障處理(重試、遷移)
- 自動化滾動更新,通過健康檢查與滾動的配合實現無縫更新
- 還可以基于Service 抽象實現藍綠發布
Kubernetes以解耦的基礎服務層的方式提供了對服務化的支持,避免了代碼實現層面的耦合,通過云端托管Kubernetes服務能夠將實現服務化的成本大幅降低。而且Kubernetes對業務沒有侵入性,實現服務化的代價相對會比較小,后面業務變得非常重,需要細粒度控制時,再用到其它框架也沒有什么影響。
我們深度整合了Docker技術和Kubernetes集群編排技術,所以網易云中會有一個Kubernetes Master,所有租戶的業務都可以使用這個Master,不用用戶自己維護。
5、DevOps
前面講到的都是云原生相關的技術,實際上實現云原生還需要一些研發、運維和組織架構上的方式調整,比如DevOps。DevOps的出現是為了解決運維角色與開發角色的矛盾,運維追求的是可用率優先,而開發希望應用能快速更新迭代。
DevOps 與微服務
微服務架構能夠支持更高頻的迭代,降低更新迭代的風險,這與DevOps的目標是一致;但是微服務架構也會給運維帶來成倍的工作量,可基于DevOps分散運維操作,而不是集中依賴少量運維角色。
實施DevOps
實施DevOps需要CI/CD、編排、故障診斷等工具鏈的支持,同時需要運維實現從操作到審計的職能轉換,運維工作前置,在前期和開發團隊合作。很多運維還需要開發工具,提高運轉效率。
基于DevOps工具鏈支持微服務架構
1)Jenkins-容器-鏡像倉庫-服務編排
Pipeline as Code:實施服務化后持續集成的復雜度成倍增加,需要定義大量的流程,包含大量Jobs,以代碼的方式管理Pipeline能夠支持審計,有效管理復雜性并降低維護成本。
2)日志服務-分布式跟蹤系統-性能管理服務
日志服務:Kafka+ELK套件,以網易云為例自動完成容器日志收集,并提供訂閱接口可對接ELK。
分布式跟蹤系統:在微服務架構下必須要做到與單體架構同樣的服務請求的調用路徑跟蹤能力,才能夠有效定位故障??蓞⒖嫉目蚣苡衂ipkin,需要對RPC框架等做instrumentation,在調用過程中攜帶額外的頭信息。
性能管理服務:微服務架構下依賴關系復雜,發生性能問題時難以定位源頭及影響范圍,性能管理服務可提供調用關系拓撲,及時統計慢響應及錯誤響應,有利于發現性能問題與定位故障。以網易云為例,利用Kubernetes提供元信息,利用AOP對常用庫做instrumentation,可在無須配置及侵入代碼的情況下,自動繪制拓撲,分析性能。
下圖是我們內部性能管理的拓撲截圖:
三、總結
最后,陳諤將云原生架構實現的要點總結如下,希望能給云計算的用戶帶來有價值的參考:
- 使用公有云;
- 重視項目工程化;
- 項目起步時建立服務化思維,而不要急于采用服務化架構帶來不必要的負擔;
- 實施微服務需權衡收益與成本,基于Kubernetes可簡化微服務實施;
- DevOps能與微服務架構良好匹配,但實施DevOps需要完善的工具鏈支持。
文章來自微信公眾號:DBAPlus社群
本文鏈接:http://www.thecarconnectin.com/12367.html
網友評論comments