官术网_书友最值得收藏!

1.2 什么是云原生

云原生(Cloud Native)最初是由 Pivotal公司的Matt Stine于2013年提出的。Pivotal公司先后開源了云原生的Java開發框架Spring Boot和Spring Cloud。隨后,Google在2015年成立了CNCF(Cloud Native Computing Foundation),使得云原生受到越來越多的關注。

1.2.1 概述

要想理解什么是云原生,我們需要先理解什么是云。

有人認為“云”的同義詞是“可公開所有信息的互聯網”,這個說法是不正確的。云一般指的是一個提供資源的平臺,云計算的本質是按需分配資源和彈性計算。

顧名思義,云原生應用即專門為在云平臺部署和運行而設計的應用。云原生應用并非完全顛覆傳統的應用,采用云原生的設計模式可以優化和改進傳統應用模式,使應用更加適合在云平臺上運行。

在云計算越來越流行的今天,云原生成了一個必然的導向。云原生存在的意義是解放開發和運維,而不是讓開發和運維工作變得更加復雜和繁重。

其實,大部分傳統應用即便不做任何改動,也可以在基于 Linux 操作系統內核的云平臺上部署和運行,但是僅以能夠部署和運行為主要目的,將云主機當作物理機一樣使用,是無法充分利用云平臺的能力的。

讓應用能夠利用云平臺實現資源的按需分配和彈性伸縮,是云原生應用被重點關注的地方。云原生還關注規模,分布式系統應該具備將節點擴展到成千上萬個的能力,并且這些節點應具有多租戶和自愈能力。

云原生使得應用本身具有“柔性”,即面對強大壓力的緩解能力以及壓力過后的恢復能力。正所謂“剛而易折,柔則長存”,對于一個單機處理能力很強的“剛性”系統而言,一旦崩潰,則很難恢復;而通過云原生實現的關注分布式與可水平伸縮的“柔性”系統,是不太容易全線覆滅的。

從本質上來說,云原生是一種設計模式,它要求云原生應用具備可用性和伸縮性,以及自動化部署和管理的能力,可隨處運行,并且能夠通過持續集成、持續交付工具提升研發、測試與發布的效率。

在云原生體系中,有下面兩組詞語用于形容應用。

無狀態(stateless)、牲畜(cattle)、無名(nameless)、可丟棄(disposable):表示應用并未采用本地內存和磁盤存儲狀態和日志,因此可以將應用隨意部署到另一個全新的環境中,在本書中我們將這類應用統稱為無狀態應用。

有狀態(stateful)、寵物(pet)、有名(having name)、不可丟棄(non-disposable):表示應用狀態將依賴于本地的運行環境,因此無法將應用隨意部署至其他環境,應用是不能隨意擴展的,在本書中我們將這類應用統稱為有狀態應用。

1.2.2 云原生與十二要素

十二要素(The Twelve Factors)是由Heroku團隊提出的云應用設計理念,它為構建流程標準化和高可移植的SaaS應用提供了完善的方法論。遵循十二要素設計的應用具備云原生應用的所有特征。十二要素適用于任何語言開發的后端應用服務,它提供的方法論和核心思想如下。

將流程自動化和標準化,降低新員工的學習成本。

劃清與底層操作系統間的界限,以保證最大的可移植性。

適合部署在現代云平臺上,避免對服務器與操作系統進行管理。

將開發環境與生產環境的差異降至最低,便于實施持續交付和敏捷開發。

應用可以在不改變現有工具、架構或開發流程的情況下,方便地進行水平伸縮。

十二要素重點關注應用程序的健康成長,開發者之間的有效代碼協作,以及避免軟件腐蝕。十二要素的內容如圖1-8所示。

圖1-8 十二要素

下面我們來逐條介紹一下十二要素。

1.基準代碼(Codebase)

同一應用對應同一套基準代碼,并能夠多次部署。

部署到不同環境的同一個應用,其基準代碼庫應該相同,但每份部署可以包含各自環境中的不同配置。一次部署對應一個運行起來的應用程序,應用與部署的關系是一對多的,這體現了應用代碼的可重用性。同一套基準代碼可以重用到多次部署中去,共享的是代碼,而不同的僅僅是配置。從另一個角度來說,非運行時的應用對應的是代碼倉庫,它的每一個運行時實例都對應一次部署,同一代碼倉庫可以保障應用的復原能力。

推薦使用 Git、SVN 等優秀的源代碼管理工具作為基準代碼庫。基準代碼與部署的關系如圖1-9所示。

圖1-9 基準代碼與部署的關系

2.依賴(Dependencies)

顯式聲明第三方依賴。

隨著技術的發展,應用程序的開發已不再是一個從零開始的過程,大量的第三方類庫使得工程師們可以站在巨人的肩膀上進行增量式開發。應用程序不應隱式地依賴類庫,而是應該通過依賴清單明確地聲明其依賴項。

顯式聲明依賴簡化了環境配置流程,開發工程師僅需要安裝編程語言環境和它對應的依賴管理工具,并從代碼庫中檢索出代碼,即可通過一個命令來構建所有的依賴項,從而輕松地開始工作。

