私有化場景下大規模雲原生應用的交付實踐

網易數帆發表於2021-12-11
本文根據作者在 CSDN 雲原生 Meetup 深圳站的演講內容整理,分享雲原生趨勢下網易數帆在私有化場景下大規模應用的交付實踐,包括在實踐過程中遇到的問題,如何實現標準化、高效率且高質量的交付方案,以及取得效果。

背景介紹

軟體私有化交付部署是建立在企業自有基礎設施的基礎之上的,是為一個企業客戶單獨使用而構建的硬體/軟體執行環境;因而能夠提供對資料安全、合規審計和服務質量的有效控制。

軟體的私有化是由市場供需關係決定的。也分為甲方和乙方,甲乙雙方各取所需從而使面向企業的私有化市場正常運轉,例如以下雙方的一些訴求:

甲方(資金提供方)訴求

  • 政策性的行業合規和安全化訴求。
  • 企業網路完全隔離限制,不能和網際網路建立通訊,無法使用公有云產品。例如金融企業內網。
  • 企業運營的資料具有敏感性,不適合直接執行在公共網際網路。例如政府企業溝通交流的工具使用企業微信、企業釘釘等資料要求絕對保密。
  • 頭部網際網路企業的雲技術能力強,投入力度大,產品整體相對較好,期望使用領先的雲技術能力。例如期望在內部使用阿里雲、騰訊雲、華為雲以及數帆數帆輕舟或大資料等產品。
  • 傳統企業希望進行數字化轉型,但是自研體系能力欠缺,從頭開發成本太高且週期較長,希望採購相關成熟的產品助力快速數字化轉型。
  • 企業有自己的機房和伺服器,但資源分散且利用率不高,希望一些私有產品能充分利用這類資源。
  • 業務管理與協同溝通割裂,著力搭建一體化成本適宜、安全高效組織協同管理平臺。
  • 缺乏統一標準支撐平臺,基礎供給能力產品容易重複建設,使用者體驗參差不齊。
  • 難以快速響應業務創新。多年資訊化的堆疊,垂直化的建設導致整合能力和開放能力不適合業務創新環境。
  • 其他由於特殊場景需要卻缺失的能力,希望通過合作的方式由其他供應商來協助建設。

乙方(產品提供方)訴求

  • 公有云廠商的公有云業務增長速度不及預期,希望通過支援私有化交付的方式擴充新的業務市場。
  • 產品設計之初就是面向其他企業的,而不是面向公網 C 端使用者的。像一些 ERP 系統、網易數帆輕舟平臺等等。

通過以上甲乙方的訴求可以知道,如果乙方剛好可以滿足甲方的一個或多個需求,那麼就有了合作和軟體私有化交付的場景出現。

是否有遇到過如下場景?

測試環境與生產環境隔離。一些企業由於內部的流程或安全規範的要求,測試環境與生產環境是隔離的狀態。例如執行節點間隔離或網路策略的隔離,甚至是物理上的隔離需要更換裝置才能訪問生產環境,這時在測試環境測試驗證的服務如何上線到生產環境?

生產環境禁止訪問 Git 執行流水線。程式碼是企業的核心資產之一,保障原始碼的安全是企業重點保障的資產;生產環境一般有自己的機房,或者一些第三方的公有云環境,企業一般不會允許將核心原始碼暴露到公網上的,這些情況下生產環境是禁止訪問內網的 Git 程式碼託管平臺的。而且,在生產環境重新執行CI流水線構建的映象,並不是 QA 團隊在測試環境測試迴歸驗證過的映象,即使他們的原始碼相同,但本質上是兩個映象。

在 Kubernetes 中部署應用時涉及較多型別資源管理問題。在 Kubernetes 叢集中部署服務並不是簡單的將 Image 映象執行起來就可以了,實際上還會涉及一些其他相關的 Kubernetes 的資源,例如常見的資源有 Deployment、Service、Ingress、Secret、ConfigMap、PV/PVC、ServiceAccount、RBAC等等以及其他擴充套件服務的相關資源,如 Prometheus-operator 的 ServiceMonitor。這麼多型別的檔案該如何維護管理才能高效且不出錯呢?

