基于 KubeVela 的 GitOps 交付
作者|董天欣(霧霧)
審核&校對:溪洋、海珠
編輯&排版:雯燕
KubeVela 是一個簡單、易用、且高可擴展的云原生應用管理和交付平臺,能讓開發人員方便快捷地在 Kubernetes 上定義與交付現代微服務應用,無需了解任何 Kubernetes 基礎設施相關的細節。
KubeVela 背后的 OAM 模型天然解決了應用構建過程中對復雜資源的組合、編排等管理問題,同時也將后期的運維策略模型化,這意味著 KubeVela 可以結合 GitOps 管理復雜大規模應用,收斂由于團隊與系統規模增長導致的系統復雜度問題。
什么是 GitOps
它的核心思想是將應用系統所需的基礎架構和應用配置聲明性描述存放在Git倉庫中,并配合一個自動化流程,使每次倉庫被更新后,自動化過程都能逐漸將環境更新到最新配置。
這樣的方式允許開發人員通過直接更改 Git 倉庫中的代碼和配置來自動部署應用,使用 GitOps 的方式可以為應用研發帶來諸多價值,例如:
? 提高生產效率。通過自動的持續部署能夠加快平均部署時間,增加開發效率。
? 降低開發人員部署的門檻。通過推送代碼而非容器配置,開發人員可以不需要了解 Kubernetes 的內部實現,便可以輕易部署。
? 使變更記錄可追蹤。通過 Git 來管理集群,可以使每一次更改都可追蹤,加強了審計跟蹤。
? 可通過 Git 的回滾/分支功能來恢復集群。
KubeVela 與 GitOps
KubeVela 作為一個聲明式的應用交付控制平面,天然支持以 GitOps 的方式來使用,并使用戶更明顯地感受到由 GitOps 帶來的益處,和端到端的應用交付與管理體驗,包括:
? 應用交付工作流(CD 流水線):即:KubeVela 支持在 GitOps 模式中描述過程式的應用交付,而不只是簡單的聲明終態;
? 處理部署過程中的各種依賴關系和拓撲結構;
? 在現有各種 GitOps 工具的語義之上提供統一的上層抽象,簡化應用交付與管理過程;
? 統一進行云服務的聲明、部署和服務綁定;
? 提供開箱即用的交付策略(金絲雀、藍綠發布等);
? 提供開箱即用的混合云/多云部署策略(放置規則、集群過濾規則等);
? 在多環境交付中提供 Kustomize 風格的 Patch 來描述部署差異,而無需學習任何 Kustomize 本身的細節;
? ……
在本文中,我們主要講解直接使用 KubeVela 在 GitOps 模式下進行交付的步驟。
GitOps 工作流
GitOps 工作流分為 CI 和 CD 兩個部分:
? CI(Continuous Integration):持續集成對業務應用進行代碼構建、構建鏡像并推送至鏡像倉庫。目前有許多成熟的 CI 工具,如開源項目常用的 GitHub Action、Travis 等,以及企業中常用的 Jenkins、Tekton 等。在本文中,我們使用 GitHub Action 來完成 CI 這一步,當然你也可以使用別的 CI 工具來代替,KubeVela 圍繞 GitOps 可以對接任意工具下的 CI 流程。
? CD(Continuous Delivery):持續部署會自動更新集群中的配置,如將鏡像倉庫中的最新鏡像更新到集群中。目前主要有兩種方案的 CD:
1)Push-Based:Push 模式的 CD 主要是通過配置 CI 流水線來完成的,這種方式需要將集群的訪問秘鑰共享給 CI,從而使得 CI 流水線能夠通過命令將更改推送到集群中,可以參考我們之前發表的博客:使用 Jenkins + KubeVela 完成應用的持續交付(詳見文末相關鏈接)。
2)Pull-Based:Pull 模式的 CD 會在集群中監聽倉庫(代碼倉庫或者配置倉庫)的變化,并且將這些變化同步到集群中。與 Push 模式相比,Pull-Based 由集群主動拉取更新,從而避免了秘鑰暴露的問題。這也是本文介紹的核心內容。
交付的面向人員有以下兩種,我們將分別介紹:
面向平臺管理員/運維人員的交付
如圖所示,對于平臺管理員/運維人員而言,他們并不需要關心應用的代碼,所以只需要準備一個 Git 配置倉庫并部署 KubeVela 配置文件,后續對于應用及基礎設施的配置變動,便可通過直接更新 Git 配置倉庫來完成,使得每一次配置變更可追蹤。
準備配置倉庫
具體的配置可參考 示例倉庫 1(詳見文末相關鏈接)。
在本例中,我們將部署一個 MySQL 數據庫軟件作為項目的基礎設施,同時部署一個業務應用,使用這個數據庫。配置倉庫的目錄結構如下:
? clusters/ 中包含集群中的 KubeVela GitOps 配置,用戶需要將 clusters/ 中的文件手動部署到集群中。這個是一次性的管控操作,執行完成后,KubeVela 便能自動監聽配置倉庫中的文件變動且自動更新集群中的配置。其中,clusters/apps.yaml 將監聽 apps/ 下所有應用的變化,clusters/infra.yaml 將監聽 infrastructure/ 下所有基礎設施的變化。
? apps/ 目錄中包含業務應用的所有配置,在本例中為一個使用數據庫的業務應用。
? infrastructure/ 中包含一些基礎設施相關的配置和策略,在本例中為 MySQL 數據庫。
KubeVela 建議使用如上的目錄結構管理你的 GitOps 倉庫。clusters/ 中存放相關的 KubeVela GitOps 配置并需要被手動部署到集群中,apps/ 和 infrastructure/ 中分別存放你的應用和基礎設施配置。通過把應用和基礎配置分開,能夠更為合理的管理你的部署環境,隔離由應用變動帶來的影響。
clusters/ 目錄
首先,我們來看下 clusters 目錄,這也是 KubeVela 對接 GitOps 的初始化操作配置目錄。
以 clusters/infra.yaml 為例:
apiVersion: core.oam.dev/v1beta1 kind: Application metadata:name: infra spec:components:- name: database-configtype: kustomizeproperties:repoType: git# 將此處替換成你需要監聽的 git 配置倉庫地址url: https://github.com/FogDong/KubeVela-GitOps-Infra-Demo# 如果是私有倉庫,還需要關聯 git secret# secretRef: git-secret# 自動拉取配置的時間間隔,由于基礎設施的變動性較小,此處設置為十分鐘pullInterval: 10mgit:# 監聽變動的分支branch: main# 監聽變動的路徑,指向倉庫中 infrastructure 目錄下的文件path: ./infrastructureapps.yaml 與 infra.yaml 幾乎保持一致,只不過監聽的文件目錄有所區別。在 apps.yaml 中,properties.path 的值將改為 ./apps,表明監聽 apps/ 目錄下的文件變動。
cluster 文件夾中的 GitOps 管控配置文件需要在初始化的時候一次性手動部署到集群中,在此之后 KubeVela 將自動監聽 apps/ 以及 infrastructure/ 目錄下的配置文件并定期更新同步。
apps/ 目錄
apps/ 目錄中存放著應用配置文件,這是一個配置了數據庫信息以及 Ingress 的簡單應用。該應用將連接到一個 MySQL 數據庫,并簡單地啟動服務。在默認的服務路徑下,會顯示當前版本號。在 /db 路徑下,會列出當前數據庫中的信息。
apiVersion: core.oam.dev/v1beta1 kind: Application metadata:name: my-appnamespace: default spec:components:- name: my-servertype: webserviceproperties:image: ghcr.io/fogdong/test-fog:master-cba5605f-1632714412port: 8088env:- name: DB_HOSTvalue: mysql-cluster-mysql.default.svc.cluster.local:3306- name: DB_PASSWORDvalueFrom:secretKeyRef:name: mysql-secretkey: ROOT_PASSWORDtraits:- type: ingressproperties:domain: testsvc.example.comhttp:/: 8088這是一個使用了 KubeVela 內置組件類型 webservice 的應用,該應用綁定了 Ingress 運維特征。通過在應用中聲明運維能力的方式,只需一個文件,便能將底層的 Deployment、Service、Ingress 集合起來,從而更為便捷地管理應用。
infrastructure/ 目錄
infrastructure/ 目錄下存放一些基礎設施的配置。此處我們使用 mysql controller(詳見文末相關鏈接)來部署了一個 MySQL 集群。
注意,請確保你的集群中有一個 secret,并通過 ROOT_PASSWORD 聲明了 MySQL 密碼。
apiVersion: core.oam.dev/v1beta1 kind: Application metadata:name: mysqlnamespace: default spec:components:- name: mysql-controllertype: helmproperties:repoType: helmurl: https://presslabs.github.io/chartschart: mysql-operatorversion: "0.4.0"- name: mysql-clustertype: rawdependsOn:- mysql-controllerproperties:apiVersion: mysql.presslabs.org/v1alpha1kind: MysqlClustermetadata:name: mysql-clusterspec:replicas: 1# 關聯 secret 名稱secretName: mysql-secret在這個 MySQL 應用中,我們使用了 KubeVela 工作流的能力。工作流分為兩個步驟,第一個步驟會去部署 MySQL 的 controller。當 controller 部署成功且正確運行后,第二個步驟將開始部署 MySQL 集群。
部署 clusters/ 目錄下的文件
配置完以上文件并存放到 Git 配置倉庫后,我們需要在集群中手動部署 clusters/ 目錄下的 KubeVela GitOps 配置文件。
首先,在集群中部署 clusters/infra.yaml。可以看到它自動在集群中拉起了 infrastructure/ 目錄下的 MySQL 部署文件:
kubectl apply -f clusters/infra.yaml $ vela ls APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME infra database-config kustomize running healthy 2021-09-26 20:48:09 +0800 CST mysql mysql-controller helm running healthy 2021-09-26 20:48:11 +0800 CST └─ mysql-cluster raw running healthy 2021-09-26 20:48:11 +0800 CST接著,在集群中部署
clusters/apps.yaml,可以看到它自動拉起了 apps/ 目錄下的應用部署文件:
kubectl apply -f clusters/apps.yaml APP COMPONENT TYPE TRAITS PHASE HEALTHY STATUS CREATED-TIME apps apps kustomize running healthy 2021-09-27 16:55:53 +0800 CST infra database-config kustomize running healthy 2021-09-26 20:48:09 +0800 CST my-app my-server webservice ingress running healthy 2021-09-27 16:55:55 +0800 CST mysql mysql-controller helm running healthy 2021-09-26 20:48:11 +0800 CST └─ mysql-cluster raw running healthy 2021-09-26 20:48:11 +0800 CST至此,我們通過部署 KubeVela GitOps 配置文件,自動在集群中拉起了應用及數據庫。
通過 curl 應用的 Ingress,可以看到目前的版本是 0.1.5,并且成功地連接到了數據庫:
$ kubectl get ingress NAME CLASS HOSTS ADDRESS PORTS AGE my-server <none> testsvc.example.com <ingress-ip> 80 162m $ curl -H "Host:testsvc.example.com" http://<ingress-ip> Version: 0.1.5 $ curl -H "Host:testsvc.example.com" http://<ingress-ip>/db User: KubeVela Description: It's a test user修改配置
完成了首次部署后,我們可以通過修改配置倉庫中的配置,來完成集群中應用的配置更新。
修改應用 Ingress 的 Domain:
...traits:- type: ingressproperties:domain: kubevela.example.comhttp:/: 8089經過一段時間后,重新查看集群中的 Ingress:
NAME CLASS HOSTS ADDRESS PORTS AGE my-server <none> kubevela.example.com <ingress-ip> 80 162m可以看到,Ingress 的 Host 地址已被成功更新。
通過這種方式,我們可以方便地通過更新 Git 配置倉庫中的文件,從而自動化更新集群中的配置。
面向終端開發者的交付
對于終端開發者而言,在 KubeVela Git 配置倉庫以外,還需要準備一個應用代碼倉庫。如圖所示,在用戶更新了應用代碼倉庫中的代碼后,需要配置一個 CI 來自動構建鏡像并推送至鏡像倉庫中。KubeVela 會監聽鏡像倉庫中的最新鏡像,并自動更新配置倉庫中的鏡像配置,最后再更新集群中的應用配置。使用戶可以達成在更新代碼后,集群中的配置也自動更新的效果。
準備代碼倉庫
準備一個代碼倉庫,里面包含一些源代碼以及對應的 Dockerfile。
這些代碼將連接到一個 MySQL 數據庫,并簡單地啟動服務。在默認的服務路徑下,會顯示當前版本號。在 /db 路徑下,會列出當前數據庫中的信息。
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {_, _ = fmt.Fprintf(w, "Version: %s\n", VERSION)})http.HandleFunc("/db", func(w http.ResponseWriter, r *http.Request) {rows, err := db.Query("select * from userinfo;")if err != nil {_, _ = fmt.Fprintf(w, "Error: %v\n", err)}for rows.Next() {var username stringvar desc stringerr = rows.Scan(&username, &desc)if err != nil {_, _ = fmt.Fprintf(w, "Scan Error: %v\n", err)}_, _ = fmt.Fprintf(w, "User: %s \nDescription: %s\n\n", username, desc)}})if err := http.ListenAndServe(":8088", nil); err != nil {panic(err.Error())}我們希望用戶改動代碼進行提交后,自動構建出最新的鏡像并推送到鏡像倉庫。這一步 CI 可以通過集成 GitHub Actions、Jenkins 或者其他 CI 工具來實現。在本例中,我們通過借助 GitHub Actions 來完成持續集成。具體的代碼文件及配置可參考 示例倉庫 2(詳見文末相關鏈接)。
配置秘鑰信息
在新的鏡像推送到鏡像倉庫后,KubeVela 會識別到新的鏡像,并更新倉庫及集群中的 Application 配置文件。因此,我們需要一個含有 Git 信息的 Secret,使 KubeVela 向 Git 倉庫進行提交。部署如下文件,將其中的用戶名和密碼替換成你的 Git 用戶名及密碼(或 Token):
apiVersion: v1 kind: Secret metadata:name: git-secret type: kubernetes.io/basic-auth stringData:username: <your username>password: <your password>準備配置倉庫
配置倉庫與之前面向運維人員的配置大同小異,只需要加上與鏡像倉庫相關的配置即可。具體配置請參考 示例倉庫 1(詳見文末相關鏈接)。
修改 clusters/ 中的 apps.yaml,該 GitOps 配置會監聽倉庫中 apps/ 下的應用文件變動以及鏡像倉庫中的鏡像更新:
...imageRepository:# 鏡像地址image: <your image># 如果這是一個私有的鏡像倉庫,可以通過 `kubectl create secret docker-registry` 創建對應的鏡像秘鑰并相關聯# secretRef: imagesecretfilterTags:# 可對鏡像 tag 進行過濾pattern: '^master-[a-f0-9]+-(?P<ts>[0-9]+)'extract: '$ts'# 通過 policy 篩選出最新的鏡像 Tag 并用于更新policy:numerical:order: asc# 追加提交信息commitMessage: "Image: {{range .Updated.Images}}{{println .}}{{end}}"修改 apps/my-app.yaml 中的 image 字段,在后面加上 # {"$imagepolicy": “default:apps”} 的注釋。KubeVela 會通過該注釋去更新對應的鏡像字段。default:apps 是上面 GitOps 配置對應的命名空間和名稱。
spec:components:- name: my-servertype: webserviceproperties:image: ghcr.io/fogdong/test-fog:master-cba5605f-1632714412 # {"$imagepolicy": "default:apps"}將 clusters/ 中包含鏡像倉庫配置的文件更新到集群中后,我們便可以通過修改代碼來完成應用的更新。
修改代碼
將代碼文件中的 Version 改為 0.1.6,并修改數據庫中的數據:
const VERSION = "0.1.6" ... func InsertInitData(db *sql.DB) {stmt, err := db.Prepare(insertInitData)if err != nil {panic(err)}defer stmt.Close()_, err = stmt.Exec("KubeVela2", "It's another test user")if err != nil {panic(err)} }提交該改動至代碼倉庫,可以看到,我們配置的 CI 流水線開始構建鏡像并推送至鏡像倉庫。
而 KubeVela 會通過監聽鏡像倉庫,根據最新的鏡像 Tag 來更新配置倉庫中 apps/ 下的應用 my-app。
此時,可以看到配置倉庫中有一條來自 kubevelabot 的提交,提交信息均帶有 Update image automatically. 前綴。你也可以通過 {{range .Updated.Images}}{{println .}}{{end}} 在 commitMessage 字段中追加你所需要的信息。
值得注意的是,如果你希望將代碼和配置放在同一個倉庫,需要過濾掉來自 kubevelabot 的提交來防止流水線的重復構建。可以在 CI 中通過如下配置過濾:
jobs: publish:if: "!contains(github.event.head_commit.message, 'Update image automatically')"重新查看集群中的應用,可以看到經過一段時間后,應用 my-app 的鏡像已經被更新。
KubeVela 會通過你配置的 interval 時間間隔,來每隔一段時間分別從配置倉庫及鏡像倉庫中獲取最新信息:
? 當 Git 倉庫中的配置文件被更新時,KubeVela 將根據最新的配置更新集群中的應用。
? 當鏡像倉庫中多了新的 Tag 時,KubeVela 將根據你配置的 policy 規則,篩選出最新的鏡像 Tag,并更新到 Git 倉庫中。而當代碼倉庫中的文件被更新后,KubeVela 將重復第一步,更新集群中的文件,從而達到了自動部署的效果。
通過 curl 對應的 Ingress 查看當前版本和數據庫信息:
$ kubectl get ingress NAME CLASS HOSTS ADDRESS PORTS AGE my-server <none> kubevela.example.com <ingress-ip> 80 162m $ curl -H "Host:kubevela.example.com" http://<ingress-ip> Version: 0.1.6 $ curl -H "Host:kubevela.example.com" http://<ingress-ip>/db User: KubeVela Description: It's a test user User: KubeVela2 Description: It's another test user版本已被成功更新!至此,我們完成了從變更代碼,到自動部署至集群的全部操作。
總結
在運維側,如若需要更新基礎設施(如數據庫)的配置,或是應用的配置項,只需要修改配置倉庫中的文件,KubeVela 將自動把配置同步到集群中,簡化了部署流程。
在研發側,用戶修改代碼倉庫中的代碼后,KubeVela 將自動更新配置倉庫中的鏡像。從而進行應用的版本更新。
通過與 GitOps 的結合,KubeVela 加速了應用從開發到部署的整個流程。
戳原文,查看 KubeVela 項目官方主頁與文檔!!
相關鏈接
1)使用 Jenkins + KubeVela 完成應用的持續交付:
https://kubevela.io/zh/blog/2021/09/02/kubevela-jenkins-cicd
2)示例倉庫 1:
https://github.com/oam-dev/samples/tree/master/9.GitOps_Demo/for-SREs
3)mysql controller:
https://github.com/bitpoke/mysql-operator
4)示例倉庫 2:
https://github.com/oam-dev/samples/tree/master/9.GitOps_Demo/for-developers/app-code
了解更多相關信息,請釘釘掃描下方二維碼或搜索釘釘群號(35922870)加入阿里云原生資訊交流群!獲取更多相關資訊!
總結
以上是生活随笔為你收集整理的基于 KubeVela 的 GitOps 交付的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云知声 Atlas 超算平台: 基于 F
- 下一篇: 加速SaaS规模化演进,餐道基于K8s的