十二要素要求應用同樣不應該隱式依賴某些系統工具,比如 curl。即使這些系統工具存在于所有的現代操作系統中,也無法保證未來的操作系統都能支持或兼容現有應用的使用方式。

現代編程語言都會提供依賴打包管理工具,如Java語言的 Maven、Gradle以及早期的Ant等。

3.配置(Config)

將配置存儲至環境變量。

應用的配置在不同環境中部署時也會有所差異,若應用將配置以編碼的方式寫入程序的常量,則會造成代碼與配置混淆。十二要素強調配置應該與代碼分離,不應在源碼中包含任何與環境相關的敏感信息。

雖然將配置提煉到屬性文件可以實現將其與代碼分離,但屬性文件仍然可能會被不小心地提交至源碼倉庫。因此,十二要素推薦將配置存儲于環境變量中,這樣可以非常方便地在不同的部署環境間修改,而無須改動代碼。

與配置文件相比,環境變量與語言和系統無關。將配置存儲在環境變量中能夠方便與Docker等基于容器的應用配合使用,也易于與Kubernetes的ConfigMap配合使用。將配置排除在代碼之外的標準取決于,應用是否可以立刻開源且不必擔心暴露任何系統的敏感信息。

十二要素并不贊同采用配置分組的方式管理配置。有些開發團隊愿意將應用的配置按照特定的環境(如開發環境、測試環境和生產環境)進行分組。采用配置分組方式不利于擴展,當工程師添加他們自己的開發環境(例如 john-dev)時,將導致各種配置組合激增,給管理部署增加額外的不確定性。

十二要素要求環境變量的粒度足夠小且相對獨立,它們不應該作為環境組合使用,而是應該獨立存在于每個部署之中。當應用程序擁有更多種類的配置項或進行環境部署時,采用這種配置管理方式更容易實現平滑過渡。

需要特別指出的是,這里所指的配置并不包括應用程序的內部配置。舉例來說,Spring 容器中Bean的依賴注入配置,或者Servlet的映射配置文件web.xml等,它們更應該被認為是代碼的一部分。

4.后端服務(Backing Services)

將后端服務作為松耦合的資源。

后端服務是指應用程序所依賴的通過網絡調用的遠程服務,如數據庫、緩存、消息中間件以及文件系統等,不同后端服務之間的區別僅僅在于資源的URL不同。

十二要素要求應用程序不應該區別對待本地服務和遠程服務,它們同樣都屬于附加資源。應用程序可以在不改動任何代碼、僅修改資源地址的情況下,將出現硬件問題的數據庫切換為備份數據庫,或將本地數據庫切換為云數據庫。應用程序與這些附加資源應該保持松耦合的狀態。圖1-10展示了后端服務松耦合的狀態。

圖1-10 后端服務松耦合的狀態

5.構建、發布、運行(Build、Release、Run)

嚴格分離構建階段與運行階段。

分離構建階段與運行階段的根本在于,要嚴格區分應用的非運行時狀態和運行時狀態。構建是將應用的源代碼編譯打包成可執行軟件的過程,屬于非運行時行為。將基準代碼轉化為一份部署一般要經過構建階段、發布階段和運行階段。構建階段是將源碼從編譯狀態轉化為可執行的二進制文件的過程;發布階段是將構建結果與當前部署所需要的配置相結合,并分發至運行環境的過程;運行階段是在執行環境中啟動一系列發布完畢的應用程序進程的過程。

十二要素規定,禁止在運行階段改動代碼,這樣做會導致基準代碼失去同步。建議每個發布版本對應一個唯一的發布 ID,發布版本只能追加而不能修改,除了回滾,其他變動都應該產生新的發布版本。構建與發布的流程如圖1-11所示。

圖1-11 構建與發布的流程

6.進程(Processes)

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

應用進程應該是無狀態的。只有無狀態的應用才能做到水平伸縮,從而利用云平臺彈性伸縮的能力,而需要持久化的數據應該存儲于后端服務中。

在有些遺留系統的設計中,Web應用通常會將用戶會話中的數據緩存至內存,并保證將同一用戶的后續請求路由到同一個進程,這種會話被稱為黏性會話。十二要素并不推薦這種做法,會話數據應該保存至 Redis 這樣的帶有過期時間的緩存中,并作為后端服務提供服務。

7.端口綁定(Port Binding)

通過端口綁定對外發布服務。

應用本身對于發布服務的環境不應該有過多的要求,不需要依賴云平臺提供應用運行容器,只要云平臺分配某個端口對外發布服務即可。通過端口綁定訪問服務也意味著任何應用都可以成為另一個應用的后端服務。

例如,可以利用Jetty這種內嵌的Web服務器或Spring Boot等快速開發框架來開發包含可發布HTTP服務的應用。

8.并發(Concurrency)

能夠通過水平伸縮應用程序進程來實現并發。