應用上線需要符合公司規範。為了保障上線的順利,符合上線的質量、安全等要求,企業都會對業務上線制定一些流程或者規範。同時,在多人協作的團隊中,如果沒有一定的規範參考指導,會因為資訊不一致導致應用管理混亂。比如最常見的就是映象的命名規範,同一個服務可能會出現 myapp:v20211129、myapp:v1.3.11、myapp:1.3.11、myapp:v1.3.11-20211129、my_app:v1.3.11 、my-app:v1.3.11 甚至是 yourapp:v1.3.11 。這些映象 tag 實際上是指同一個 Git Release v1.13.11 的程式碼版本,但由於沒有規範約束導致管理難,而且容易出錯。

多部門或子公司開發的產品複用。在企業內部一個部門開發了好的一款優秀的應用,其他部門也希望能夠使用這個應用,特別是大型企業有多個子公司時尤為明顯。這類應用例如:日報週報系統、裝置日誌系統、發票管理系統、ERP系統等等。這時如何將這些應用分享給其他部門會成為一個挑戰,如果交付過程太過複雜就會導致推廣受限,進而在集團層面產生資源的浪費。

軟體私有化交付到客戶環境。如前文提到的 ERP 系統、網易數帆輕舟平臺等,這些 toB 私有化產品在交付時會有很多的困難,如何高效高質量的將交付軟體到客戶環境成為這類企業核心關注的重點之一。

本文主要探討的就是網易數帆輕舟團隊在私有化場景下大規模應用的交付實踐,在實踐過程中同樣會涉及到上述的這些問題,通過本文提供的實踐給上述的場景提供一些參考。

軟體私有化交付的痛難點

軟體私有化交付時一般都不會太順利,在不同的階段,不同的角色或維度會有各種各樣問題,這些問題有些可能會決定整個專案是否延期,有些問題甚至影響專案能否成功。

在專案早期,如果能評估到一些痛難點,提前準備相關的應對策略,將會給產品的私有化交付提供很大的幫助。

站在交付方,以私有化交付全域性的維度來分析專案交付前後的痛難點,可以分三大類,分別是使用者側、交付側和工程售後側。

使用者側痛難點

產品功能需求多樣。標準的產品不滿足企業的需求,需要軟體提供商按照企業的需求進行產品的修改或適配,但是跨企業的協同效率相對較低,經常出現返工修改以及環境頻繁升級的問題。
資源準備週期長。時間長,或者資源變更修改時流程長。由於企業內部資源申請需要經過多層的稽核和審批,如果不符合企業規範要求調整申請又需要從新審批流程,這個週期可能是周,甚至是月。
企業業務上線規範。使用者有自己的上線運維規範,交付軟體需要滿足他們的運維或安全的規範。例如有等保三級,效能指標、安全掃描、上線時間視窗短等等規範要求,但這些在做產品時可能沒有全部考慮到。
使用者側的變更。由於裝置搬遷、網路變更、裝置升級、關機等沒有,導致無法展開交付。
沒有按照部署規劃要求準備資源。討論好的資源需求申請,由於客戶內部的某些原因無法按照前期規劃的方案交付,或使用者準備的資源環境不穩定。

交付側痛難點

交付人員要求高。交付過程涉及作業系統、Docker/Kuberentes、交付產品本身以及使用者流程和基礎設施等方面問題,需要交付人員有較強的技術基礎和使用者溝通的能力。
測試驗證複雜。在部署完成後,為了保障交付質量的,一般都會要求有測試驗證的流程,對於自動化測試無法覆蓋還需要人工手動迴歸來保障交付的環境質量。交付產品越複雜,測試驗證也就會越複雜。
跨企業協同困難。在專案開始部署前,都會設計部署實施方案並和使用者溝通,但由於雙方沒有對齊導致的方案和資源不一致,現場實施時受阻。即使可以調整方案,但依舊會給專案帶來延期的風險。
使用者的網路隔離與限制。企業考慮到安全等原因,網路無法訪問網際網路,在交付實施過程中遇到問題時查詢資料,尋求遠端協助以及下載更新檔案都是受限的。
部署包較大,上傳檔案時間長。使用容器化私有交付時,一般都是將程式構建成離線的 Image 映象。Image 映象即使通過映象層的複用降低了整體的大小,但由於交付系統本身的複雜導致依舊會有大量無法複用的層,結果就是離線映象包或部署包比較大。特別是傳統企業使用者的網路質量和頻寬並沒有網際網路企業那樣好,這就導致了專案交付用到的部署包即使用行動硬碟複製到客戶現場,上傳到實際的部署執行環境依舊會花費較多的時間。

