新一代的微服務架構 Service Mesh 博客原文地址 (https://elfgzp.cn/2020/06/21/新一代的微服務架構 Service Mesh 由於最近在工作中在做 Service Mesh 的落地項目,有非常多的感觸,所以想寫一篇文章來分享這個「新一代的微服務架構 Servi ...
新一代的微服務架構 Service Mesh
博客原文地址 (https://elfgzp.cn/2020/06/21/新一代的微服務架構 Service Mesh
由於最近在工作中在做 Service Mesh
的落地項目,有非常多的感觸,所以想寫一篇文章來分享這個「新一代的微服務架構 Service Mesh
」。
筆者會從以下順序開始分享:
- Part 1 從「單體應用架構」到「微服務架構」開始說起
- Part 2 從「Docker」到 「K8s」
- Part 3 從「邊車模式」到「服務網格」
- Part 4 用「Istio Demo」來講一個實際的應用場景
首先會從 「單體應用架構」 演進到 「微服務架構」 產生的問題開始說起,到自己作為開發人員感觸最深的痛點。
然後簡單介紹以下今天的主角 Istio
的服務編排環境 Kubernetes
。
最後從 Sidecar
這種設計,說到 Service Mesh
,最後到我們的主角 Istio
。
到正式的主角之前的鋪墊會比較多,這是為了讓大多數開發者都能理解。
本文大部分內容都整理自筆者的學習資料加上自己的一些總結和體會,大家最後可以從文末找到他們。
Part 1「單體應用架構」到「微服務架構」開始說起
1.1 單體應用架構與微服務架構對比
從「單體」到「分散式」演進(也就是微服務化)的原因我相信大家都很瞭解了。
因為業務量越來越大,我們需要多台機器才能應對大規模的應用,所以需要垂直或者水平拆分業務系統,讓其變成一個分散式的架構。
從上面的表格我們可以看到,分散式系統雖然有一些優勢,但也存在一些問題。
- 架構設計變得複雜。
- 部署單個服務會比較快,但是如果一次部署需要多個服務,流程會變得複雜。
- 系統的吞吐量會變大,但是響應時間會變長。
- 運維複雜度會因為服務變多而變得很複雜。
- 架構複雜導致學習曲線變大。
- 測試和查錯的複雜度增大。
- 技術多元化,公司中可能會有多個技術棧,這會帶來維護和運維的複雜度。
- 管理分散式系統中的服務和調度變得困難和複雜。
作為業務開發人員最直觀的感受:
- 介面為什麼這麼慢,明明只依賴了一個服務。我需要更新我的服務,但是哪些服務依賴了我的服務,這次更新會對哪些服務造成影響。
- 我需要在代碼框架層編寫客戶端接入監控、日誌、鏈路追蹤、告警、健康檢查等各種各樣非業務相關的代碼。
- 測試很不方便,測試一個服務需要所有依賴的服務,測試環境資源緊張。
- ...
1.2 微服務架構的痛點和需要解決的問題
總結來說,微服務架構有這些痛點和需要解決的問題:
- 服務多,服務之間的依賴難以管理。
- 服務之間的版本管理,不同版本的服務可能會有相容性的問題。
- 需要對整體架構監控,快速發現問題。
- 資源調度管理。
- 需要做流量控制。負載均衡、服務路由、熔斷、降級、限流、灰度發佈等流量相關的控制。
圖片引用自 《左耳聽風 - 分散式系統技術棧》
針對這麼多的需要去解決和處理的問題。
引出了我們今天的主角 Istio
。
在介紹我們今天的主角 Istio
之前,先簡單介紹一下它的服務編排環境 Kubernetes
。通過 Docker
以及其衍生出來的 Kubernetes
之類的軟體或解決方案,大大地降低了做上面很多事情的門檻。
Part 2「Docker」到 「K8s」
2.1 Docker 容器的本質
Docker
相信大家都非常瞭解了,所以這裡我就從 Docker
過度講到 k8s
。
Docker
容器這個聽起來玄而又玄的概念,實際上是在創建容器進程時,指定了這個進程所需要啟用的一組 Namespace
參數。這樣,容器就只能“看”到當前 Namespace
所限定的資源、文件、設備、狀態,或者配置。而對於宿主機以及其他不相關的程式,它就完全看不到了。
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
我們知道,在 Linux
系統中創建線程的系統調用是 clone()
,就像這樣。而當我們用 clone()
系統調用創建一個新進程時,就可以在參數中指定 CLONE_NEWPID
參數。這時,新創建的這個進程將會“看到”一個全新的進程空間,在這個進程空間里,它的 PID
是 1。之所以說“看到”,是因為這隻是一個“障眼法”,在宿主機真實的進程空間里,這個進程的 PID
還是真實的數值,比如 100。
所以說,容器,其實是一種特殊的進程而已。
感興趣的同學可以閱讀 《自己動手寫 Docker》 和嘗試一下書中的代碼。
2.2 K8s 最小調度單位 Pod
我花了很多精力去學習 Linux
容器的原理、理解了 Docker
容器的本質,終於, Namespace
做隔離, Cgroups
做限制, rootfs
做文件系統” 這樣的“三句箴言”可以朗朗上口了。
為什麼 Kubernetes
又突然搞出一個 Pod
來呢?
這裡提一個概念: Pod
, 是 Kubernetes
項目中最小的 API
對象。如果換一個更專業的說法,我們可以這樣描述: Pod
是 Kubernetes
項目的原子調度單位。
這裡通過一個實際的例子來說明:
我們通過 pstree
查看操作系統中運行的進程,進程並不是“孤苦伶仃”地獨自運行的,而是以進程組的方式,“有原則地”組織在一起。
比如,這裡有一個叫作 rsyslogd
的程式,它負責的是 Linux
操作系統里的日誌處理。可以看到, rsyslogd
的主程式 main
, 和它要用到的內核日誌模塊 imklog
等,同屬於 1632
進程組。這些進程相互協作,共同完成 rsyslogd
程式的職責。
如果說 「Docker 容器」的其實就是一個「特殊的進程」。
那麼「K8s」就可以理解成操作系統。
Kubernetes
所做的,其實就是將 “進程組” 的概念映射到了容器技術中,並使其成為了這個雲計算 “操作系統” 里的 “原子調度單位”。
不過,相信此時你可能會有第二個疑問:
對於初學者來說,一般都是先學會了用 Docker
這種單容器的工具,才會開始接觸 Pod
。而如果 Pod 的設計只是出於調度上的考慮,那麼 Kubernetes
項目似乎完全沒有必要非得把 Pod
作為“原子調度單位”吧?
首先,關於 Pod
最重要的一個事實是:它只是一個邏輯概念。
具體的說: Pod
里的所有容器,共用的是同一個 Network Namespace
,並且可以聲明共用同一個 Volume
。
那這麼來看的話,一個有 A
和 B
兩個容器的 Pod
,不就是等同於一個容器(容器 A
)共用另外一個容器(容器 B
)的網路和 Volume
?這好像通過 docker run --net --volumes-from
這樣的命令就能實現,就像這樣。
但是,你有沒有考慮過,如果真這樣做的話,容器 B
就必須比容器 A
先啟動,這樣一個 Pod
里的多個容器就不是對等關係,而是拓撲關係了。
所以,在 Kubernetes
項目里, Pod
的實現需要使用一個中間容器,在這個 Pod
中,中間容器永遠都是第一個被創建的容器,而其他用戶定義的容器,則通過 Join Network Namespace
的方式,與 中間容器關聯在一起。
如上圖所示,這個 Pod
里有兩個用戶容器 A
和 B
,還有一個中間容器容器。很容易理解,在 Kubernetes
項目里,中間容器一定要占用極少的資源,所以它使用的是一個非常特殊的鏡像,叫作: k8s.gcr.io/pause
。這個鏡像是一個用彙編語言編寫的、永遠處於“暫停”狀態的容器,解壓後的大小也只有 100~200 KB
左右。
這裡就不再深入說明瞭,感興趣的可以點擊圖片鏈接,或者在文章末尾我列出的參考資料。
其中 Pod
的一個重要的特性,它的所有容器都共用同一個 Network Namespace。這就使得很多與 Pod
網路相關的配置和管理,也都可以交給 Sidecar
完成,而完全無須干涉用戶容器。
這裡最典型的例子莫過於 Istio
這個微服務治理項目了。
接下來就從 Sidecar
到 Service Mesh
來一步一步介紹 Istio 的設計思想。這裡提到的 Sidecar
到底是什麼呢, Sidecar
在國內翻譯為邊車模式,這個翻譯真的很形象。
Part 3「邊車模式」到「服務網格」
3.1 邊車模式
所謂的邊車模式,對應於我們生活中熟知的邊三輪摩托車。
圖片引用自 《左耳聽風 - 管理設計篇“邊車模式”》
我們可以通過給一個摩托車加上一個邊車的方式來擴展現有的服務和功能。這樣可以很容易地做到 "控制 " 和 "邏輯" 的分離。
也就是說,我們不需要在服務中實現控制面上的東西,如監視、日誌記錄、限流、熔斷、服務註冊、協議適配轉換等這些屬於控制面上的東西,而只需要專註地做好和業務邏輯相關的代碼,然後,由“邊車”來實現這些與業務邏輯沒有關係的控制功能。
圖片引用自 《左耳聽風 - 管理設計篇“邊車模式”》
那最終這個 Sidecar
的效果就會像上圖所示。
那麼在 Istio
中, [Envoy](https://github.com/envoyproxy/envoy)
就是預設的 Sidecar
。它與服務容器在同一個 Pod
中,與服務容器共用同一個 Network Namespace
,接管所有經過服務容器的流量。
3.2 服務網格
然後, Sidecar
集群就成了 Service Mesh
。圖中的綠色模塊是真實的業務應用服務,藍色模塊則是 Sidecar
, 其組成了一個網格。而我們的應用服務完全獨立自包含,只需要和本機的 Sidecar
依賴,剩下的事全交給了 Sidecar
。
圖片引用自 《左耳聽風 - 管理設計篇之“服務網格”》
Service Mesh
這個服務網路專註於處理服務和服務間的通訊。其主要負責構造一個穩定可靠的服務通訊的基礎設施,並讓整個架構更為的先進和 Cloud Native
。在工程中, Service Mesh
基本來說是一組輕量級的服務代理和應用邏輯的服務在一起,並且對於應用服務是透明的。
說白了,就是下麵幾個特點。
Service Mesh
是一個基礎設施。Service Mesh
是一個輕量的服務通訊的網路代理。Service Mesh
對於應用服務來說是透明無侵入的。Service Mesh
用於解耦和分離分散式系統架構中控制層面上的東西。
3.3 Istio 與 Service Mesh
我們今天的主角 Istio
,它的偉大之處不只是在設計本身,而是在於它是一個相容並包的生態。它為整個行業提供了一種全新的開發及運維的方式。
微服務架構在網路鏈路上還有很多待解決的點,如鏈路跟蹤、分散式日誌、監控報警、壓測演練、故障註入等。若讓 Istio
官方來實現所有的功能,不僅耗時,還會讓整個系統變得非常臃腫。
接下來就用 Istio
的官方 Demo
來講一個實際的應用場景。
Part 4 用「Istio Demo」來講一個實際的應用場景
這部分會用 Istio 官方的 Demo 來演示,所以本文的大部分內容都可以在官方文檔中找到。
如果有感興趣的同學可以跟著這個 Demo
來實踐,但是可能需要一個 K8s
集群,這裡推薦使用 Google Cloud Platform 的免費試用服務 GCP Free Tier - Free Extended Trials and Always Free。
當然如果想自己折騰搭建 K8s
集群的同學可以參考筆者的這篇文章 「K8s 學習日記」Kubeadm 部署 kubernetes 集群。
但是筆者還是建議使用谷歌的服務,體驗雲原生的方式。
4.1 Istio Demo「Bookinfo 應用」服務架構
Bookinfo
應用分為四個單獨的微服務:
productpage
. 這個微服務會調用details
和reviews
兩個微服務,用來生成頁面。details
. 這個微服務中包含了書籍的信息。reviews
. 這個微服務中包含了書籍相關的評論。它還會調用ratings
微服務。ratings
. 這個微服務中包含了由書籍評價組成的評級信息。
reviews
微服務有 3 個版本:
- v1 版本不會調用
ratings
服務。 - v2 版本會調用
ratings
服務,並使用 1 到 5 個黑色星形圖標來顯示評分信息。 - v3 版本會調用
ratings
服務,並使用 1 到 5 個紅色星形圖標來顯示評分信息。
下圖展示了這個應用的端到端架構。
對 Reviews-v2、Reviews-v3 服務進行測試
在實際的應用場景中,我們當前發佈了兩個 Reviews
服務的 feature
版本 v2
和 v3
版本。但是如果需要對這些服務進行測試。
為了開發人員在測試自己開發的 Review
服務不受影響,我們可能需要部署多個完整的 Bookinfo 應用
即 Product page
、 Ratings
、 Details
的服務都需要部署,如下圖所示 。
官方的 BookInfo
中的微服務數量還是比較少的,在實際的場景中,一個完整的系統可能會有成百上千個微服務共同支撐和運行,如果為了開發測試方便就需要龐大的伺服器資源提供給微服務進行部署,這也是目前筆者公司的一個痛點。
利用 Istio 對流量進行控制
在官方的 demo
中,有這樣一個例子。
將來自名為 Jason
的用戶的所有流量路由到服務 reviews:v2
。將請求頭中 end-user
值為 jason
的所有請求指向 reviews:v2
。
正常來說,這樣的功能應該需要在具體語言的 Web
框架層進行實現,但是由於 Istio
的 Sidecar
接管了所有的流量,這個功能就在 Istio
中已經集成了。
對於開發人員來時也就是簡單的一個配置和一行命令:
$ kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
$ kubectl get virtualservice reviews -o yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
...
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
當 Istio
的流量控制放到實際的應用場景中時,測試環境就只需要一套完整的服務,和一些需要測試的不同版本的服務了。
當然這隻是其中一個應用場景,流量控制還可以用於 A/B
測試,灰度發佈等。並且這隻是 Istio
的其中一個功能。
筆者也不一一去介紹 Istio
的其他功能了,如:服務安全、鏈路追蹤、網路拓撲、服務註冊等等服務治理相關的功能,感興趣的同學可以閱讀官方文檔。
除了官方給出的 demo
, 感興趣的同學還可以在這個網站上找到更多的例子,https://istiobyexample.dev/ 。
結尾
以上就是筆者想分享的全部內容,在這個雲計算時代,筆者相信 Service Mesh
將會成為微服務架構中的一個佼佼者,幫助我們更好治理微服務架構。
參考文獻
- 《左耳聽風》陳皓
- 《深入剖析Kubernetes》張磊
- 《Kubernetes 權威指南:從 Docker 到 Kubernetest 實踐全接觸(第 4 版)》
- 《Service Mesh 實戰:用 Istio 軟負載實現服務網格》
本文由博客一文多發平臺 OpenWrite 發佈!