為什麼說Kubernetes是新的應用伺服器
本文最初發表於RedHat開發者部落格 ,經原作者Rafael Benevides授權由InfoQ中文站翻譯分享。
你是否想過我們為什麼要使用容器部署多平臺應用呢?難道這僅僅是“跟風”嗎?在本文中,我將提出一些有挑戰性的問題,以佐證我的觀點,那就是為什麼說Kubernetes是新的應用伺服器。
你可能已經注意到了,大多數的語言都是要經過“解釋(interpret)”的,並且使用“執行時”來執行原始碼。在理論上,大多數的Node.js、Python和Ruby程式碼可以很容易地從一個平臺(Windows、Mac、Linux)轉換到另一個平臺。Java應用則更進一步,它將編譯後的Java類轉換成了位元組碼,能夠在任何具有JVM(Java虛擬機器)的地方執行。
Java生態系統提供了標準的格式來分發同一個應用中的所有Java類。我們可以將這些類打包為JAR(Java Archive)、WAR(Web Archive)以及EAR(Enterprise Archive),在這些格式中包含了前端、後端以及嵌入其中的庫。那麼我就要問了:你為什麼要使用容器來分發Java應用呢?難道它不是已經支援很便利地在不同環境間遷移了嗎?
站在開發人員的角度回答這個問題的話,答案可能並不那麼明顯。但是,我們考慮一下你的開發環境,以及因為開發環境和生產環境的差異可能導致的問題:
-
你使用Mac、Windows還是Linux?在路徑分隔符方面有沒有遇到過
\
和/
相關的問題? - 你使用什麼版本的JDK?是否在開發環境使用Java 10,而在生產環境使用JRE 8?你有沒有遇到過JVM差異所引入的bug?
- 你使用什麼版本的應用伺服器?生產環境是否使用相同的配置、安全補丁和相同版本的庫?
- 在生產部署的時候,是否遇到過不同版本的驅動或資料庫伺服器所導致的JDBC驅動問題,而這些問題在開發環境可能並不存在?
- 你是否請求過應用伺服器管理員為你建立資料來源或JMS佇列,但是在建立的過程中卻出現了拼寫錯誤?
所有的這些問題都是由應用之外的因素導致的,容器最大的好處之一就是它能夠在一個預先構建的容器中部署所有的內容(比如Linux發行版、JVM、應用伺服器、庫、配置,最後還有你的應用)。另外,在一個容器中將所有的東西都包含進來能夠更容易地將你的程式碼轉移到生產環境中,在它無法正常執行的時候,也更容易分析其中的差異。因為它易於執行,所以也很容易將相同的容器映象擴充套件至多個副本。
強化應用
在容器流行起來之前,應用伺服器提供了一些非功能性需求(NFR,non-functional requirement) ,比如安全性、隔離性、容錯、配置管理等等。打個比方,應用伺服器和應用之間的關係就像CD播放器和CD之間的關係一樣。
作為開發人員,你應該遵循預定義的標準並按照特定的格式分發應用,而應用伺服器會“執行”你的應用並帶來一些額外的功能,這些功能因伺服器“品牌”的差異而有所不同。注意:在Java領域,應用伺服器所提供的企業功能的標準最近轉移到了Eclipse基金會。Eclipse Enterprise for Java(EE4J )的工作形成了Jakarta EE 。(關於這方面的更多資訊,請閱讀Jakarta EE官方釋出 的文章或觀看DevNation視訊:Jakarta EE:Java EE的未來 )。
與CD播放器的類比方式相似,隨著容器的流行,容器映象 成為了新的CD格式。實際上,容器映象僅僅是用來分發容器的格式。(如果你需要更深入地瞭解容器映象是什麼以及它們如何進行分發的話,請參見容器術語的實用簡介 。)
容器的真正收益在你需要為應用新增企業級功能時才體現出來。為容器化的應用提供這些功能的最佳方式就是使用Kubernetes作為它們的平臺。另外,Kubernetes平臺還為其他專案提供了很棒的基礎實施,這些專案包括Red Hat OpenShift 、Istio 以及Apache OpenWhisk ,基於這些基礎設施能夠更容易的構建和部署健壯的生產級質量的應用。
接下來,我們探討九個這樣的功能:
1.服務發現
服務發現指的是確定如何連線服務的過程。要獲得容器以及雲原生應用的很多收益,我們需要將配置從容器映象中移除出去,這樣的話,我們就能把相同的容器映象應用到所有的環境中。將配置提取到應用外部是12要素應用 的核心原則之一。服務發現是從執行時環境中獲取配置資訊的方式之一,這樣能夠避免將其硬編碼到應用之中。Kubernetes自帶了服務發現 。Kubernetes還提供了ConfigMaps 和[Secrets] (https://kubernetes.io/docs/concepts/configuration/secret/ )用來將配置從應用容器中移除。在執行時環境中,如果要連線資料庫這樣的服務,我們會儲存憑證資訊,Secrets解決了一些這方面所面臨的挑戰。
藉助Kubernetes,我們無需使用外部的伺服器或框架。儘管我們可以通過Kubernetes YAML檔案管理每個執行時環境的配置,但是Red Hat OpenShift提供了GUI和CLI,能夠讓DevOps團隊更容易地管理配置資訊。
2.基本呼叫
容器中的應用可以通過Ingress 進行訪問,也就是從外部世界路由到你所暴露的服務。OpenShift提供了基於HAProxy的route objects ,它具有各項功能和負載均衡策略。你可以使用路由功能進行輪流部署。這可以作為一些非常複雜的CI/CD策略的基礎。參見下文的“6.構建和部署管道”。
如果你想執行一次性的任務,比如一個批處理或者只是使用叢集來計算一個結果(比如計算Pi的位數),那該怎麼辦呢?針對這種場景,Kubernetes提供了job objects 。同時還有一個cron job ,能夠管理基於時間的任務。
3.彈性
在Kubernetes中,彈性(elasticity)是通過ReplicaSets (它過去被稱為Replication Controllers)解決的。與面向Kubernetes的大多數配置類似,ReplicaSet是一種協調所需狀態的方式:你告訴Kubernetes,系統應該處於各種狀態,Kubernetes就能知道如何達到該狀態。在任意時間,ReplicaSet都能控制副本的數量或應用程式精確的例項數量。
但是,如果你所構建的服務受歡迎程度超出了預先的規劃,計算資源耗盡了該怎麼辦呢?你可以藉助KubernetesHorizontal Pod Autoscaler ,它會基於觀測到的CPU利用率(或所支援的自定義指標 ,以及應用提供的指標)擴充套件pod的數量。
4.日誌
因為Kubernetes叢集能夠執行容器化應用的多個副本,所以將這些日誌聚合起來,以便於在同一個地方進行檢視就變得非常重要了。同時,為了利用自動擴充套件(以及其他雲原生應用的功能)所帶來的收益,容器應該是不可變的。所以,我們應該將日誌儲存在容器之外,這樣它們才能跨執行時持久化。OpenShift允許我們部署EFK技術棧來聚合來自主機和應用的日誌,即便這些日誌來自多個容器甚至已刪除的pod均是可以的。
EFK技術棧的組成如下所示:
- Elasticsearch (ES),儲存日誌內容的物件儲存;
- Fluentd ,從節點收集日誌並將其傳送至Elasticsearch
- Kibana ,針對Elasticsearch的Web UI。
5.監控
儘管日誌和監控看上去解決的是相同的問題,但是它們之間是不同的。監控是觀察、檢查、通常還有告警以及記錄,而日誌則只有記錄。
Prometheus 是一個開源的監控系統,它包含了時序資料庫。它可以用來儲存和查詢指標、告警,並使用視覺化的方式檢視系統內部的執行狀況。Prometheus可能是監控Kubernetes叢集方面最流行的可選方案。在Red Hat開發人員部落格 上,有多篇介紹使用Prometheus 進行監控的文章。在OpenShift部落格 上,也能找到關於Prometheus的文章。
你還可以看到Prometheus和Istio實際結合使用的教程 。
6.構建和部署管道
對於你的應用來說,CI/CD(持續整合/持續交付)並不是“必備”的要求。但是,CI/CD通常被認為是成功軟體開發和DevOps 實踐的支柱。如果沒有經過CI/CD管道的話,軟體不應該釋出到生產環境中。Jez Humble和David Farley合著的《持續交付:釋出可靠軟體的系統方法》中是這樣描述CD的:“持續交付能夠將各種型別的變更釋出到生產環境中,包括新特性、配置變化、缺陷修正以及體驗性的功能,或者說以可持續的方式將這些變更安全且快速地交到使用者的手裡”。
OpenShift內建提供了CI/CD管道,將其作為“構建策略 ”。讀者可以檢視我兩年前錄製的視訊 ,其中包含了部署一個全新微服務的Jenkins CI/CD管道樣例。
7.適應性
Kubernetes為叢集本身 提供了適應性(resilience)方案,它還提供了PersistentVolumes 來支援卷(volume)的副本,從而幫助應用實現適應性。Kubernetes的ReplicationControllers /部署能夠確保指定數量的pod副本在整個叢集中始終正常執行,它會自動處理任何可能出現的節點 故障。
結合適應性,容錯能夠作為一種有效的方式來處理使用者對於可靠性和可用性的關切。執行在Kubernetes上的應用還可以通過Istio 的重試規則、斷路器和池彈射(pool ejection,即移除掉出現故障的容器——譯註)來實現容錯。如果你想自行了解一下的話,可以嘗試Istio Circuit Breaker的教程 。
8.認證
在Kubernetes中,認證可以通過Istio的mutual TLS認證 來實現,它致力於增強微服務及其通訊的安全性,而無需服務程式碼的變更。它會負責:
- 為每個服務提供一個代表其角色的強標識(identity),從而允許它能夠跨叢集和雲進行互操作;
- 保護服務與服務之間的通訊,以及終端使用者與服務之間的通訊;
- 提供key管理系統,自動化key和證書生成、分發、輪換和撤銷。
另外,值得一提的是,我們還可以在Kubernetes/OpenShift叢集中執行Keycloak 以提供認證和授權。Keycloak是Red Hat Single Sign-on的上游產品。關於它的更多資訊,請參閱使用Keycloak簡化單點登入 。如果你使用Spring Boot的話,還可以觀看DevNation視訊:使用Keycloak保護Spring Boot微服務 或閱讀部落格文章 。
9.跟蹤
基於Istio的應用可以配置為使用Zipkin 或Jaeger 收集跟蹤的span。不管使用什麼語言、框架或平臺來構建應用,Istio都能支援分散式跟蹤。關於這方面的知識,可參考該教程 。讀者還可以參見“在膝上型電腦上掌握Istio和Jaeger的基礎知識 ”以及最近的DevNation視訊:使用Jaeger進行高階的微服務跟蹤 。
應用伺服器會消亡嗎?
通過這些功能,你就能意識到Kubernetes + OpenShift + Istio確實能夠增強你的應用,並且提供了一些特性,這些特性以前都是由應用伺服器或者像Netflix OSS 這樣的框架來負責的。這是否意味著應用伺服器將會消亡呢?
在這個新的容器世界中,應用伺服器正在變得越來越像框架。軟體開發的演化很自然會導致應用伺服器的演化。這種演化的一個例子就是Eclipse MicroProfile 規範以及WildFly Swarm 應用伺服器,它為開發人員提供了各種特性,比如容錯、配置、跟蹤、REST(客戶端和服務端)等等。WildFly Swarm和MicroProfile規範的設計是非常輕量級的,WildFly Swarm並不包含完整Java企業級應用伺服器的各種各樣的元件。相反,它關注微服務,只保留了將應用按照簡單可執行的“.jar”檔案進行構建和執行的功能。在該部落格中,你可以閱讀到關於MicroProfile 的更多資訊。
另外,Java應用還包括Servlet引擎、資料庫池、依賴注入、事務、訊息等特性。當然,框架可能會提供這些特性,但是應用伺服器必須要具備在任何環境下構建、執行、部署和管理企業級應用所需的各種功能,不管它是不是在容器中執行。實際上,應用伺服器可以在任何地方執行,例如,在裸機上、在像Red Hat Virtualization 這樣的虛擬化平臺上、在像Red Hat OpenStack平臺 這樣的私有云環境中以及在像Microsoft Azure 或Amazon Web Services 這樣的公有云環境中。
好的應用伺服器要確保它所提供的API和具體實現之間的一致性。開發人員可以確信如果他的業務邏輯需要特定的功能,他所部署的邏輯是正常執行的,因為應用伺服器開發人員(以及預先定義的標準)能夠保證它們之間能夠協同工作和協同演化。另外,好的應用伺服器還要負責最大化吞吐量和可擴充套件性,因為它要處理來自使用者的所有請求;減少延遲並提升負載能力,它有助於提升應用的可處置性 ;輕量級的資源佔用,最小化硬體資源和成本;最後,還要足夠安全,能夠防範所有的安全漏洞。對於Java開發人員來說,Red Hat提供了Red Hat JBoss企業級應用平臺 ,滿足了現代、模組化應用伺服器的所有需求。
結論
容器映象已經成為分發雲原生應用的標準打包格式。儘管容器本身並沒有為應用提供任何真正的業務優勢,但是Kubernetes及其相關的專案,如OpenShift和Istio,提供了非功能性的需求,而這些需求過去曾是應用伺服器的功能的一部分。
開發人員過去所使用的大多數非功能性需求,來源於應用伺服器或者像Netflix OSS 這樣的庫,這些需求是與特定語言繫結的,比如Java。但是,如果開發人員選擇使用Kubernetes + OpenShift + Istio來滿足這些需求的話,它們是與任何特定語言都沒有關聯的,這樣的話就能鼓勵開發人員針對每個使用場景選擇最佳的技術/語言。
最後,在軟體開發領域,應用伺服器依然有它的位置。但是,它們變得更像是特定語言的框架,在開發應用的時候,這是很簡便的,因為它們包含了大量已經編寫就緒且經過測試的功能。
轉移到容器、Kubernetes和微服務架構時,最棒的事情之一就是不必為應用選擇單一的應用伺服器、框架、架構風格甚至程式語言。你可以很容易地部署一個含有JBoss EAP的容器,讓JBoss EAP執行已有的Java EE應用,其他的容器則可能會包含使用Wildfly Swarm編寫的微服務或者使用Eclipse Vert.x編寫的反應式程式。這些容器都可以通過Kubernetes進行管理。如果想了解這些概念如何實際執行,參考Red Hat OpenShift應用執行時 。通過Launch服務 線上構建和部署示例應用,這些應用可以使用WildFly Swarm、Vert.x、Spring Boot或Node.js。選擇“Externalized Configuration”以便於學習如何使用Kubernetes ConfigMaps,這足以讓你踏上學習雲原生應用的征途。
你可以說Kubernetes/OpenShift是新的Linux ,甚至可以說“Kubernetes是新的應用伺服器”。但實際上,應用伺服器/執行時+OpenShift/Kubernetes + Istio已經成為了雲原生平臺的事實標準。
關於作者
Rafael Benevides是Red Hat 的開發者體驗(Developer Experience)總監,具有多年的各領域IT行業經驗,他幫助世界範圍內的開發人員和公司提升軟體開發的效率。Rafael將自己定位為問題解決者,並樂於分享。他是Apache DeltaSpike PMC成員,該專案曾獲得過Duke’s Choice Award,他還會在JavaOne、Devoxx、TDC、DevNexus等技術會議上發表演講。