雲原生技術在離線交付場景中的實踐

語言: CN / TW / HK

軟體產品只有交付到使用者手中才有價值,本人在面向政府等 ToG 場景的軟體交付領域具有數年的工作經驗,深知其中痛點。今天藉助這篇文章,分享這些痛點以及我的解決之道。

提出問題

本人供職的公司,其主要客戶群體是省內的政府部門,所開發的業務系統是服務於政府內網之中的移動APP。作為交付負責人,我一直苦惱於如何將一套基於 Spring Cloud 框架開發而來的服務端業務系統交付給我的客戶。完成軟體系統的交付只是萬里長征第一步,如何處理後期的運維工作也是必須面對的問題。政府場景的特殊性,為我的工作平添了許多不利因素,這些 ToG 場景交付的痛點,且聽我娓娓道來。

離線環境交付

與公網環境隔離,與公司網路隔離,完全的離線場景是政府交付工作中的標配特徵,也是 ToG 交付最大的痛點。相信離線環境交付是所有的交付工程師都不想面對的場景,這意味著所有的交付物必須在事先準備好,交付過程中一旦出現任何遺漏和錯誤,都意味著明天必須再來現場一次。

交付環境不統一

如果你從事過面向政府的交付工作,那多半會遭遇過交付環境不統一的情況。由於各級政府部門的 IT 建設腳步不一樣,同樣一套業務系統,在交付到市級部門時,得到的硬體設施可能是一臺物理伺服器,而到了省級部門時,則可能得到了私有云提供的數臺虛擬機器。值得慶幸,物理機與虛擬機器的差異並不大。然而近年來政府的 IT 建設一直在向國產自主可控的方向前進,當省級部門要求使用鯤鵬Arm架構CPU,亦或是使用國產麒麟作業系統進行交付時,和市級部門交付環境的差異就已經非常大了。我甚至不得不將同一套業務系統在兩級部門的交付當作完全不同的兩個專案來對待。這體現出不同交付環境之間的差異,而當我轉身看向公司開發環境時,開發環境與交付環境的差異,已經開始讓我聽到自己頭髮落到地面的聲音了。我很難確定事先準備好的交付資源,在甲方環境部署時會否遭遇作業系統以及硬體設施差異所導致的依賴性衝突問題。這種問題在離線環境下又被放大,我甚至不具備連線公網安裝軟體包來除錯解決依賴性衝突問題的能力。

缺乏自動化運維能力

將軟體交付到客戶環境中,只是最初級的目標,在合同期內維護軟體系統穩定執行是對交付質量更高層次的考驗。依照個人經驗,在一個軟體交付專案中,交付部署的工作量,不及後期運維工作量的一半。我們是不希望所有的軟體問題都需要工程師親自抵達現場解決的,一來無法保障 SLA 服務協議中的時間承諾,其次也會消磨工程師的工作熱情。在離線環境下如何構建起一套具備自動化運維能力的軟體執行環境,變得尤為重要。依靠自動化運維能力,讓一些軟體故障得以自愈,在一定程度上降低了政府交付場景中的運維難度。但選擇任何一種技術實現自動化運維的目標都是需要付出代價的,這意味著我需要在軟體系統交付之前,先行在交付環境中組裝一套穩定可靠的自動化運維平臺。

過度依賴核心人員

在離線化的政府交付場景中,常常面臨如下問題:一是交付環境難以統一時,其中特殊之處只被少數全程參與專案交付的工程師所瞭解,而實際經驗告訴我們,這些特殊之處往往是一些異常情況的根源;二是離線的工作環境使得工程師通過查詢資料來解決問題變成一種奢望,反向提高了對於工程師的經驗和技能的技術要求,因此,“合格”的駐場運維工程師很難招到。以上問題造成了一些運維工作過分地依賴某些核心技術人員的局面,一旦核心技術人員離職或者調崗,對當前的業務連續性將會造成較大影響。所有的這些對人的依賴,都在某個靠譜的駐場工程師希望另謀高就,向我提出辭職申請時痛擊我的腦神經。

持續交付困難

軟體交付並非一次性工作。從專案管理的角度來說,使用者很難在一開始就提出具體且可落實的需求,具體的專案範圍會隨著專案的推進逐漸確定,這是一個漸進明細的過程。而在軟體產品交付的過程中,這種漸進明細體現在交付的產品會經過多次迭代,每次升級後的產品,都距離使用者的最終需求更近一步。而這個持續交付的過程,在離線環境中,所遭遇的難處並不亞於首次交付,甚至會在某些需要回滾的場景中更加複雜。在微服務時代,一套完整的業務系統往往包含了幾十個獨立的元件,元件數量也為持續交付添加了複雜性。

駐場開發難

駐場開發是一種在政府交付場景中常見的需求。標準的軟體產品往往是不能直接滿足甲方需求的,這就需要我們的開發人員可以在甲方辦公室直接定製開發指定的幾個元件,並快速更新到線上環境中去,供甲方驗證。在實際場景中,多數微服務功能是固定的,只有一兩個 jar 包需要頻繁更替。

