​[轉載]雲原生(Cloud Native)

分享此文:

Cloud Native is structuring teams, culture and technology to utilize automation and architectures to manage complexity and unlock velocity.

雲原生應用,是指原生為在雲平台上部署運行而設計開發的應用。公平的說,大多數傳統的應用,不做任何改動,都是可以在雲平台運行起來的,只要雲平台支持這個傳統應用所運行的計算機架構和操作系統。只不過這種運行模式,僅僅是把虛擬機當物理機一樣使用,不能夠真正利用起來雲平台的能力。

雲原生能幫助企業高效、快速、穩定、大量地完成軟件交付工作。持續交付、開發運維一體化(DevOps)、微服務是雲原生的關鍵。雲原生既有利於塑造團結信任的企業文化,又能有效利用自動化提升工作效率,讓良好的運營促進公司更快更穩定地發展。

雲原生應用與相關技術理念的關係

雲原生應用與雲平台的關係

雲平台是用來部署、管理和運行SaaS雲應用的。 SaaS是雲計算的三種服務模型之一,即跟業務相關的應用即服務。雲計算最根本的特性是提供按需分配資源和彈性計算的能力,而云原生應用的設計理念就是讓部署到雲平台的應用能夠利用到雲平台的能力,實現按需使用計算資源和彈性伸縮,成為一個合格的SaaS應用。

雲原生應用與12要素的關係

12要素是PaaS平台Haroku團隊提出的應用設計理念,是有關SaaS應用設計理念的紅寶書;可以說,12要素應用就是雲原生應用的同義詞。

雲原生應用與Stateless和Share Nothing架構的關係

為了實現水平伸縮的能力,雲原生應用應該是Stateless和Share Nothing的。

雲原生應用與微服務架構的關係

微服務架構是實現企業分佈式系統的一種架構模式,即將一個複雜的單體應用按照業務的限定上下文,分解成多個獨立部署的組件。這些獨立部署的組件,就稱為微服務。而在談論云原生應用與微服務架構關係的時候,根據上下文不同可能是有兩種不同的含義。一種含義是宏觀的雲原生應用,即將整個分佈式系統看作一個應用,這種語境下,微服務架構是實現雲原生應用的一種架構模式;另一種含義是微觀的雲原生應用,即每個微服務是一個應用,這種語境下,每個微服務要按照雲原生應用的設計理念去設計,才能真正實現微服務架構所要達到的目的,即讓分佈式系統具備按需使用計算資源和彈性伸縮的能力,這裡“應用”和“服務”變成了同義詞。

雲原生應用與寵物和牲畜的關係

雲原生應用的設計理念是希望把應用當作牲畜來養,而不是當作寵物來養。部署一個雲原生應用的集群,就好像圈養了一大群奶牛,目的主要是為了產奶,對待每頭牛就像對待機器一樣沒有什麼感情,死了一頭就再養一頭,而不會像對待寵物那樣細心呵護。而傳統應用,因為往往因為對運行環境依賴嚴重,運維人員需要細心照顧、維護,萬一出現宕機,一般要在原來的服務器上修復問題再恢復運行;如果恢復不了,整個應用系統就癱瘓了,因此會令運維人員像“寵物死了”一樣傷心。

雲原生應用的設計理念——12要素

一個應用對應一套代碼多次部署

這一理念主要是強調應用應該清晰明確地區分什麼是應用,什麼是部署。一個應用對應的就是一個代碼倉庫,一個軟件產品;一次部署對應的是一個運行起來的應用;因此應用與部署的關係是一對多。這種一對多的關係也體現了應用代碼的可重用性,一套代碼可以重用到多次的部署中去;不同部署之間的區分是配置,而代碼是共享的。對應用架構來說,最基本的是要區分運行時行為和非運行時行為,一個應用的非運行時的代表就是一個代碼倉庫,它可能有多個運行時實例,每個實例就是一次部署。

明確地聲明並隔離依賴的程序庫

不管用什麼語言開發應用,編程語言一定都有管理程序庫的機制。這一理念強調所有依賴庫一定要明確的聲明出來,因為只有這樣,在運行應用的時候,才能保證所有運行所需要的程序庫都正確部署到了雲環境中。

將配置存儲到部署環境中

正像前面所說,一個應用的不同部署之間是共享一套代碼的,不同之處是配置。代碼是存儲到代碼倉庫中的,那自然配置不應該是存到代碼倉庫中。每次部署都有自己獨立的部署環境,每次部署所對應的配置要存到這次部署所對應的部署環境中去,因此配置的另一個同義詞就是環境變量。這裡的部署,不包括應用內部的配置,例如Java的Properties文件或者是Servlet的映射配置文件web.xml等,這些算作是代碼而不是配置。這是一個容易令人混淆的地方,那到底什麼算代碼,什麼算配置?判斷的標準很簡單,就是變化的頻率。變動導致產品版本更新的,就是代碼;每次部署都可能變更,而每次變動不導致產品版本更新的,就是配置,就是環境變量。

將後端支撐服務作為掛載資源來使用

這一理念強調應用使用後台支撐服務的方式。不同的服務之間的區別就只是資源的URL不同,也就是設定這個資源的相關環境變量不同。不管是本地資源還是遠程資源,應用程序都可以正常使用,區別只是環境變量的值不同,而應用本身並不會因為環境變量不同而有所區別。最常用的後台支撐服務就是數據庫、緩存、消息隊列等服務。這一理念可以保證應用在任何環境都可以正常運行,不會因為後台支撐服務的變化而導致應用無法運行。

嚴格區分構建階段和運行階段