云平臺操作系統與UNIX操作系統類似,運行在系統之上的不同進程彼此獨立并且共享操作系統管理的硬件資源。不同的應用彼此獨立、互不干擾地運行在一個云平臺上,可以充分利用云平臺的整體計算能力。這樣的進程模型對于系統擴容非常實用。

開發人員應該將不同類型的工作分配給不同的進程,例如,將HTTP 請求交給Web服務器的進程來處理,將常駐后臺進程交給 worker 進程負責,將定時任務交給clock進程負責。這條原則與微服務的設計原則有異曲同工之妙,它希望應用開發者將應用的職責盡可能進行拆分。圖1-12清晰地展示了如何通過增加不同類型的應用進程來實現系統的水平伸縮。

圖1-12 通過增加不同類型的應用進程來實現系統的水平伸縮

9.已處理(Disposability)

可以快速啟動和優雅關閉應用。

快速啟動是為了充分利用云平臺根據需要調度資源的能力,在需要的時候,以最小的延時擴展計算能力,提供服務。優雅關閉是為了保證應用邏輯的完整性,將該完成的任務正確完成并釋放資源,將未能完成的任務重新交回系統由其他應用的運行實例來繼續完成。隨時可能有大量部署在云平臺上的應用實例啟動、運行和關閉,因此快速啟動和優雅關閉應用對于維持系統的高性能和穩定性尤為重要。

10.開發環境與線上環境等價(Dev/Prod parity)

要保持開發環境與線上環境等價。

開發環境和線上環境之間存在著很多差異,主要包括代碼差異和操作差異。開發人員正在編寫的代碼可能需要很長時間才會上線,這將導致開發環境和線上環境的代碼差異很大。在開發環境中,代碼一般由開發人員編寫并調試,而在線上環境中,代碼則由運維人員部署,不同的操作方式也可能帶來環境的差異。

保持環境一致,可以提高功能測試和集成測試的有效性,避免出現開發環境測試正常但生產環境出現問題的情況。推薦使用Jenkins等持續集成工具來縮短生產代碼和代碼庫中的代碼不一致的時間,并采用自動化部署的方式避免操作差異。

11.日志(Logs)

使用事件流處理日志。

運行在云平臺上的應用處在復雜的分布式基礎設施之上,如果日志仍然寫在硬盤的一個文件中,將給系統排錯或通過日志挖掘信息帶來很大的困難,并且當日志與應用綁定時,應用不能作為無狀態進程,也就無法充分利用云平臺的擴容能力了。

為了解決以上問題,我們應采取相應措施——應用將日志輸出到標準輸出(STDOUT),然后由云平臺統一收集并處理。在線上環境中,進程的輸出事件流由運行環境截獲,運行環境會將所有輸出事件流整合在一起,然后發送給一個或多個最終的處理程序,用于查看或長期存檔。

推薦使用 Flume、Filebeat 或 fluentd 等日志收集工具。日志事件流最終可以被發送到Elasticsearch或 Splunk 這樣的日志索引及分析系統中,用于排錯查詢和后期分析。

12.管理進程(Admin Processes)

將后臺管理任務當作一次性進程運行。

與用來處理應用的常規業務進程不同,工程師經常希望執行一些用于管理或維護應用的一次性任務,這類任務被稱為后臺管理任務,例如檢查和清理環境、遷移數據等。

這些后臺管理任務應該作為一次性進程,與常駐進程使用同樣的環境,基于同樣的代碼庫和配置發布運行。總而言之,一次性進程同樣應該遵循前面提到的十一個要素。

遵循十二要素的應用程序環境是一次性且可復制的。由于應用程序的狀態均通過后端服務持有,因此無狀態的應用有助于編排系統自動化擴展。擴容時,編排系統僅須將應用程序的運行時環境數量擴充到期望位并直接啟動進程即可;縮容時,則需要停止應用進程并刪除環境,無須進行環境狀態備份。

要想了解有關十二要素的詳細內容,請參見官方網站:https://www.12factor.net/。

1.2.3 十二要素進階

在十二要素發布之后,就職于Pivotal公司的Kevin Hoffman出版了Beyond the Twelve-Factor App一書,書中不僅對原十二要素進行了更加詳細的闡述,還增加了三個新要素,具體如下。

1.優先考慮API設計(API first)

在云原生應用中,系統之間的跨進程調用是不可避免的,因此對于開發者而言,設計出合理的、具有高兼容性的交互API是首要任務。

API如同契約,一旦生效,就應該盡可能少地被改動。若API在投入使用后再進行修改,其影響范圍可能不易掌控,還會波及很多外部系統。相反,在API不改動的情況下,修改內部實現則相對容易。

無論使用RESTful API、WebService API,還是同構語言的接口級別API,都應該優先勾勒一個API的設計藍圖。

設計一個具有前瞻性的API并不容易,在很多情況下需要對現有的API進行改動。每次對API 進行改動都需要做到向后兼容,并為每次改動提供唯一的版本號。應盡量避免廢止原有的API,以及修改原有API中已經存在的屬性,而應該通過增量的方式增加新的功能。

2.通過遙測感知系統狀態(Telemetry)