以往的經歷

我經歷了公司軟體產品交付的完整變革流程。從最開始的 jar 包交付,繼而引入容器化技術交付映象,到後來採用 Kubernetes 容器編排技術,我們始終圍繞著複雜的離線環境進行軟體產品的交付工作。每個階段或多或少的解決了上述各種痛點,所付出的代價也不盡相同。最終我們擁抱了雲原生技術,將業務系統整體作為新的物件實踐了較為簡單可靠的離線環境交付,同時兼顧了以往各種痛點。

Jar 包交付

得益於 Java 開發語言,我們可以將程式碼打包成為僅依賴 JDK 執行環境的二進位制交付產物——Jar 包。彼時我們的軟體產品還處於初級階段,業務系統由10個 Jar 包、Mysql資料庫、Redis 快取、前端Nginx組成。

一次交付工作中,首先要搭建起基礎執行環境,完成 JDK 的安裝。Mysql、Redis 等中介軟體依靠很原始的 rpm 包進行安裝,這個過程經常會遭遇包依賴衝突問題。最後將所有的 Jar 包執行起來,啟動之前免不得進行一系列的人工配置工作。

這種交付方式比較原始,我們會寫一些指令碼來達成一定程度上的自動化,然而這隻在一定程度上提升部署效率,自動化運維能力基本為零。中介軟體的安裝部署對作業系統的繫結程度很高,一旦伺服器的作業系統和我們預先了解的稍有偏差,都可能導致依賴衝突,導致安裝失敗。而配置過程對人工依賴過重,這在高可用部署的環境中表現的尤為突出,配置各種 IP 很容易出錯。

做一個總結,這個階段我們實現了簡單業務系統的離線交付,然而沒有解決其他任何一個 ToG 場景交付痛點。

引入容器化技術

為了抹平交付環境不統一所帶來的複雜度,我們開始引入容器化技術,通過將所有元件容器化,我們只需要確保客戶的伺服器能夠執行 Docker 容器,就不需要再擔心底層作業系統的問題了。官方提供靜態編譯版本的 docker 二進位制檔案,我們再也不用和軟體依賴打交道了。這個階段,我們的業務系統也開始擴充套件,元件的數量上漲到了幾十個,這導致我們不得不同時引入 docker-compose 以及 docker-swarm 技術來解決單機或高可用場景下的元件編排問題。這些技術同時提供了較低程度的故障自愈能力,距離真正的生產可用還有距離。

容器化技術解決了交付環境不統一的問題,但是其他方面的痛點提升有限。隨著業務功能的擴充套件,一個新的痛點逐漸展現出來,我們需要攜帶數十個容器映象進行交付,交付複雜度被交付物數量裹挾著不斷上升。

轉向 Kubernetes 技術

在交付團隊掌握了容器化技術之後,為了解決自動化運維問題,我們開始向 Kubernetes 轉型。Kubernetes 技術是可以為業務系統的交付和運維賦能的,藉助於它,我們的業務系統實現了較高程度的自動化運維能力。

Kubernetes 技術在故障自愈、彈性伸縮等方面的能力提升使我們非常受用,業務系統真正做到了生產可用。但是同時也帶來了新的痛點,那就是它本身過於複雜,無論是開發人員還是現場運維交付人員,都必須對它有足夠的瞭解才可以駕馭。換句話說,這種技術的引入大幅度提高了對核心技術人員的依賴程度,甚至提高了對技術團隊全員的入門門檻。離線化的交付場景下,對交付環境的前期一次性建設的成本大幅度提高,我們必須事先在離線環境中準備好可靠的 Kubernetes 叢集,光這一項工作,就大幅度阻礙了 Kubernetes 技術在交付團隊中的推廣。

新的痛點

經過了前面的幾個階段,我認為面對離線化的複雜交付場景,繼續在容器技術以及 Kubernetes 容器編排技術方向上前進是沒有問題的,每一次技術選型,都在一定程度上解決了很多痛點,我們在交付的過程中已經不懼怕離線環境、交付環境不統一、缺乏自動化運維能力等痛點,但也引入了一些新的問題,是待解決的。

  • 業務功能擴充套件會同步提升交付複雜度。這一新痛點從本質上來說,是由於我們將每一個元件獨立看待,而非將整個業務系統作為整體看待。這樣做的結果就是交付物的數量和交付複雜程度直接掛鉤,如果能將業務系統作為整體交付,而非每個元件單獨交付,那將極大的降低交付複雜度。
  • 每一次新的選型,都引入了新的複雜度,這一點在轉向 Kubernetes 技術時尤為突出。這項技術對業務系統的賦能能力是毋庸置疑的,但無論是一個新環境的首次部署,還是後期的運維難度,對交付團隊成員技術能力的要求是直線上升的。為了降低交付團隊新成員的入門難度,我們開始選型一些能夠降低 Kubernetes 使用難度的圖形化工具,易用性是選型的首要影響因素。
  • 持續交付困難以及駐場開發難這兩大痛點,依然沒有被很好的解決。這二者都需要我們提供機制,解決業務系統在交付環境中持續變更的問題,前者注重業務系統整體框架的迭代升級,後者注重某個元件的個性化快速迭代。