工程售後側痛難點

基礎設施多樣。在私有化場景下,不同的企業客戶有自己獨有的基礎設施。比如不同的硬體,有的客戶採購了華為的伺服器硬體,有的客戶採購了 HP 的伺服器硬體,也有的客戶自己定製伺服器。作業系統也是各有不同,例如在企業內部常見的作業系統有 CentOS/Debian/Ubuntu/Redhat/統信 UOS/麒麟OS等等。CPU 架構也可能不同,有 x86 的伺服器,也有 ARM 的伺服器。
私有化的產品複雜。如果私有化的產品本身比較複雜,在私有化版本釋出時需要真正的能夠理解產品並對私有化交付體系有較深刻認識的負責人來把整體控私。否則由於私有化技術選型、版本的管理、自動化的封裝、場景的認知不足、準備的材料缺失或者其他考慮不周全導致產品的交付和管理複雜且混亂。
產品本身質量不高。由於新功能的加入頻繁的需求變動,導致產品功能不穩定 Bug 數量比較多,QA 的測試把控不到位的話,會導致現場交付時分析定位和解決 Bug 。現場定位解決問題不僅不方便,同樣會消耗較多的時間。
文件材料缺失。在做私有化時,建議提供匹配的文件工程師。企業在進行外部採購時,有些材料是強制要求有的,否則不會驗收該專案。而且,如果每次使用者有文件需求時都是首次準備,質量是否高暫且不說,給使用者的感覺也不好,顯得不夠專業。
專案數量逐年增長。專案數量的增長本身說明產品賣的好,但也會帶來運維和售後的成本增長。在合適時間應該做好人力的評估,及時擴充團隊和人員,否則會給當前的員工帶來較為繁重的工作任務進而導致人員流動較大。
客戶環境離線,後期維護難度大。由於網路離線無法及時收取異常告警資訊,需要使用者收取到告警反饋給售後人員,可能由於技術的差異導致問題定位和修復過程不順利。由於離線,一些預期內的變更或升級需要出差客戶現場,支援的成本比較高。
使用者基礎設施影響。如果交付的是軟體產品,由於基礎設施如機器、網路、電源等都是由使用者其他部門維護,基礎設施異常時,會影響上層的軟體的穩定執行。

由於上述的一些原因導致軟體在私有化交付時交付週期長,交付質量差、交付成本高。如果成本太高,這個專案可能就由於投入太多而虧損。

為了保障軟體私有化的正常交付,在進行架構設計和技術選型時應該結合當前主流技術體系,選擇合適的解決方案。

基於 Helm 的應用封裝、交付、升級與環境維護

軟體應用交付現狀

軟體的交付部署有多種方式,按照交付方式可以分為傳統基礎交付、自動化交付和雲原生交付三種。

傳統基礎交付。傳統的應用交付是應用交付的基礎方式,比如常用的 rpm 軟體包或者直接二進位制的方式安裝執行,比較適合場景相對固定的基礎設施。如果有較多的軟體包依賴,一般還會搭建一些 YUM 或 DEB 的軟體源來快速安裝依賴。這類服務的執行一般可以通過 systemd 或者 supervisor 的方式來管理。自動化交付和雲原生交付也是在這種方式之上構建的。

自動化交付。如果軟體數量較多,安裝部署過程有著複雜的邏輯時,使用手動 rpm/yum 安裝會比較繁瑣且易出錯。一般都會使用自動化的方式封裝,如 shell 和 Ansible 就是主流的自動化工具。

