Kubernetes上分佈式系統的演化

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"現代分佈式應用"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我想爲這次演講預先設置一些背景,在這裏當我提到分佈式系統時,我所指的是由多個組件組成的系統,可能會有數百個這樣的組件。這些組件可能是有狀態的、無狀態的或者是無服務器的。除此之外,這些組件可以使用不同的語言創建,運行在混合環境之中,開發時使用的是開源技術和開發標準,支持互操作性。我相信你也可以使用閉源的軟件創造這樣的系統,或者在AWS和其他的地方創建它們。具體到這次演講,我會特別關注Kubernetes生態系統,以及如何在Kubernetes平臺上創建這樣的系統。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們從分佈式系統的需求開始。我所想的是我們想要創建一個應用或者服務,並編寫一些業務邏輯。那麼,我們需要從平臺和運行時環境得到哪些支撐以構建分佈式系統呢?從基礎來講,最初的需求是我們需要一些生命週期管理的能力。當我們使用任意語言編寫應用的時候,我們希望能夠穩定地打包和部署應用,進行回滾和健康檢查。並且能夠將應用放到不同的節點上,進行資源隔離、擴展、配置管理,以及所有類似這樣的事情。這些都是我們創建分佈式應用所需要的最基本的東西。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/55image001-1616431697020.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二個基石是網絡相關的。我們有了一個應用之後,就希望它能夠可靠地連接到其他的服務上,不管其他的服務在集羣內還是在集羣外部。我們希望能有諸如服務發現、負載均衡等能力,我們還希望能夠進行流量轉移,不管是基於不同的發佈策略還是其他的一些原因。在此之後,我們希望能夠與其他的系統進行彈性通信,不管是通過重試、超時、斷路器還是其他方式來實現。當然,還要有安全保障,要有足夠的監控、跟蹤、可觀察性等等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/25image002-1616431698392.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有了網絡之後,下一件事就是我們希望能夠與不同的API和端點進行對話,也就是資源綁定:與其他協議和不同的數據格式進行對話。甚至可能從一種數據格式轉換成另外一種數據格式。在這裏我還想要包括像輕量級過濾(light filtering)這樣的事情,也就是當訂閱一個主題的時候,我們可能只關心特定的事件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/45image003-1616431697873.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"你認爲最後一類會是什麼呢?它就是狀態。當我提到狀態和狀態化抽象的時候,我討論的不是實際的狀態管理,比如數據庫或文件系統所做的事情。我更多的是討論開發人員對那些幕後依賴狀態的功能的抽象。也許,你需要進行工作流管理。可能你想要管理長時間運行的進程,或者要進行時間調度,或者要實現一些cron job來定期運行服務。也許,你想要實現分佈式緩存、保證冪等性或者能夠回滾。所有的這些都是開發人員層面的原語(primitive),但是在幕後,它們依賴於一些狀態。我們希望能擁有這些抽象來創建健壯的分佈式系統。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/26image004-1616431697348.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們將會使用這個分佈式系統原語的框架來評估在Kubernetes和其他項目上這些內容的變化。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"單體架構:傳統中間件的能力"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"假設我們從單體架構開始,考慮如何獲取這些能力。在這種情況下,當我提到單體的時候,在分佈式應用這個上下文中,我想到的是ESB。ESB的功能是非常強大的,當檢查我們的需求列表時,我會說ESB對所有有狀態的抽象都有很好的支持。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"藉助ESB,我們可以實現長期運行的進程的編排、實現分佈式事務、回滾和冪等性。此外,ESB還提供了出色的資源綁定的能力,它們具備上百個連接器,支持轉換、編排,甚至網絡方面的能力。最後,ESB甚至可以實現服務發現和負載均衡。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它具備網絡連接可靠性方面所有的功能,所以它能夠實現重試。可能從本質來講,ESB並不是分佈式的,所以它不需要非常高級的網絡和發佈功能。ESB缺乏的主要是生命週期管理。因爲它是一個單運行時,第一個問題就是你會被限制使用單一的語言。這通常對應真正的運行時在構建中所使用的語言,比如Java或.NET等。然後,因爲它是一個單運行時,我們無法很容易地進行聲明式部署或自動放置(automatic placement)。部署是非常龐大和重量級的,所以通常會涉及到人工的交互。而這樣一個單體架構所帶來的另外一個困難就是擴展性。“我們無法擴展單個組件。”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後同樣重要的是,關於隔離,不管是資源隔離還是故障隔離,在單體架構下都是無法實現的。從我們所需的框架來看,ESB單體架構並不合格。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/40image005-1616431696438.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"雲原生架構:微服務和Kubernetes"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來,我建議我們看一下雲原生架構以及這些需求是如何變化的。如果我們從一個比較高的層面來看這些架構的變化的話,就會發現雲原生可能是從微服務運動開始的。微服務允許我們將一個單體應用按照業務域進行拆分。實踐證明,容器和Kubernetes實際上是管理這些微服務的絕佳平臺。接下來,我們看一下Kubernetes有哪些具體的特性和能力,使其成爲微服務領域特別有吸引力的方案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/13image006-1616431699209.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最初,能夠進行健康探測是Kubernetes流行起來的原因。在實踐中,這意味着當我們在一個pod中部署容器的時候,Kubernetes將會檢查進程的健康狀況。通常情況下,這樣的進程模型是不夠好的。我們仍然可能會有一個正在運行的進程,但它的狀態並不健康。這就是爲何還需要使用就緒狀態(readiness)和活躍狀態(liveness)檢查的原因。在啓動的時候,Kubernetes將會進行就緒檢查來確定應用程序何時能夠開始接受流量。它還會進行活躍性檢查,以持續檢查應用的健康狀況。在Kubernetes之前,這種方式並不流行,但是如今幾乎所有的語言、框架和運行時環境都有健康檢查的功能,通過一個端點可以快速實現。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/29image007-1616431696697.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kubernetes引入的另外一件事情就是應用程序的生命週期管理,在這裏我的意思是,你不用再去控制服務何時啓動以及何時關閉了。我們可以相信平臺能夠幫我們做到這一點。Kubernetes能夠啓動應用,能夠關掉應用,也能將其在不同的節點間進行轉移。要實現這一點,我們就必須正確地實現平臺在啓動和關閉時告訴我們的事件。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Kubernetes使之流行起來的另外一件事情就是部署以及以聲明式的方式進行部署。這意味着,我們不必再去自己啓動服務並根據日誌判斷它是否已經啓動完畢。我們也不必再去手動升級實例,Kubernetes的聲明式部署就可以幫我們做到這一點。根據你所選擇的策略,它能夠停掉舊的實例並啓動新的實例。除此之外,如果出現問題的話,它還能夠回滾。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"另外一件事情就是聲明所需的資源。當創建服務的時候,我們會將其容器化。有一項好的實踐是告訴平臺該服務需要多少CPU和內存。Kubernetes會利用這些信息爲我們的工作負載找到最合適的節點。在Kubernetes出現之前,我們必須根據自己的標準手動將實例放到節點中。現在,我們可以根據自己的偏好設置指導Kubernetes,它將會爲我們做出最佳的決策。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如今,在Kubernetes上,我們可以支持多種方式的配置管理。我們的應用程序運行時不需要進行任何的配置查找。Kubernetes會確保配置內容將會最終出現在工作負載所在的節點上。配置被會映射爲一個卷或者環境變量,供應用程序使用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實際上,我剛纔提到的這些具體的能力也是互相關聯的。例如,如果你希望實現服務的自動放置,那麼就需要將服務的資源需求告訴Kubernetes。然後,你需要告訴它使用什麼樣的部署策略。爲了讓該策略能夠正常運行,應用程序必須要實現來自環境的事件。它必須要實現健康檢查。一旦我們將所有的最佳實踐準備就緒並使用好這些能力,那麼我們的應用就會成爲一個優秀的雲原生公民,它就可以在Kubernetes上實現自動化(這代表了在Kubernetes上運行工作負載的基礎模式)。最後,關於在pod中如何組織容器、配置管理和行爲等方面還有其他的模式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我想簡要討論的下一個話題是關於工作負載的。從生命週期的角度來看,我們希望能夠運行不同的工作負載。我們在Kubernetes上也可以做到這一點。運行十二要素應用(Twelve-Factor App)和無狀態微服務是非常簡單的。Kubernetes可以做到這一點。但這並不是唯一的工作負載類型。也許你還會有有狀態的工作負載,在Kubernetes上我們可以通過stateful set實現它。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們想要運行的另外一種工作負載可能是單例應用。我們想要在整個集羣中運行該應用的唯一一個實例,我們希望它是一個可靠的單例應用。當它出現故障時,應該會再次重新啓動。因此,你可以根據需要,以及這個應用應該最少要有一個實例還是最多有一個實例的語義,在stateful set和replica set之間做出選擇。還有一種工作負載就是job和cron job,藉助Kubernetes,它們也是可以實現的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們將Kubernetes所有的這些特性映射到我們的需求上,那麼可以說Kubernetes滿足了生命週期的要求。通常情況下,我所創建的需求列表的內容是由Kubernetes迄今爲我們提供的功能所驅動的。這是所有平臺的預期能力,Kubernetes能夠爲部署所提供的特性包括配置管理、資源隔離以及故障隔離。除此之外,它還支持不同的工作負載,不過無服務器本身除外。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/12image008-1616431698134.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這就是Kubernetes爲開發人員提供的所有功能,那麼我們該如何擴展Kubernetes?如何讓它爲我們提供更多的特性呢?因此,我想要描述我們目前常用的兩種方式。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"進程外的擴展機制"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先要提及的就是pod的概念,它是一種用來在節點上部署容器的抽象機制,pod能夠爲我們保證如下兩點:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一個就是部署方面的保證:pod中的所有容器最終將會位於相同的節點上。這意味着它們彼此之間可以使用localhost、基於文件系統的異步方式或者其他IPC機制進行通信。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"pod給我們的另外一個保證是關於生命週期的,pod中所有的容器並不是平等的。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/22image009-1616431698660.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"根據使用的是init容器還是應用容器,你會得到不同的保證。例如,init是在開始時運行的,當pod啓動的時候,它們會一個接一個地按順序執行。只有當前面的容器成功完成後,後面的容器纔會運行。它們有助於實現由容器驅動的類似工作流的邏輯。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而應用容器則是並行運行的。它們會在pod的整個生命週期中運行,這是sidecar模式的基礎。sidecar可以運行多個容器,它們相互協作,共同爲用戶提供價值。這就是我們目前能夠看到的擴展Kubernetes以獲取額外能力的主要機制。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/9image010-1616431695489.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了闡述下面的能力,我必須要簡單介紹一下Kubernetes內部的運行方式。它是基於一種叫做調諧循環(reconciliation loop)的機制實現的。調諧循環的理念就是將期望狀態驅動到實際狀態。在Kubernetes中,有很多功能都是基於這種機制實現的。例如,當我想要兩個pod實例的時候,這就是系統的期望狀態。Kubernetes會有一個持續運行的控制循環,它會檢查是否有兩個pod的實例在運行。如果實際運行的實例數量不是兩個的話,它會計算差異,看實例的數量是隻有一個還是超過了兩個。它會確保最終有兩個實例。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這方面的例子還有很多,有些是關於replica set或stateful set的。資源定義會映射到具體的控制器,每種資源定義都會有一個控制器。控制器能夠確保現實狀況會匹配期望,你甚至可以編寫自定義的控制器。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當在pod中運行應用的時候,我們無法在運行時加載配置文件的變化。但是,我們可以編寫自定義的控制器,讓它監控config map的變化並重新啓動pod和應用,這樣我們就能夠獲取到配置的變更了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實踐證明,即便Kubernetes有一個很好的資源集合,它也無法滿足我們所有不同的需求,因此Kubernetes引入了自定義資源定義(custom resource definition)的概念。這意味着我們可以建模自己的需求,並定義Kubernetes中運行的API。它與其他的Kubernetes原生資源是共存的。我們可以使用任何語言編寫自己的控制器,它們只需要理解我們的模型即可。我們可以使用Java實現一個ConfigWatcher,描述我們前面所闡述的內容。這也就是operator模式,一個與自定義資源定義一起運行的控制器。如今,我們看到已經有了很多的operator,這是擴展Kubernetes實現額外能力的第二種方式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來,我想要介紹幾個在Kubernetes之上構建的幾個平臺,它們大量使用了sidecar和operator來爲開發者提供額外的能力。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"什麼是服務網格?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們首先從服務網格開始,那什麼是服務網格呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們有兩個服務,服務A想要調用服務B,而且可能會使用任意的語言。假設這就是我們的工作負載。服務網格使用了sidecar控制器並將一個代理注入到了我們的服務旁邊。這樣在pod中就有了兩個容器。代理是透明的,我們的應用完全不會感知到代理的存在,但是它會攔截所有傳入和傳出的流量。另外,代理還充當了數據防火牆的角色。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這些服務代理的集合代表了數據平面,它們通常是非常小且無狀態的。爲了獲取所有的狀態和配置,它們會依賴於控制平面。控制平面是有狀態的部分,它會保持所有的配置,收集指標,做出決策並與數據平面進行交互。實際上,我們還需要另外一個組件,也就是將數據輸入到集羣的API網關。有些服務網格有自己的API網關,有些則會使用第三方的網關。但是,如果你查看一下所有的這些組件的話,會發現它們都提供了我們想要的能力。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"API網關主要的關注點在於抽象我們的服務實現。它隱藏了細節並提供了邊界能力。服務網格所做的事情則恰好相反。在某種程度上,它增強了服務中的可見性和可靠性。聯合起來,我們可以說API網關和服務網格滿足網絡方面的所有需求。爲了獲取Kubernetes之上的網絡能力,單純使用服務是不夠的,我們還需要服務網格。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/19image011-1616431696146.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"什麼是Knative?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我想討論的下一個話題是"},{"type":"link","attrs":{"href":"https:\/\/cloud.google.com\/knative","title":"","type":null},"content":[{"type":"text","text":"Knative"}]},{"type":"text","text":",這是由谷歌在幾年前發起的項目。它是在Kubernetes之上的一個層,提供了無服務器的能力,它包括兩個主要的模塊:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Knative Serving:主要關注請求-答覆的交互"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Knative Eventing:更多地用於事件驅動的交互。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們來簡單體會一下Knative Serving是什麼。藉助Knative Serving,我們會定義一個服務,但是它與Kubernetes服務不同,這是一個Knative服務。使用Knative服務定義完工作負載之後,就會得到一個具備無服務器特性的部署(deployment)。我們不需要建立和運行實例,請求抵達時,它可以從零開始啓動。這樣我們就具有了無服務器的能力,它可以快速擴展,也可以收縮至零。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Knative Eventing爲我們提供了一個完全聲明式的事件管理系統。假設我們有一些想要集成的外部系統和一些外部的事件生產者,在底層,我們讓自己的應用運行在一個容器中,它具有一個HTTP端點。藉助Knative Eventing,我們可以啓動一個broker,它可以觸發一個映射到Kafk的broker,也可以觸發內存或雲服務。除此之外,我們還可以啓動一個導入器(importer),將其連接到外部系統上並將事件導入到我們的broker中。比如,這些導入器可以基於Apache Camel,它有數百個連接器。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"事件進入到broker之後,我們就可以通過YAML聲明的形式,讓我們的容器訂閱這些事件。在我們的容器中,並不需要任何的消息客戶端,如Kafka客戶端。我們的容器會以HTTP POST的形式得到事件。這是一個完全由平臺託管的消息基礎設施。作爲開發人員,我們只需要在容器中編寫業務邏輯,而不需要處理任何消息相關的邏輯。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/8image012-1616431698919.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從我們的需求來看,Knative滿足了其中的一些。從生命週期的角度來看,它給了我們的工作負載無服務器的能力,所以能夠收縮至零,並從零開始進行擴展。從網絡的角度來看,它與服務網格有一些重疊,Knative也能進行流量轉移。從綁定的角度來看,它對使用Knative導入器的綁定提供了很好的支持。它還能爲我們提供Pub\/Sub或點到點的交互,甚至某些順序化(sequencing)處理的功能。它滿足了一些類別的需求。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"什麼是Dapr?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"另外一個使用sidecar和operator的項目是"},{"type":"link","attrs":{"href":"https:\/\/dapr.io\/","title":"","type":null},"content":[{"type":"text","text":"Dapr"}]},{"type":"text","text":",它是由微軟在最近發起的一個項目,並且正在快速流行起來。1.0版本"},{"type":"link","attrs":{"href":"https:\/\/www.infoq.com\/news\/2021\/02\/dapr-production-ready\/","title":"","type":null},"content":[{"type":"text","text":"已經被認爲可以投入生產環境使用了"}]},{"type":"text","text":"。這是一個sidecar形式的分佈式系統工具集,Dapr中的任何內容都是以sidecar的形式提供的,並且具有一組他們稱之爲構建塊(building block)或者能力的特性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那Dapr的這些能力是什麼呢?第一組能力是關於網絡的。Dapr能夠實現服務發現以及服務間的點到點集成。類似的,它還能夠進行跟蹤、可靠性通信、重試以及恢復。第二組能力是關於資源綁定的:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"它有大量到雲API和不同系統的連接器"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還能實現消息的發佈\/訂閱以及其他邏輯。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有意思的是,Dapr還引入了狀態管理的概念。除了Knative和服務網格提供的功能之外,Dapr還在狀態存儲之上進行了抽象。除此之外,我們還可以在存儲機制的支持下與Dapr進行基於鍵值的交互。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從較高的層級來看,這種架構是將我們的應用放在最頂層,而應用可以採用任意的語言。我們可以使用Dapr提供的客戶端庫,但並不強制要求這樣做。我們可以使用語言本身的特性來發起HTTP和gRPC調用sidecar。它與服務網格差異在於Dapr sidecar並不是一個透明的代理。它是一個顯式的代理,我們必須要在應用中調用它,並通過HTTP或gRPC進行交互。根據我們所需要的能力,Dapr可以與其他的系統進行交互,比如雲服務。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/18image013-1616431699532.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Kubernetes上,Dapr以sidecar的形式進行部署,它也可以在Kubernetes之外運行(它並非只能用在Kubernetes中)。除此之外,它還有一個operator,sidecar和operator是主要的擴展機制。還有一些其他的組件用來管理證書、處理基於actor的模型以及注入sidecar。我們的工作負載與sidecar進行交互,並且要完成與其他服務的對話,從而實現與不同雲供應商的交互性。它還爲你提供了額外的分佈式系統的能力。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果讓我總結一下這些項目爲我們提供了什麼的話,那麼我們可以說ESB是分佈式系統的早期形態,在這裏我們具有中心化的控制平面和數據平面,但是無法很好地進行擴展。在雲原生中,我們依然有一箇中心化的控制平面,但是數據平面是去中心化的,而且是通過良好的隔離能夠實現高度的可擴展性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們始終會需要Kubernetes進行良好的生命週期管理,在此之上,我們可能會需要一個或多個附加組件。也許我們需要Istio實現高級的網絡,需要使用Knative實現無服務器的工作負載,或者需要Dapr進行集成。這些框架能夠與Istio和Envoy進行很好的協作。從Dapr和Knative的角度來看,我們可能必須要從中選擇一個。將它們聯合起來,我們就以雲原生的方式提供了過去ESB上所擁有的功能。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"未來雲原生的新趨勢:生命週期的趨勢"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在接下來的部分中,我提供了一個帶有一定傾向性的項目列表,我認爲這些領域的開發狀態非常令人興奮。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/8image014-1616431695762.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我想首先從生命週期開始。藉助Kubernetes,我們可以爲應用實現非常有用的生命週期管理,但是對於複雜的生命週期管理來講,這可能是不夠的。例如,如果你有一個更復雜的有狀態應用,那麼Kubernetes中的部署原語對你的應用程序來說就是不夠的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這些場景下,我們就可以使用operator模式。我們可以使用operator進行部署和升級,也可以進行備份,可能會是將服務存儲到S3上。除此之外,你可能還會發現Kubernetes中的健康檢查機制不夠好,比如僅有活躍性檢查和就緒檢查還是不夠的。在這種情況下,我們可以藉助operator實現更智能的活躍性檢查和就緒性檢查,並基於此進行恢復。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第三個領域是自動擴展和調優。你可以實現一個能夠更好地理解你的應用的operator,從而能夠在平臺上自動調優。如今,有兩個主要的框架來編寫operator,分別是來自Kubernetes特別興趣小組的Kubebuilder以及Red Hat所創建的operator框架所包含的Operator SDK。它包含下面幾個組成部分:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Operator SDK允許我們編寫operator,Operator Lifecycle Manager能夠管理operator的生命週期,而OperatorHub則可以發佈operator。如果感興趣的話,我們可以看到上百個管理數據庫、消息隊列和監控工具的operator。從生命週期角度來看,operator可能是在Kubernetes生態系統中最活躍的開發領域。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"網絡的新趨勢:Envoy"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我選擇的另外一個項目是"},{"type":"link","attrs":{"href":"https:\/\/www.envoyproxy.io\/","title":"","type":null},"content":[{"type":"text","text":"Envoy"}]},{"type":"text","text":"。服務網格接口的引入能夠讓我們更容易地切換不同的服務網格實現。在部署方面,對Istio有了一些整合。現在,你不需要部署七個pod了,而只需要部署一次。更有意思的是Envoy項目在數據平面上所發生的變化。我們看到越來越多的第七層協議添加到了Envoy中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/11image015-1616431697613.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務網格添加了對更多協議的支持,比如MongoDB、ZooKeeper、MySQL、Redis,以及最近的Kafka。我看到Kafka社區現在正在進一步改善他們的協議,以便於對服務網格更加友好。我們可以期待,將會有更緊密的集成以及更多的能力。最可能出現的情況是,會有一些橋接能力。我們可以在應用程序的本地發起一個HTTP調用,而代理將會在幕後使用Kafka。我們還可能會在應用程序之外,在sidecar中爲Kafka協議進行轉換和加密。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"另外一個令人興奮的進展是引入了HTTP緩存。現在,Envoy可以進行HTTP緩存。在我們的應用中,不需要使用任何的緩存客戶端。所有的這些都會在sidecar中透明地完成。這裏會有竊聽過濾器(tap filter),所以我們可以竊聽流量並得到流量的副本。最近,隨着WebAssembly的引入,這意味着如果你想爲Envoy寫一些自定義的過濾器,我們不必用C++來編寫,也不必編譯整個Envoy運行時。我們可以用WebAssembly編寫過濾器,並在運行時部署。其中大部分功能仍在進行中。他們沒有固步自封,這說明數據平面和服務網格沒有裹足不前,只支持HTTP和gRPC。他們有興趣支持更多的應用層協議,從而讓我們支撐更多的用例。最主要的是,隨着WebAssembly的引入,我們現在可以在sidecar上編寫自定義邏輯。這種方式很好,只要你不把一些業務邏輯放在那裏就行。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"綁定的新趨勢:Apache Camel"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/camel.apache.org\/","title":"","type":null},"content":[{"type":"text","text":"Apache Camel"}]},{"type":"text","text":"是一個進行集成的項目,它用很多的連接器,能夠連接到使用企業級集成模式的不同系統中。"},{"type":"link","attrs":{"href":"https:\/\/camel.apache.org\/releases\/release-3.0.0\/","title":"","type":null},"content":[{"type":"text","text":"Camel 3.0版本"}]},{"type":"text","text":"已經深度集成了Kubernetes,並使用了相同的原語,比如我們提到的operator。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/7image016-1616431694981.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以在Camel中使用Java、JavaScript或YAML等語言編寫集成邏輯。最新版本引入了一個在Kubernetes中運行並能理解我們的集成需求的Camel operator。當我們在編寫Camel應用程序時,會將其部署到一個自定義的資源中,然後operator就能知道如何構建容器或找到依賴。根據平臺的能力,無論是單純的Kubernetes,還是與Knative結合的Kubernetes,它都能決定使用什麼服務以及如何實現我們的集成需求。在我們的運行時之外,會有相當多的智能處理,但是它們都在operator中,所有的這一切運行都非常快。爲什麼我將其稱之爲一個綁定方面的新趨勢呢?主要是因爲Apache Camel的能力都是由它提供的連接器實現的。這裏有趣的一點是它如何與Kubernetes深度整合。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"狀態的新趨勢:Cloudstate"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我想要討論的另一個項目是"},{"type":"link","attrs":{"href":"https:\/\/cloudstate.io\/","title":"","type":null},"content":[{"type":"text","text":"Cloudstate"}]},{"type":"text","text":"以及狀態相關的新趨勢。Cloudstate是Lightbend的一個項目,主要專注於無服務器和函數驅動的開發。在最新版本中,他們正在使用sidecar和operator與Kubernetes進行深度集成。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/8image017-1616431996943.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏的理念在於,當我們編寫函數的時候,在函數中所要做的就是使用gRPC獲取狀態,然後與狀態進行交互。所有的狀態管理是在一個sidecar中進行的,這個sidecar與其他的sidecar形成了集羣。藉助它,我們可以實現事件溯源、CQRS、鍵值查找和消息功能。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從我們的應用程序的角度來看,我們並不瞭解所有這些複雜的事情。我們要做的只是調用一個本地的sidecar,而sidecar會處理這些複雜的問題。在幕後,它可以使用兩個不同的數據源,而且它擁有所有的有狀態抽象,而這是我們作爲開發人員所需要的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"到目前爲止,我們已經看到了雲原生生態系統的現狀和一些仍在進行中的最新進展。我們該如何理解這一切呢?"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"多運行時的微服務已然出現"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們看一下微服務在Kubernetes上的樣子,就會發現我們需要一些平臺性的功能。此外,我們還需要使用Kubernetes的功能,主要用於生命週期管理。然後,我們很可能會透明地使用一些服務網格,比如Envoy,以得到增強的網絡能力,不管是流量路由、彈性、增強的安全性,還是爲了監控的目的。除此之外,根據我們的使用場景,可能還需要Dapr或Knative,這取決於工作負載。所有的這些都是進程外的附加能力。我們剩下的就是編寫業務邏輯了,不過這不是在這些基礎設施之上,而是在另外一個單獨的運行時中。最有可能出現的是,未來的微服務將是多個容器組成的多運行時,其中有些是透明的,有些是顯式使用的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/6image018-1616431996411.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"智能sidecar和啞管道"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果看得再深入一點會是什麼樣子呢,我們使用某種高級別的語言編寫業務邏輯。至於是什麼語言並不重要,它不一定必須是Java,因爲我們可以使用任意的語言來開發自定義邏輯。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"業務邏輯與外部世界的所有交互都是通過sidecar進行的,sidecar會與平臺集成並進行生命週期管理。它爲外部系統進行網絡抽象,並提供高級綁定能力和狀態抽象。sidecar不需要我們進行開發。我們可以直接選取它,並使用YAML或JSON進行配置,然後就可以使用它了。這意味着我們可以很容易地更新sidecar,因爲它不會嵌入到我們的運行時中。這樣的話,打補丁和更新會更容易。它爲我們的業務邏輯實現了多語言運行時。"}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"微服務之後將是什麼呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"回到我最初的問題,微服務之後將是什麼呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/imgopt.infoq.com\/fit-in\/1200x2400\/filters:quality(80)\/filters:no_upscale()\/articles\/distributed-systems-kubernetes\/en\/resources\/6image020-1616431995910.jpg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們看一下架構是如何發展的,會發現從較高的層次來看,應用架構是從單體應用開始的。然而,微服務爲我們提供瞭如何將單體應用拆分成獨立的業務域的指導原則。從此之後,出現了無服務器和函數即服務(FaaS),我們可以進一步將系統拆分爲操作(operation),這帶來了極強的擴展性,因爲我們可以獨立擴展每個操作了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我想說的是,也許FaaS並不是最好的模型,因爲函數並不是實現複雜服務的最佳模型,在這種情況下,如果多個操作與同一個數據集進行交互的話,我們希望能夠將它們放到一起。如果是這樣的話,也許可以考慮我所說的"},{"type":"link","attrs":{"href":"https:\/\/www.infoq.com\/articles\/multi-runtime-microservice-architecture\/","title":"","type":null},"content":[{"type":"text","text":"Mecha架構"}]},{"type":"text","text":"多運行時,在這種架構中,我們將業務邏輯放到一個容器中,並將所有基礎設施相關的關注點作爲一個單獨的容器。它們共同代表了一個多運行時微服務。這可能是更爲合適的模型,因爲它具有更好的屬性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以得到微服務的所有好處,但我們依然將所有的領域、所有的限界上下文放到了同一個地方。我們在一個單獨的容器中放置了所有的基礎設施和所需的分佈式應用,在運行時,我們會將它們組合在一起。目前,與之最接近的可能是Dapr。他們正在遵循這種模式。如果你只對網絡方面感興趣,使用Envoy可能也會接近這種模式。"}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"作者簡介"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Bilgin Ibryam是紅帽公司的產品經理和前架構師,是Apache軟件基金會的提交者和成員。他是一位開源佈道者、博主和演講者,並且是"},{"type":"link","attrs":{"href":"https:\/\/k8spatterns.io\/","title":"","type":null},"content":[{"type":"text","text":"Kubernetes Patterns"}]},{"type":"text","text":"和Camel Design Patterns技術圖書的作者。Bilgin目前的工作重點是分佈式系統、事件驅動架構,以及可重複的雲原生應用開發模式和實踐。請通過@bibryam關注他,以瞭解未來類似主題的更新。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"原文鏈接:"},{"type":"link","attrs":{"href":"https:\/\/www.infoq.com\/articles\/distributed-systems-kubernetes\/","title":null,"type":null},"content":[{"type":"text","text":"Article: The Evolution of Distributed Systems on Kubernetes"}],"marks":[{"type":"underline"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章