我們開始將目光放在了逐漸火熱起來的雲原生技術領域。首先,雲原生技術是基於容器化技術和 Kubernetes 技術的,我們已經具備了一定的技術基礎。其次,雲原生技術也注重軟體交付領域的各種最佳實踐,其中一些實踐非常契合前文中的痛點。經過一段時間的內部測試選型,我們最終使用了 Rainbond 雲原生應用管理平臺作為交付工具,實現了全新的複雜場景離線交付模式。

雲原生離線交付實踐

最開始,交付團隊內部的一名成員從開源渠道偶然瞭解到了 Rainbond 這款產品,並推薦給開發團隊人員使用。當時僅僅作為圖形化的 Kubernetes 管理工具來使用,以此降低新手開發人員學習 Kubernetes 的門檻。但隨著對產品的瞭解,我們逐漸發覺,Rainbond 真正的用途在於能夠解決軟體產品的交付問題。

將業務系統抽象為應用

以往的交付過程中,我們總是將業務系統中的每一個元件單獨看待,但是在 Rainbond 體系中,管理的單元可以放大到業務系統級別,這種管理單元被稱之為應用。應用內部的元件部署和編排都是基於圖形化操作的,使用起來不難理解。元件間的呼叫關係基於拓撲圖展現,一目瞭然。最重要的是,基於應用這種抽象,我們實現了將元件數量和交付複雜度脫鉤,無論應用中有多少元件,我們始終視之為一個應用。這麼做的好處在交付過程中體現的非常明顯。

應用模板的離線匯出匯入

應用一旦部署編排完成,就可以釋出成一個應用模板並匯出,匯出的產物是單獨管理的一個包。離線的模板包在匯入時完全不依賴於外部網路,匯入完成就可以在離線環境中一鍵安裝,復原為釋出時的樣子。元件之間的相互依賴關係、配置資訊都得以儲存,不需要在交付現場重新配置。這一能力完全改變了交付的邏輯,從單獨交付數十個容器映象,變成了交付一個涵蓋整個業務系統的包,其中難度的下降可想而知。

簡單易用

Rainbond 底層基於 Kubernetes 技術實現容器的排程,提供全面的自動化運維能力。並且將常見的配置從 Yaml 宣告式配置轉化成為圖形化介面操作,極大的降低了入門門檻。引入 Rainbond 體系之後,新入職的工程師可以在簡單的培訓後,一日之內掌握 Rainbond 的使用方式並可以獨立交付業務系統。

原生多雲管理

Rainbond 原生支援面向 Kubernetes 的多雲管理能力。政府交付場景雖說與公網隔離,然而其實同個系統內往往具有想通的內部網路。藉助 Rainbond 的多雲管理能力,我們將省內多個城市政府部門的交付場景統一管理了起來,在省會建立了統一的管理控制檯。這樣的部署模式為業務系統快速在多個數據中心的交付提供了機制,極大的降低了業務系統在全省範圍內交付的成本。

持續交付機制

Rainbond 應用模板支援版本管理,當業務系統有較大改動時,只需要將應用整體重新發布一次,重新匯入到交付環境中去後即可一鍵升級或回滾,極大提升了業務系統升級效率。在以往處理數十個容器映象的升降級和配置工作,需要的時間成本是按天計算的,引入Rainbond 應用模板的版本控制機制之後,升降級的時間成本降低為分鐘級,操作成本則可以忽略不計。

駐場開發快

當甲方要求某個元件做出些許改動時,使用整個應用級別的模板離線匯入顯然得不償失。此時,只需要現場開發人員在個人開發筆記本上打包出 Jar 包,通過上傳 Jar 包構建元件的能力快速構建指定的元件,簡單的拼裝後即可替換對應的元件。這個過程中開發人員只需要提供 Jar 包,甚至不需要學習容器化技術瞭解映象打包的機制,Rainbond 會自動處理後續的工作。

總結

我司交付團隊藉助雲原生技術, 極大的降低了面向政府的複雜離線場景交付工作成本。這種成本節約體現在交付時間縮短、人員技術要求降低、人員操作成本降低、交付物數量減少、配置工作量減少等多個方面。降低成本的同時,也成功為業務系統賦能,能夠自動處理很多異常場景,實現了自動化運維。方便駐場開發,能夠快速的響應甲方客戶的需求,提升客戶滿意度。

然而 IT 工程領域的發展過程就是在不斷面向新的痛點解決問題。目前使用雲原生技術也並非能夠解決所有的問題,在政府交付場景中,也曾經遭遇這一類場景,甲方提出了比較嚴苛的要求,禁止使用容器技術進行交付。這種要求從根源上阻絕了雲原生交付技術的落地,然而如何優雅的回退到 Jar 包交付的路線中去就成了一個問題,期待社群提供支援,將應用模板轉化成為裸機環境可用的交付物,這是後話。