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