當 Spring Cloud 遇上 Kubernetes

完整的微服務框架從此不完整了

Fred Chien(錢逢祥)
Brobridge - 寬橋微服務
7 min readMar 14, 2020

--

Photo by Nikola Johnny Mirkovic on Unsplash

許多客戶在微服務顧問的評估工作做完之後,才有感而發:

以為用 Spring Cloud 成功打造了微服務架構,殊不知導入了 Kubernetes 之後,卻和 Cloud Native 的主流發展生態脫節了。

從 Spring Boot 一直到了 Spring Cloud,許多早已導入的大企業,很久之前就建構出了一個完整的微服務(Microservice)生態,也因為很多的解決方案早已開放原始碼,可以說開發資源已經相當成熟。

這對於許多想要導入微服務架構的企業來說,無疑的是一個最佳的進入點,只要你導入 Spring Cloud,並採用其生態內相關的元件,基本上構建出一套微服務架構,絕對不會有什麼問題,也是正確的選擇。

只是導入了 Kubernetes 之後,似乎一切變了調。

導入 Kubernetes 後到底發生了什麼問題?我們又該如何解決?本文將淺談這個議題,並整理一些解決的手段。

Kubernetes 與 Spring Cloud 的衝突點?

身為 Java 開發者極為幸運,有個 Spring Cloud 這樣完整的微服務框架可以使用,至少微服務架構下所需的基本需求,都能滿足。網路上也有數不清的文獻,可以快速學習怎麼利用這框架開發出自己的微服務架構。

但也由於 Spring Cloud 生態具備著各種完整的微服務元件,在今天 Kubernetes 當道的情況下,當我們把基於 Spring Cloud 開發的服務放到 Kubernetes 之上後, 一些機制將變成自成一格,不受 Kubernetes 生態系的工具和機制所管控。

這一切原因,都是因為從擴展部署、維運面角度出發的 Kubernetes,在最原始容器、應用程式部署及網路層管理的基礎之上,已經逐步實現並貼近應用層的需要,一些微服務架構下的基礎需求(如:Service Discovery、API Gateway 等)開始直接或間接被納入在 Kubernetes 的生態裡。

這導致兩方有些元件功能重疊,而且只能擇其一使用, 一旦你選了 Spring Cloud 的解決方案,就代表你得放棄掉 Kubernetes 那一邊的機制。

Spring Cloud 官方提供的解決方案

為了解決這樣的問題,官方在 Github 上提供了一個開放原始碼專案,說明如何以 Spring Cloud 整合 Kubernetes 生態下的元件,主要討論從原本的元件架構過渡並移植到 Kubernetes 原生環境後的處理方法:

https://github.com/spring-cloud/spring-cloud-kubernetes

有興趣可以自行參考,在接下來的章節,將大概整理一下這份解決方案的幾個重點。

服務發現 (Service Discovery)

關於服務發現,在 Spring Cloud 的經典解決方案中,最知名的不外乎是 Netflix Eureka 和 Hashicorp。其主要原理是在服務部署時,去註冊自己的服務,讓其他的服務可以查詢並找到自己。

但在 Kubernetes 的領域,服務的註冊和查詢是由 Service 元件所負責,其連線名稱,則是利用內部 DNS 來實現。這代表我們要將服務發現的功能,接上 Kubernetes 的 Service 機制。

為了達成這個需求,解決方案中提供了 DiscoveryClient 這個元件,讓基於 Spring Cloud 所開發的應用程式,可以方便查詢其他服務。

使用了 Kubernetes 原生的服務發現,才能被 Istio 所追蹤,未來才能納入 Service Mesh 的管轄。

設定參數管理 (Configuration Management)

在設定參數管理上, Spring Cloud 也有一些既有的解決方案,如:Config Server、Consult 或 Netflix Archaius 等。但在 Kubernetes 上,有 ConfigMap 和 Secret 可以使用,而且通常還會搭配 Vault 來管理敏感設定。

官方的解決方案提供了 ConfigMapPropertySource 和 SecretsPropertySource 的參考實作,來存取 Kubernetes 上的 ConfigMap 和 Secret。

負載平衡和熔斷器 (Load Balancing & Circuit Breaker)

在 Spring Cloud 上有常見的負載平衡元件 Netflix Ribbon 和熔斷器 Hystrix,但在 Kubernetes 的世界,有 Service 元件可實現負載平衡,以及 Istio 可實現熔斷器,開發者通常不用煩惱這個問題。

由於負載平衡和熔斷器的工作,會依賴著服務發現機制,因此 Ribbon 和 Hytrix 原先的功能在 Kubernetes 的原生環境下會失效。官方解決方案內雖有提到了一些關於 Ribbon 整合 Kubernetes 原生環境的實作,但由於相關實作連結已經消失,因此這部分就不做多說明。

以筆者角度建議,避免使用客戶端的負載平衡和熔斷器實作即可。

原有的服務註冊 (Service Registry) 機制將失效

Spring Cloud 原本有自己的一套服務註冊機制,透過下面的設定可以影響服務註冊的行為:

  • spring.cloud.service-registry.auto-registration.enabled
  • @EnableDiscoveryClient(autoRegister=false)

在 Kubernetes 的環境下將失效,因為服務發現不再由 Spring Cloud 的框架所掌控。

另外補充

Spring Cloud 與 Kubernetes 生態系之間的替代方案對照

除了 Spring Cloud 官方解決方案所提及的之外,其他維運層面的部分也同樣有對應的方案,在這裡一併補充,可參照上面圖表。

當然,我們能完全不理會 Kubernetes 原生生態的元件,完全採用 Spring Boot 和 Spring Cloud 的解決方案和框架,然後只把 Kubernetes 當作是部署應用程式的工具和平台。但顯然在未來,Service Mesh 及其它通用的 Cloud Native 技術發展,就會與我們脫節,無法與我們的應用程式深度整合。

後記

相較於 Spring Cloud 的生態以 Java 語言為主,Kubernetes 生態的發展和設計更為通用且廣泛,一些 Spring Cloud 內的元件功能,在 Kubernetes 除了包含支援以外,甚至有更多的整合和考量及延伸的功能。

由於 CNCF 的推波助瀾及更多廠商投入,許多新工具、維運方法、整合能力都層出不窮。因此,在計劃導入微服務架構時,關於 Kubernetes 的各項原生解決方案,需要被放入評估考量之中。

網路上和坊間雖然已經有很多 Spring Boot 和 Spring Cloud 的教學文件與書籍,但不少文獻已經有些時日,很多是在當初沒有 Kubernetes 的場景下所撰寫出來,可能與現在的主流的基礎設施(Infrastructure)環境有落差,這是需要特別注意的部分。

最後,如果您對微服務架構及其生態有任何疑問,或是需要技術上的評估與建議,歡迎與我們 Brobridge 聯絡,取得專業的教育訓練和顧問服務。

--

--