雲原生交付。由於雲原生的概念興起,加上早期的 DevOps 理念的長期薰陶,應用又有了新的交付模式。在雲原生的場景下,使用基於流水線的 CI/CD(持續整合與持續交付)模式成為了新的主流,提供了快速高效的應用迭代節奏。雲原生交付執行的環境基本上都是基於 Kubernetes 平臺,所以也有一些工具可以直接管理和部署應用,比如 KubeVela 。但是,目前真正在企業內生產環境使用的,並且已經屬於 CNCF 畢業的專案只有 Helm 。

按照交付部署時是否能夠聯通各個系統,可分為線上交付和離線交付。

線上交付。線上交付是指在交付部署過程中全部或者部分材料執行在其他伺服器上,在安裝部署時可以通過網路的方式獲取到這些資料。比如常見的基於Nginx 的 YUM 軟體源,或者企業內部的 Harbor 映象倉庫,內部的 Gitlab 程式碼參考,或者公網的 Maven 倉庫等。線上交付的好處是不需要提前準備準備這些資源,需要什麼資源就到對應的伺服器上獲取即可。

離線交付。離線交付和線上交付剛好相反,部署時依賴的資源無法外部獲取,需要單獨準備依賴的資源。沒有 YUM 軟體源就本地臨時搭建一套或者把離線的軟體包以及依賴的軟體包都下載下來準備好一起安裝。在離線場景下有很多服務需要部署時搭建,這也給專案的交付增加了很多的困難。

複雜的客戶基礎設施帶來了複雜的交付場景。如果基於傳統和自動化的方式交付,會有一個長長的適配支援相容清單,例如硬體裝置、CPU架構、作業系統等等,這無疑是給企業帶來了大量的人力成本消耗。

但是,如果選擇了雲原生的方式交付應用,就有機會將這種差異的場景人力消耗降到最低。

輕舟應用交付工具選型

基於容器化的交付。面對使用者環境的多樣,基於 Docker 容器化的方式封裝應用能夠遮蔽底層基礎設施的差異,使交付的製品根據有普適性。

基於 Kubernetes 的執行平臺。容器的執行排程、故障的發現與自動處理、彈性的擴縮容、簡單的網路環境等環境比較薄弱,而 Kubernetes 剛好解決這些痛點問題。使用 Kubernetes 作為容器的執行環境,能大大降低交付和運維的複雜度。

基於 Helm 的應用構建與交付部署。Helm 能夠管理應用的多個不同的 Kubernetes 資源,按照一定的策略來使其在叢集中生效。同時,和 rpm/deb 類似也能標準化定義應用,有 Helm 定義的標準化應用就是 Chart。

Helm 的版本選擇

首選 Helm3 。在已經有Kubernetes 叢集的情況下,只需要一個 kubeconfig 就可以完成環境的交付部署。

Helm 的版本選擇有 Helm2 和 Helm3 兩種。如果您是新手,當看到這篇文章時,強烈建議您直接選擇 Helm3;如果您已經使用了 Helm2,也同樣建議您儘快升級到 Helm3。Helm3 不僅在架構上簡單了很多,在功能上,使用和易用上都有了很大的優化。

Helm3 於2019 年 11 月 13 日釋出。Helm3 公開發布 12 個月後,對 Helm 2 的支援正式結束。

雲原生應用的定義與標準化

當使用 Helm Chart 來定義雲原生應用時,應該也很希望類似 RPM/DEB 軟體包一樣可以定義一定的規範標準。幸運的是 Helm 也是支援的,Helm 定義標準分兩種,強制標準和推薦標準。

強制標準是指在 Helm Chart 的目錄結構上,有一些檔名稱放置的位置,內建的函式或變數,模板的渲染方式和資源的優先順序等是必須準守的,否則 Helm 無法正常的工作。比如 values.yaml 是預設的引數配置檔案,templates 目錄是 Kubernetes 的資源模板目錄等。

推薦標準是指在強制標準基礎之上,企業根據業務需求和管理規範來定義的 Chart 標準。例如應用的命名規範、Kubernetes 資原始檔命名規範、環境變了的命名規範、安裝升級的邏輯規範等。