對于部署在云環境上的應用,其系統環境是封閉且隔離的,在出現狀況時不應該登錄有問題的物理服務器去觀察和收集應用的狀態,況且不同的云原生應用實例是無差別地被混合部署在物理機上的,如果采用微服務架構,應用的實例數量還會呈幾何級增長,出現問題時通過登錄物理服務器來解決是不現實的。

云原生應用的無狀態特性使得解決故障變得非常簡單。應用本身出現問題時可以直接關閉該應用進程,物理服務器出現問題則可以直接將該服務器移出集群。通過調度編排系統可以自動在其他服務器上啟動相應個數的實例,整個過程基本不需要人為參與。因此云原生應用需要通過遙測來感知應用以及服務器本身的狀況,暴露盡量多的監測信息為運維工程師或云調度系統提供判斷和處理問題的依據,應用本身則需要提供包括 APM 信息、健康檢查、系統日志在內的采集數據。

將云原生應用比喻為一個太空探測器比較貼切。它可以通過遙控的方式采集它所在星球的各類樣本,但無須通過宇航員真正登陸那個星球來完成每個操作。

3.認證和授權(Authentication and Authorization)

雖然十二要素中并沒有提到安全問題,但在云環境中,安全是至關重要的。開發者通常關注更多的是如何實現業務功能,但與此同時,開發者需要知道,云原生應用所運行的云環境中可能包含某些不為人知的其他應用。

將安全問題完全拋給云平臺是很危險的,因此建議采用OAuth2認證和RBAC授權等比較完善的安全機制。

十二要素以及以上三個補充要素為設計云原生應用提供了思路,設計應用時不必完全生搬硬套,也不一定每一條都得滿足,靈活運用即可,建議根據應用適合的場景進行裁剪和改良。

1.2.4 云原生與CNCF

2015年,Google牽頭創立了CNCF(Cloud Native Computing Foundation),同年,CNCF發布了其標志性作品——Kubernetes 1.0。由此,圍繞CNCF又產生了許多很有價值的云原生項目。CNCF 獨立維護了一個全景圖項目,該項目發布非常頻繁,截止到本書寫作時,其最新版本是0.9.9。大家可以在GitHub上查看相關內容。

如圖1-13所示,在CNCF全景圖中,云原生的生態圈在橫切面上被劃分為五層,同時在縱切面上又規劃出兩部分作為共用層。五層分別是應用定義與開發層、編排與治理層、運行時層、供應保障層和云設施層。另外兩部分是觀察與分析、平臺。將這些功能整合起來就是一個完善的云平臺服務產品。

圖1-13 CNCF全景圖

圖1-13中所含信息量巨大,無法看清細節,下面我們就層層遞進地來仔細解讀一下CNCF全景圖。首先來看看橫切面五層中每層涵蓋的內容。

應用定義與開發層

如圖1-14所示,應用定義與開發層中的內容對于有經驗的技術人員來說是比較熟悉的。無論是否要開發基于云原生的應用,這些內容都是開發和運維的基礎,與傳統開發模式并無二致。

圖1-14 應用定義與開發層

應用定義與開發層包括數據庫與數據分析、流式處理、軟件配置管理、應用定義以及持續集成/持續交付,下面分別來看。

1.數據庫與數據分析

圖1-15展示了CNCF應用定義與開發層中數據庫與數據分析部分的內容。

圖1-15 數據庫與數據分析

這部分主要包括數據庫與大數據分析工具,涉及關系型數據庫、NoSQL、NewSQL、數據庫中間層以及大數據處理方案。

基于SQL操作的關系型數據庫主要包括Oracle、SQL Server、MySQL、PostgreSQL、DB2、MariaDB等。雖然各種新型數據庫層出不窮,但關系型數據庫的存儲引擎畢竟經歷了數十年的打磨,又有經典的ACID事務模型作為支撐,因此它作為核心數據存儲選型的地位不可撼動。針對關鍵業務,大部分企業依然傾向于采用關系型數據庫進行存儲,如存儲交易數據、訂單信息等。數據庫本身的穩定性、SQL的查詢靈活度、開發工程師的熟悉程度以及數據庫管理員的專業度等,共同形成了關系型數據庫的強大生態圈,使得關系型數據庫始終是格式化數據存儲行業最優先的選擇。

作為關系型數據庫的有效補充,NoSQL數據庫在數據存儲領域也占據重要地位,常用的有MongoDB、Couchbase、Redis、Cassandra、HBase、Neo4j等。面向文檔、面向列簇、面向Key-Value、面向圖等的 NoSQL 數據庫在數據的分布式處理方面表現得更加優秀,編程模型也更加貼近面向對象原有的方式,雖然查詢的靈活度遠不如SQL,但在特定場景中的性能、對面向對象的原生存儲能力、無Schema模式等方面都做得很不錯,因此在適合的業務場景下,NoSQL數據庫也大有用武之地。比如,將Redis當作緩存,將Neo4j當作關系分析的數據庫,將MongoDB當作存儲Schema易變型數據的數據庫,這些都是很常見的使用方式。

