基于 Kubernetes 的發布系統設計
背景介紹
在我們之前將服務遷移部署到 Kubernetes 集群的工作中,主要是通過描述 .gitlab-ci.yml 文件來實現 CI/CD 的流程。通過這個流程,我們可以完成代碼更新之后的單元測試、lint、編譯、鏡像打包以及發布等工作。
但是,當服務部署到 Kubernetes 集群之后,每個服務都需要在 GitLab 倉庫維護一份 deployment 模板來進行服務新版本的發布上線,每次的 deploy 過程是將一些發布參數結合 deployment 模板生成發布所需的deployment.yml 文件,然后通過 kubectl 命令發布到 Kubernetes 集群中。但是該種方案存在以下缺點:
- 每個服務各自維護一份 deployment 模板,具有一定的管理復雜度
- 缺少統一的發布歷史記錄管理,不利于問題排查和回溯
- 缺少有效的權限控制,存在一定風險
為了解決以上問題,我們將 CI/CD 的流程發布工作抽取出來,設計了一套基于 Kubernetes 的發布系統來完成服務發布發布工作。
發布系統基本功能
我們設計的發布系統具有以下基本功能:
- 以服務為粒度完成發布功能
- 發布記錄展示
- 每條發布記錄可以查詢發布的詳細過程
- 針對每條發布記錄可以進行快速回滾操作
- 發布結果通知,支持郵件和釘釘進行通知
- 部分服務支持灰度發布
發布流程總覽
發布系統在進行發布操作之前,需要完成前置的 CI 流程,具體操作為:
- 在 GitLab 中有代碼更新時,我們可以設置一定的 CI 規則觸發流水線
- Gitlab-ci 會進行代碼的拉取,并完成單元測試、lint、代碼編譯和鏡像構建等操作
- 完成鏡像構建后,將帶有版本信息的 Docker 鏡像上傳到 Docker Harbor 中
- 在發布系統進行 Docker 鏡像版本信息的錄入
在上述工作準備就緒之后,發布系統可以基于每個服務選擇對應的版本,生成每一次發布需要的 deployment 文件,然后調用 Kubernetes API server 實現服務的滾動升級。
發布過程詳解
基本發布操作
在發布系統中,每一次發布操作都視為一個發布任務,所以需要對某個服務進行升級就需要對這個服務新建一次發布任務,具體需要進行如下操作:
- 選擇需要發布的環境(測試環境或正式環境)
- 根據服務名獲取鏡像列表,并進行版本選取
- 確認發布參數,并填寫發布描述
- 提交信息,開始版本的發布任務
在完成發布任務新建之后,每次的發布任務的信息就可以展示出來,除以上填入的信息之外,還包括發布任務的開始時間,發布時長,操作用戶,發布描述,發布狀態等信息,這樣完成每次發布操作的記錄,用助于故障的排除和問題回溯。
此外,每個發布任務還支持回滾操作,可以在新版本發布存在問題時,進行版本的快速回滾。對于最近一次的發布任務,可以進行重發操作,該功能主要有以下兩個實用場景:
由于外部因素導致發布失敗,在外部因素問題解決后需要重新發布
代碼的配置信息更新后,需要讓 Kubernetes 中的 Pod 更新此配置信息回滾和重發操作本質上還是新建發布任務,是基于每次的發布任務的信息自動地進行了發布參數選擇,更加地快速便捷。
發布 deployment 文件生成
deployment 模板中的參數分為以下兩類:
基礎參數
發布的基礎參數包括 Pod 副本數、健康檢查路徑、組織信息等,可以根據實際情況進行調整,但是調整頻率很低。這些參數通過發布配置進行管理,每一個服務都維護了一份發布配置,存儲在數據庫中,我們可以通過在頁面編輯發布配置進行基礎參數的修改。此外,發布配置里維護了該服務所采用的發布模板信息。
對于基礎參數的調整,相比于新建發布任務具有更高的權限
發布參數
包括服務名、版本號、發布環境、發布方式等。每次發布根據需求進行填寫。這些參數在新建發布任務的時候均會確定。
發布系統每次發布時結合基礎模板和以上參數值生成一份本次發布任務所需要的 deployment 文件,然后通過 kubectl apply 調用 Kubernetes 的 API server 進行對應服務的滾動升級。
deployment 模板管理
在我們的實踐中,服務是具有共性的,針對一類服務抽象出 deployment 發布模板,然后多個服務可以共用一個發布模板,大大減小了管理成本。目前發布采用的 deployment 模板存儲在 GitLab 中,模板的管理與使用方式如下:
- 模板新增通過提交 Merge Request 完成
- GitLab 中的模板文件有新增時,GitLab Pipeline 會被觸發向發布系統中同步 deployment 模板信息
- 模板在發布系統中有記錄,模板 ID 作為唯一標識
- 每個服務在發布配置中對應一個發布模板 ID
- 新建發布任務時,發布系統會根據發布配置中的模板 ID 獲取存對應模板文件的 url,并將內容下載下來
Kubernetes 發布過程跟蹤與結果記錄
由于 Kubernetes 在進行版本更新時,是通過定義聲明式 deployment 文件并進行異步調用的方式實現的。在調用 kubectl apply 之后并無法確定對應的 Pod 是否可以正確地完成滾動更新。所以我們采用命令 kubectl rollout status deployment $deployment_name 來進行發布過程的跟蹤,此處變量 deployment_name 與我們的服務為一一對應的關系。
發布過程跟蹤的信息可以在每條發布任務的詳情中進行查看,此處記錄了 Pod 滾動更新的詳細過程。
發布的 Pod 成功更新時,kubectl rollout status deployment $deployment_name 會成功退出,發布系統會判定發布任務成功。如果,新版本的 Pod 由于某些原因在滾動更新的過程中一直被阻塞住,在超過發布系統中所設置的超時時間后即判定發布任務失敗。
對于發布失敗的任務,目前支持簡單的 Pod 日志查看,主要原理是對發布過程中 status 不為 Running 和 Terminating 的 Pod 進行日志查詢,這樣就可以對發布任務失敗進行問題定位。效果如下:
總結
本文主要介紹了基于 Kubernetes 的發布系統。首先闡述了設計基于 Kubernetes 的發布系統的背景和必要性。然后對發布系統所具備的基本功能進行了介紹。第三部分是本文的主體部分,對發布系統的原理進行了詳細說明,從新建發布任務入手,然后對發布 deployment 文件生成、發布模板管理、發布結果跟蹤與記錄以及灰度發布的實現進行了細節展開。
作者:伍沖斌,VPGAME 運維開發工程師,VPGAME 是集賽事運營、媒體資訊、大數據分析、玩家社群、游戲周邊等為一體的綜合電競服務平臺。