對於強制規範是必須遵守的,否則 Chart 無法正常工作。而對於推薦標準是通過人為約束或定義腳手架的方式來管理。新應用使用腳手架的方式建立手,就已經是符合標準的應用。

1.定義變數:export XDG_DATA_HOME=/root/.helm
2.腳手架路徑:/root/.helm/helm/starters/chartstarter
3.新建應用:helm create --starter chartstarter myapp

即使在後續的迭代的過程中,應用的一些配置和標準偏移了,也同樣可以使用自動化的 Check 的方式來掃描是否違反了標準。

製品的管理

在雲原生場景下的軟體包製品常見的有 code 原始碼、編譯或打包的可執行檔案、構建的系統軟體包(可選,如RPM包)、構建的映象、以及 Helm Chart 包。

最小原子化。在製作 Chart 包時,根據業務的場景特性決定一個 Chart 中包含的業務服務數量。輕舟的 Helm Chart 是基於應用程式碼倉庫作為最小單元,即一個 Chart 中只有一個功能性程式映象。如果業務系統不是很大,只有幾個應用的話,也可以考慮使用子Chart的方式來管理多個服務,如 WordPress Helm Chart。

版本可追溯。最小原子化後,在結合一定的內部規範就可以做到 GitRelease,映象 Tag,ChartAppVersion 一致,部署或執行時可根據環境 Chart 版本快速溯原始碼版本。

例如:

1.Git Release:myapp  Rlease/v1.23.6
2.Image:   myapp:v1.23.6
3.Chart:    myapp-v1.23.6.tgz

Helm Chart 中變數的複用與預設

Helm Chart 的安裝時可以指定多個 values.yaml 檔案,命令列引數右邊的 values.yaml 內容會覆蓋左邊 values.yaml 的內容。

Chart 中預設的 values.yaml 。values.yaml 只有 myapp 自己 Chart 會用到的配置項 ,配置項儘量以預設的方式配置在values.yaml 中,如預設:

1.global.imagePullSecret
2.global.clusterDnsDomain
3.myapp.resources
4.myapp.mysql.dbname

values-global.yaml 。支援所有的配置項,但並不需要所有配置,如環境差異配置:

1.global.imageRegistry.addr(project,user,passwd)
2.global.mysql.host(port,user,passwd)

values-myapp.yaml。在 values-global.yaml 定義了該欄位,但是因為某些原因需要調整的內容。比如有 10 個應用使用到了 MySQL ,但是其中有9個使用一套 MySQL 叢集,另外一個應用單獨使用一套獨立的 MySQL,這時可以單獨給這個應用定義一個差異化的 Values-myapp.yaml 來覆蓋 values-global.yaml 中的 MySQL 欄位即可。如

global.mysql.host(port,user,passwd)
例如 myapp-v1.23.6.tgz Chart 安裝命令

helm install -n ns1  myapp  -f values-global.yaml -f values-myapp.yaml ./myapp-v1.23.6.tgz

安裝時檔案的優先順序順序Chart 中預設的 values.yaml < values-global.yaml < values-myapp.yaml

安裝和依賴的管理

在單個 Helm Chart 安裝時可以使用 helm install 的方式安裝,但是如果 Chart 數量非常多,而且有順序依賴時手動安裝並不合適,這時推薦編寫一個自動化的工具來管理和安裝,可以是 shell 指令碼或者安裝部署平臺。

輕舟部署使用的 Sail 系統就是一套自研的私有化交付系統,它能夠提供環境的部署規劃、配置的渲染、安裝邏輯的處理、部署任務的執行以及環境資訊的統一管理等功能。

Helm 升級應用

軟體交付無論是早期的自動化交付還是當今的 Helm 雲原生應用交付,帶有結構化資料的應用升級都不是一件容易的事情。經常會因為升級時涉及到表欄位的更新增大了升級的風險。

在雲原生應用交付場景下,Kubernetes 資原始檔宣告式支援,一般不需要特殊處理,Kubernetes 的滾動更新與 Helm 的差異內容更新可以很好的解決。