NewSQL數據庫目前是新一代數據庫的焦點,是顛覆關系型數據庫統治地位的有力競爭者。它在兼容SQL的同時,更加擅長分布式處理。其中的優秀代表是PingCAP開源的TiDB。

TiDB采用Key-Value存儲引擎,采用不同于ACID的強一致分布式事務,可動態平滑地進行數據遷移,自動水平伸縮,也可以在線修改Schema,進行索引變更,是完整的數據存儲方案。但新的存儲引擎的成熟度畢竟還需要時間來檢驗,而且“無須專業數據庫管理員運維”的理念也需要時間來讓更多的企業接受。因此,愿意嘗試的公司仍然秉持“關系型數據庫和NewSQL數據庫共用”的較為謹慎的態度。隨著時間的沉淀,相信NewSQL的前景會越來越光明。

大數據處理方案用在離線或準實時的計算大數據的技術棧中,如Hadoop、Spark、Druid等。這里的 Druid 不是指阿里巴巴開源的數據庫連接池,而是一個用于大數據實時處理的分布式系統。

以Map/Reduce聞名的Hadoop體系,將計算任務抽象成Mapper和Reducer的編程模型,能夠通過分布式手段在由成百上千臺 PC 服務器組成的不完全可靠的集群中并發處理大量的數據集,并且將分布式和故障恢復等實現細節隱藏起來。它將數據處理過程分解為多個包含Mapper和Reducer的作業,將這些作業放入集群執行,并最終得出計算結果。但由于Map/Reduce任務將中間結果存入HDFS文件系統,因此延時較長,只適合高吞吐和大批量的數據處理場景,無法滿足交互式數據處理的需要。

以RDD(Resilient Distributed Dataset)作為計算模型的Spark,提供了一個供集群使用的分布式內存。在Spark中,RDD轉換操作后會生成新的RDD,而新的RDD數據仍然依賴于原來的RDD。因此,程序構造了一個由多個相互依賴的RDD組成的DAG(有向無環圖),并將其作為一個作業交由Spark執行。由于每次迭代的數據并不需要寫入磁盤,而可以保存在內存中,因此Spark的性能較Hadoop有很大提升。

2.流式處理

流式處理所包含的內容如圖1-16所示。

流式處理包括消息中間件以及流式實時計算框架。

消息中間件用于異步化和解耦系統依賴,如RabbitMQ和Kafka,未上榜的還有老牌消息中間件 ActiveMQ,以及國產的優秀消息中間件 RocketMQ 等。由于存儲引擎不同,ActiveMQ、RabbitMQ這種可以基于消息索引查詢的消息中間件,功能雖然完善,但分布式能力和性能不盡如人意。Kafka 以及早期的 RocketMQ 采用日志追加的存儲引擎,因此分布式能力和性能大幅提升,但自身對于消息的控制能力有限。新一代的 RocketMQ 以及阿里巴巴隨之孵化的OpenMessaging,正在努力平衡和兼容兩種流派的消息中間件。

圖1-16 流式處理

流式實時計算框架包括 Strom、Flink 等,相較于 Hadoop 這樣的離線計算體系,這類框架更加關注實時性。Storm與Flink都是將輸入流進行轉換和計算,并將結果作為輸出流傳輸至下一個計算節點的。對于實時統計PV、UV等需求,采用流式實時計算框架來實現是不錯的選擇。

3.軟件配置管理

軟件配置管理即SCM(Software Configuration Management),它通過執行版本控制來保證所有代碼和配置項變更的完整性和可跟蹤性。在源代碼版本控制工具領域,老牌的SVN已是明日黃花,將會逐漸退出歷史舞臺,取而代之的是Git,Git已是當前的行業標準。Git的出現使得源代碼版本控制工具升級為分布式工具,進而愈加受到青睞。

GitLab使用Git作為其源代碼版本控制工具,在管理源碼的同時可以提供便捷的Web服務,在成為代碼托管服務平臺的同時還可以通過安裝配置各種插件完成代碼評審、代碼質量檢查等工作。企業一般都使用GitLab來搭建自己的軟件配置管理系統。

對于個人開發者、開源項目負責人、企業付費用戶來說,推薦采用GitHub來管理源代碼,世界頂級公司大多將頂級開源項目源碼托管在GitHub上。

由開源中國搭建的碼云同樣采用 Git 作為其源代碼管理工具,它在國內的訪問速度優于GitHub,更加符合國人的使用習慣,也是非常優秀的源碼管理平臺。

4.應用定義

對于熟悉Java技術棧的工程師來說,圖1-14中可能沒有特別熟悉的產品。其實,Java中的Maven就屬于該范疇,它由于功能穩定、周邊生態多元化,因此成為業界的主流,也是Java用于編譯打包和依賴管理的首選。Maven使用項目對象模型(Project Object Model)聲明和管理項目的生命周期和應用依賴,并且可以自定義插件開發方式。大量的第三方插件使得Maven的應用場景被無限擴大,比如,代碼靜態檢查、代碼風格評審、測試覆蓋率計算等都會用到Maven。