這一理念跟區分應用和部署類似,本質上也是要嚴格區分應用的非運行時行為和運行時行為。構建是將應用的代碼倉庫編譯打包成可運行的軟件的過程,是非運行時行為。因此說,這一理念另一方面也說明要防止在運行階段改代碼的行為,這樣才能夠保證運行中應用的穩定性。

將應用作為無狀態的進程來運行

這一理念要求所有的用戶數據都要通過後端支撐服務來存儲,而應用本身是無狀態的,因為只有這樣,應用才能做到水平伸縮,從而利用雲平台彈性伸縮的能力。

僅需要綁定一個端口就可以對外發布一個服務

這一理念強調應用本身對於發布服務的環境不應該有過多的要求,而應該是完全自包含的,也就是說不需要依賴雲平台提供應用運行容器,而只需要雲平台分配某個端口對外發布服務。這一理念保證應用可以使用雲平台中任意分配的端口發布服務。

可以像UNIX進程一樣水平擴展

在UNIX操作系統上,不同的進程彼此獨立地運行著,共享這整個操作系統管理的計算機資源。雲原生應用在雲平台上的運行模式也是類似的,雲平台就是分佈式操作系統,不同的雲原生應用彼此獨立互補干擾的運行在一個雲平台上,可以充分利用雲平台的整體計算能力。

可以快速啟動和優雅地關閉

快速啟動是為了能充分利用雲平台根據需要調度資源的能力,能夠在需要的時候,以最小的延時擴展計算能力提供服務。優雅地關閉,一方面是為了釋放資源,將不再使用的計算資源歸還雲平台;另一方面也是為了保證應用邏輯的完整性,將該完成的任務正確完成,未能完成的任務重新交回到系統由其它應用的運行實例來繼續完成。要假設雲原生應用的目標工作環境中隨時有大量同樣的應用實例在運行、啟動和關閉,因此快速啟動和優雅關閉對高性能和穩定的系統非常重要。

保持開發環境、預發布環境和生產環境盡量一致

保持環境一致,是為了提高開發單元測試、功能測試和集成測試的有效性,避免出現開發測試中正常而在生產環境中出現問題的情況。

將日誌作為事件流來處理

雲原生應用運行在復雜的分佈式基礎設施之上,如果日誌不通過簡單統一的模式來管理,將給系統排錯或通過日誌挖掘信息帶來很大困難。同時,如果應用將日誌輸出到系統的文件中,也會給系統的存儲空間造成壓力,增加系統運維的複雜性。因此這一理念推薦應用將日誌輸出到標準輸出,然後由雲平台統一收集處理。

將應用管理任務當作一次性進程來運行

將應用的管理任務與應用的業務請求以相似的方式運行,以同樣的方式進行調度、日誌和監控,將有利於系統的穩定性和分析系統的整體行為。

雲原生應用的挑戰

處理分佈式系統的網絡通信問題

雲原生應用必須要針對分佈式系統中網絡通信的複雜性進行設計。對於分佈式系統,如果還像單一進程應用那樣考慮問題,就會進入所謂的“分佈式系統的認識誤區”,包括武斷地認為:網絡是可靠的;網絡的延時為零;網絡帶寬是無限大的;網絡是安全的;網絡拓撲是不變的;系統中只有一個管理員和網絡環境都是統一一致的。也許現在很少會有人幼稚到真的認為分佈式環境中的交互處理和運行在單一進程中的函數調用是一樣的;但開發的複雜度、功能上線的壓力,經常會使開發人員把這些複雜問題暫時放在一邊,不斷積累起越來越多的“技術負債”。

處理分佈式系統的狀態一致性問題

分佈式系統的CAP理論認為,在分佈式系統中,系統的一致性、可用性和分區容忍性,三者不可能同時兼顧。當然,實際在分佈式系統中,由於網絡通信固有的不穩定,分區容忍性是必須要存在的,因此在設計應用的時候,就要在一致性和可用性之間權衡選擇。

最終一致性

很多情況下,在一致性和可用性之間,雲原生應用比傳統應用更加偏向可用性,而採用最終一致性代替傳統用事務交易保證的ACID一致性。傳統的ACID一致性編程模型與業務無關,開發人員對它經驗豐富,而最終一致性的交互模式與業務相關,必須通過業務的合理性來校驗階段不一致的合理性,這使得最終一致性比ACID一致性複雜得多。

服務發現和負載均衡

雲原生應用的運行實例隨時可能關閉和啟動,因此需要機制使得訪問應用服務的客戶端隨時都能找到健康運行的實例,放棄對宕機實例的訪問,這就是服務發現的問題。與服務發現同時存在的,是在多個健康實例中選擇一個實例真正為某個客戶請求提供服務的過程,這就是負載均衡。

任務分解和數據分片

大的任務要分解成很多小任務,分配到各個運行實例上去執行,然後再將執行結果匯總,這就是任務分解。數據分佈到各個實例上做處理和存儲,這個就是數據分片。這些都需要適應云計算環境的機制去支持。

主控角色選舉

不管是任務分解還是數據分片,每個應用實例上負責的子任務和數據分片雖然是不同的,但如何分解、誰負責誰這種分配映射表一定是完全相同的;因此在這種情況下,需要負責計算分配映射表的主控角色;而因為雲計算環境下沒有實例是永遠保證健康運行的,主控角色不可能是永遠固定的;這就需要主控角色選舉的機制,能夠在主控角色空白或出現故障宕機的情況下,自選舉出新的主控角色。

像設計模式解決面向對象設計中的複雜問題一樣,面對雲原生應用的複雜應用場景,我們也需要一些典型的設計模式能夠可重用地解決一些特定場景的問題。

原文作者: Feisky

原文鏈接:http://feisky.xyz/cloud/native/index.html

發表迴響

This site uses Akismet to reduce spam. Learn how your comment data is processed.