但對於 SQL 的處理,由於涉及到業務本身的邏輯,Helm 作為工具也是無能為力。但 Helm 為我們提供了 Hook 的功能,可以讓我在安裝或升級的某個階段中插入一定的任務。對於這個任務可以由業務方來決定如何處理 SQL。

對於 SQL 的處理一種思路如下:

SQL檔案按照如下規則定義邏輯,Job 使用 pre-upgrade hook 作為升級依據:

  • 備份待升級的資料庫
  • 獲取環境執行中 Release 資訊中的 Chart 版本(外部工具獲取)
  • 使用 .Chart.appVersion 表示目標版本
  • 獲取環境 Release 版本和目標 Chart 版本的缺少版本
  • 判斷是否滿足升級相容性
  • 按照版本依次執行 SQL 匯入

    SQL 維護方法

  • 維護初始的全量SQL檔案,如果大於1M就拆分成多個 SQL 檔案
  • 每個版本的增量都作為獨立的 SQL 檔案,SQL 檔案規範命名和版本規範保持一致。如 v1.1.0.sql/v1.1.1.sql/v1.1.2.sql
  • 使用 ConfigMap 來掛載一個大版本的全量和增量 SQL 到 Job 容器的固定目錄 (如:/data/upgrade/sql/)

那麼在升級時就可以通過如下命令來自動升級到目標的版本

$ helm upgrade -n ns1 -f values-global.yaml -f values-myapp.yaml   -set release.chartVersion=v1.23.1 myapp ./myapp-v1.23.7.tgz

環境管理

在基於 Helm Chart 的雲原生應用交付的模式下,業務環境的定義可以簡單理解為就是 Chart列表和部署時的 Values.yaml 檔案。

按照規範定義的 Chart 列表能夠說明環境中部署的產品和元件都有哪些以及使用的版本是什麼。

Values.yaml 中儲存了當前環境中所有的差異性配置,結合 Chart 中預設的配置,就可以還原該環境執行的服務所有的配置資訊。

在私有化場景下,環境資訊維護尤為重要。在無法實時訪問客戶環境時,部署時維護的 Chart 列表和 Values 檔案能夠幫助售後快速的定位和解決問題,在進行 bug 修復或版本升級時也能快速的輸出升級材料。

基於 Helm 實踐的效果與收益

網易數帆輕舟使用 Helm 的現狀

由於早期 Helm3 還未釋出前,輕舟私有化交付是基於 Ansible 的方式來交付的,在越來越多的專案交付起來後,場景的差異也越來越多,相容適配的成本也越來越高。

在 Helm3 釋出後,輕舟所有的服務全部進行 Helm 化的改造,以當前的狀態和之前相比有很大的進步:

  • 單個應用版本釋出週期:6個月 ==> 1個月
  • 場景化適配 :無法預測的多種 OS 系統適配 ==> Docker 映象單次x86/ARM 適配即可
  • 專案交付效率:平均 2周/套 ==> 平均 2~3天/套
  • 交付質量:平均每套環境交付問題數 大於10個 ==> 小於3個

交付的產品能力涵蓋雲原生的容器雲、微服務、服務網格、CICD、API 閘道器、分散式事務、APM 以及 PaaS 中介軟體等產品。

基於這套私有化交付工程,支援了公司內外大量的私有化客戶專案,保障了專案的順利交付。

總結

商業私有化交付時客戶環境基礎設施種類繁多、場景複雜,基於容器和 Kubernetes 能極大的降低場景適配和後期運維的工作量。

非線上場景下 Helm 是當前雲原生應用的打包和交付的最佳選擇之一。

優秀的 Helm Chart 實踐經驗需要案例積累,並能夠傳承,推薦基於程式碼的方式傳承經驗。

作者簡介:趙文宇,網易數帆輕舟交付解決方案專家。負責網易數帆輕舟專案交付和解決方案相關的工作,從0到1構建了輕舟私有化交付體系,給客戶提供從專案規劃到交付落地的技術支撐。對雲原生場景下元件高可用方案與應用打包交付有著豐富經驗,對輕舟生態技術體系有著深入的理解,熟悉雲原生場景下軟體私有化交付模式。

相關文章