5.持續集成/持續交付

持續集成是指自動且持續不斷地構建和測試軟件項目并監控其結果是否正確。有了持續集成工具的支持,項目可以頻繁地將代碼集成到主干位置,進而使得錯誤能夠快速被發現。它的目的是讓產品在快速迭代的同時還能保持高質量。持續集成并不能消除 Bug,但是它能讓 Bug被快速發現并且容易被改正。

持續交付是指頻繁地將應用的新迭代版本交付給測試團隊或最終用戶以供評審,如果評審通過,則自動部署至生產環境。持續交付的中心思想是,無論應用如何更新,它都可以隨時隨地交付并自動化部署。

常見的持續集成/持續交付工具有Jenkins、Bamboo、CircleCI、Travis等。

上面講到的軟件配置管理、應用定義、持續集成/持續交付三個部分的內容如圖1-17所示。

圖1-17 軟件配置管理、應用定義、持續集成/持續交付

應用定義與開發層的變動非常頻繁,之前CNCF將開發語言、開發框架等都納入這一層,但從0.9.6版本起,新的全景圖卻將這些內容全部刪除了。原因大概是 CNCF 認為這些內容屬于業務開發范疇,云原生無須關注。因此,無論選擇Java還是PHP進行開發,也不管使用Spring還是Play搭建架構,都可能開發出契合云原生的應用,也可能開發出不契合云原生的應用。

編排與治理層

將應用框架的分布式治理與云原生所需的調度、編排等功能抽象出來,形成獨立的一層,即編排與治理層,如圖1-18所示。這種劃分方式使業務開發工程師對云原生的了解更準確,云原生中間件工程師也無須過多關注業務。相對來說,CNCF 的產品更多地集中在這一層,這是云原生產品比較容易發力的部分。

圖1-18 編排與治理層

這一層包括調度與編排、分布式協調與服務發現、服務管理。下面我們具體來看一下每個部分涉及的內容。

1.調度與編排

調度與編排提供了面向應用的容器集群部署和管理功能,目的是解耦CPU、GPU、內存、網絡以及存儲等基礎設施與應用程序間的依賴,使開發人員將重點完全放在核心業務應用的研發上,而不必操心資源管理的問題,同時也使運維人員將重點放在硬件基礎設施以及操作系統和網絡本身的維護上,而不必操心資源利用率最大化的問題。調度與編排負責按照預定的策略將承載著應用的容器調度到擁有相應運行資源的執行服務器中。除了 CNCF 的核心成員Kubernetes,Mesos、Swarm也屬于此范疇。

雖然調度與編排同屬一部分,但它們負責的內容并不相同,調度是將分布式系統中的閑置資源合理分配給需要運行的進程并采用容器進行封裝的過程,編排則是對系統中的容器進行健康檢查、自動擴縮容、自動重啟、滾動發布等的過程。

Mesos采用兩級調度架構,因此能將調度和編排分離得比較徹底。由Mesos自身負責資源的調度,由運行在Mesos系統中的Marathon進行容器的編排。

調度與編排是云原生中最基礎的需求,其中包含的內容如圖1-19所示。

圖1-19 調度與編排

2.分布式協調與服務發現

分布式場景由于網絡的延遲以及不確定性,因此復雜度非常高。分布式系統一般都是通過一個可靠性非常高的注冊中心對分布式服務進行協調與發現的。注冊中心需要確保數據在分布式場景下的一致性,并且能夠將分布式集群的狀態變化及時通知給每個分布式節點。

在很多分布式系統中,我們都可以看到分布式協調和服務發現的身影,如Hadoop、Kafka、Dubbo中的ZooKeeper,Spring Cloud中的Eureka,Swarm中的Consul,其他常見的產品還有CNCF的項目CoreDNS,以及負責Kubernetes元數據存儲的etcd。雖然etcd并未在Kubernetes中扮演分布式協調和服務發現的角色,但它可以作為注冊中心提供這方面的能力。分布式協調與服務發現中包含的內容如圖1-20所示。

圖1-20 分布式協調與服務發現

3.服務管理

如同編排與調度是云原生的基礎需求一樣,服務管理是云原生的另一個重要基礎,也是CNCF的重點關注點之一。服務管理的產品主要集中在三個方面:遠程通信、反向代理、服務治理。

服務間的遠程通信需要依托高性能和跨語言的通信框架,gRPC、Thrift、Avro 等跨語言框架集序列化和通信功能于一身,是分布式系統的重要基石。

關于反向代理的產品目前已經非常成熟,有涉及硬件的 F5,涉及軟件的 HAProxy、Nginx等。它們負責承載入口流量,并將請求按照規則配置分發給相關的系統。

在服務治理方面,也已經有很多成熟的框架可以使用,如Netfix OSS負責網關的Zuul、負責客戶端負載均衡的Ribbon、負責熔斷的Hystrix等,它們也是Spring Cloud開發套件中的重要組成部分。由Twitter開源的用Scala語言開發的Finagle,以及國內非常流行的Dubbo,也屬于此范疇。

