當紅架構Cloud_Native_怎麼搭建才能成為上雲助攻手?

當紅架構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。

分散式跟蹤系統:在微服務架構下必須要做到與單體架構同樣的服務請求的調用路徑跟蹤能力,才能夠有效定位故障。可參考的框架有Zipkin,需要對RPC框架等做instrumentation,在調用過程中攜帶額外的頭信息。

性能管理服務:微服務架構下依賴關係複雜,發生性能問題時難以定位源頭及影響範圍,性能管理服務可提供調用關係拓撲,及時統計慢響應及錯誤響應,有利於發現性能問題與定位故障。以網易云為例,利用Kubernetes提供元信息,利用AOP對常用庫做instrumentation,可在無須配置及侵入代碼的情況下,自動繪製拓撲,分析性能。

下圖是我們內部性能管理的拓撲截圖:

三、總結

最後,陳諤將雲原生架構實現的要點總結如下,希望能給雲計算的用戶帶來有價值的參考:

  1. 使用公有雲;

  2. 重視項目工程化;

  3. 項目起步時建立服務化思維,而不要急於採用服務化架構帶來不必要的負擔;

  4. 實施微服務需權衡收益與成本,基於Kubernetes可簡化微服務實施;

  5. DevOps能與微服務架構良好匹配,但實施DevOps需要完善的工具鏈支持。

    原文地址:當紅架構Cloud Native,怎麼搭建才能成為上雲助攻手?

推薦閱讀:

Docker 基本原理
etcd集群配置
Dockerfile實踐
Docker 17.06-1發布,兩個重要的BUG修復

TAG:Docker | 架構 | 微服務架構 |