在服務治理方面,業界新興的Service Mesh概念正在漸漸被更多人認同,它的中文翻譯為服務網格。Linkerd 和 Istio 是這方面的代表,由于技術實在太新,目前還處于快速發展時期。其中Linkerd和Istio的通信底層組件Envoy都已加入CNCF。Istio是與英文sail對應的希臘文單詞,中文則是“航行”的意思,它與Kubernetes一脈相承,Kubernetes同為希臘文,是“舵手”的意思。除了Envoy,Linkerd也實現了Istio的接口并提供了底層通信能力。因此,Kubernetes掌控編排,Istio掌控服務治理,云原生的未來秩序已逐漸清晰。

值得一提的是,Kubernetes也內置了服務管理的功能,它們并未從Kubernetes的核心中抽離出來。Kubernetes使用Service和Ingress處理服務發現和負載均衡。未來的Service Mesh是否能夠從Kubernetes中將服務治理完全接管過來,這將是一個值得關注的重點。

服務管理中包含的內容如圖1-21所示。

圖1-21 服務管理

運行時層

云原生的應用并不直接運行在物理服務器或傳統的虛擬機之上,通常為了運行云原生應用,會在物理服務器或傳統的虛擬機之上再構建一層,用于輕量和靈活地運行更多的實例。

云原生應用的運行時環境與傳統應用的運行時環境有很大不同,但是它們的抽象層級是類似的,與傳統應用的文件系統、進程以及網絡環境相對應的是云原生存儲、容器和云原生網絡。運行時層包含的內容如圖1-22所示,下面我們具體來看一下每個部分涉及的內容。

圖1-22 運行時層

1.云原生存儲

云原生存儲是指適合云服務的分布式文件存儲系統,它能將運行在云平臺上的應用所需的或產生的數據放入一個可以不依賴本地磁盤且可以平滑擴容的高可靠文件系統,典型的產品有HDFS、Ceph、ClusterFS等。

云原生存儲與專門用于存儲業務數據的數據庫并不是一個概念,目前很少有將數據庫安裝在云原生存儲上的成熟方案。云原生存儲目前最廣泛的應用途徑是存放日志、圖片、文檔等文件。云原生存儲中包含的內容如圖1-23所示。

圖1-23 云原生存儲

2.容器

容器是過去幾年的熱門話題。云原生應用選擇容器這種更加輕量級的方案作為運行應用的載體,將容器作為最小單元對應用進行資源隔離以保證云平臺的隔離性,并且通過容器打包環境和應用來提供更易復制的部署方式。不過需要注意的是,Kubernetes采用Pod作為應用的最小單元,一個Pod內可以包含多個容器。Docker是目前使用最廣泛的容器,業界也有rkt等替代方案。關于容器,其中包含的內容如圖1-24所示。

圖1-24 容器

3.云原生網絡

云原生網絡可以解決為每個容器(或Pod)分配獨立IP地址的問題。若采用和宿主機一樣的IP地址,運行在同一個宿主機中的容器IP地址則會發生沖突。雖然可以通過改造應用程序來屏蔽對IP地址的依賴,但為了使應用透明化,令每個容器都擁有一個獨立的IP地址才是上策。為了實現這一點,使用軟件定義網絡(SDN)是最佳方案。

云原生網絡比較復雜,各種網絡方案也層出不窮,因此產生了 CNI(Container Network Interface)這樣的容器網絡接口標準,它的主要實現有Flannel、Calico、OVS、weave等。云原生網絡包含的如容見圖1-25所示。

圖1-25 云原生網絡

供應保障層

供應保障層包括宿主機管理工具、基礎設施自動化工具、容器倉庫、鏡像安全和密鑰管理,如圖1-26所示,這一層用于為宿主機和容器本身提供保障,它的關注點更加偏向于運維。下面我們來具體看一下其中的每個部分。

圖1-26 供應保障層

1.宿主機管理工具

雖然云原生應用運行在一個相互隔離的由調度系統掌控的容器環境中,但它們最終仍然是運行在真正的物理服務器或虛擬機之上的。因此,我們需要通過管理工具將Docker、Kubernetes、Mesos、etcd、ZooKeeper、Flannel等眾多運行時所需環境和工具自動安裝和配置在應用運行的宿主機上。

原有的自動化運維工具在這里仍然有用武之地,它們無須再安裝復雜的軟件應用環境,只搭建容器運行環境和編排調度平臺即可,這類工具包括Ansible、Puppet、Chef等。自動化運維工具的目標不再是安裝應用及其相關環境,而是安裝云原生應用所需的環境。

2.基礎設施自動化工具

對于云原生的系統來說,調度編排平臺即基礎設施。基礎設施自動化工具的用途是為調度編排平臺安裝插件。常見的相關工具有Docker的包管理工具Infrakit,以及簡化Kubernetes應用的部署工具Helm。Helm可以看作Kubernetes的apt-get或yum,它通過Helm Charts幫助使用者安裝和更新復雜的 Kubernetes 應用,支持版本管理和控制,這在很大程度上降低了Kubernetes應用部署和管理的復雜性。

宿主機管理工具與基礎設施自動化工具有類似之處,都屬于系統軟件安裝的范疇,它們包含的內容如圖1-27所示。

圖1-27 宿主機管理工具和基礎設施自動化工具

3.容器倉庫

容器倉庫負責容器鏡像內容的存儲與分發。Docker Registry是Docker 的核心組件之一,客戶端的 docker pull 以及docker push 命令都與它交互。Harbor是一個比較知名的項目,它的目標是幫助用戶迅速搭建一個企業級的Docker Registry服務。

4.鏡像安全

安全漏洞一直存在于程序世界。升級為容器之后,此類安全威脅仍然存在,因此我們需要一個能夠發現容器中可能存在的安全問題的工具,如Clair、Twistlock等工具均可以檢查容器中應用的漏洞。

供應保障層中還包含一個密鑰管理的部分,是新加入CNCF的部分,筆者并不是很熟悉,因此不做詳細介紹。以上三個部分的內容如圖1-28所示。

圖1-28 容器倉庫、鏡像安全、密鑰管理

云設施層

云設施層主要包括用于提供物理服務器的云廠商,如圖1-29所示。

按照公有云和私有云來分,常見的公有云有 AWS、Azure、阿里云、騰訊云、華為云等,常見的私有云有OpenStack、VMware等。嚴格來講,這一層其實并不在CNCF的范疇內,它們僅用于提供服務所需的資源。

圖1-29 云設施層

下面再介紹一下另一個維度下的云原生應用。觀察與分析是每一層都需要的功能,平臺則是將每一層功能組合起來的整體解決方案。

觀察與分析

觀察與分析包括對系統指標的監控,對鏈路調用的追蹤,以及對分布式日志的收集。除了收集相關數據,還能夠通過對這些數據進行解讀,將系統當前狀態以易懂的可視化圖形形式展現出來,以便運維工程師掌控整個系統。

1.監控

監控部分包括以下內容:對物理服務器指標進行采集與報警的工具,如Nagios、Zabbix等;對容器指標進行采集的工具,如 CAdvisor 等;存儲海量采集信息的時間序列數據庫,如Prometheus、InfluxDB等。監控部分的具體內容如圖1-30所示。

監控往往通過“采集、存儲、分析、報警(展現)”的流程自動將系統狀態通知給系統責任人,令其處理或定期分析。一般可以采用Grafana等專門用于監控分析的圖形工具來展示數據。

2.日志

由于云原生應用是無狀態的,因此不應該將日志寫入本地磁盤,而是應該寫入日志中心。用于采集標準輸出并將日志輸入其他流的工具主要有Fluentd、Flume、FileBeat、Logstash等,然后這些工具會將日志通過各種緩沖的管道進行處理,寫入日志中心,日志中心的存儲介質可以是Elasticsearch、HBase等。Elastic公司提供的由搜索引擎Elasticsearch、日志收集工具Logstash和圖形界面Kibana所組成的日志中心套件(簡稱ELK)是一站式的開源解決方案,也有如Splunk這樣的一體化商業日志解決方案。

圖1-30 監控

3.追蹤

云原生應用運行實例多,應用調用復雜,因此一旦系統響應變慢,便會難以定位問題。因此需要提供一套梳理和分析服務之間調用鏈以及服務內部調用棧的解決方案。OpenTracing是調用鏈的一個標準協議,遵循該協議的開源解決方案主要有 ZipKin、JAEGER,以及國產的優秀開源項目SkyWalking等。也有一些開源解決方案并未遵循此協議,如PinPoint、Open-Falcon、CAT等。

日志與追蹤兩部分中包含的內容如圖1-31所示。

圖1-31 日志和追蹤

平臺

基于云的整合平臺是目前各個云公司都著力打造的產品,比較知名的有Mesosphere公司圍繞Mesos打造的DC/OS,以及Rancher公司打造的可以整合Mesos和Kubernetes的Rancher平臺等。

上面提到的技術只是整個云原生技術的冰山一角,無論是開源產品還是商業產品,優秀的解決方案非常多。云原生可以有不同的實現方式,但它的本質在于彈性地利用云平臺的資源。無論是通過“應用程序 + 分布式中間件 + 自動化運維”的方式,還是通過“應用程序 + 調度編排平臺 + 容器 + 服務治理”的方式,都可以實現健壯的系統。

主站蜘蛛池模板: 旬邑县| 浑源县| 鞍山市| 图片| 上虞市| 南平市| 石首市| 隆回县| 濮阳县| 柳河县| 西峡县| 广安市| 汉源县| 郯城县| 铜陵市| 抚顺市| 山丹县| 宜都市| 昆山市| 新巴尔虎左旗| 稻城县| 宝鸡市| 巴里| 博乐市| 广灵县| 大关县| 松阳县| 左贡县| 辉县市| 中西区| 浙江省| 临西县| 上高县| 云浮市| 吉木萨尔县| 三门县| 麻城市| 威信县| 军事| 濮阳市| 昌图县|