背景
Kubesphere 3.3.0
集成了 ArgoCD
,但與筆者目前使用的 K8S 版本不兼容。再者,目前 Kubesphere
中持續集成和流水線打通還是不太友好,也缺少文檔說明(可能是筆者沒有找到)。
目前遇到最主要的問題就是流水線制作完成的鏡像如何更新到 Git 倉庫,然后觸發 Application 的同步。
基于上述問題,目前有兩種方法:
ArgoCD 官方的argocd-image-updater[1](根據鏡像倉庫的鏡像 Tag 變化,完成服務鏡像更新)
Kubesphere 提供了一個 ks app update 工具[2](支持 Kubesphere v3.3.0 中 Application,不支持原生 ArgoCD Application)
為此筆者基于 Kubesphere v3.1.1 的流水線,根據筆者的場景,實現了 GitOps 的服務發布流程,作此記錄,暫且稱之為最佳實踐。
目標
基于 Kubesphere 的流水線:
自動創建服務部署清單
自動創建服務 pipeline
提交到服務部署清單倉庫
流水線風格統一
通過服務流水線發布版本之后在一段時間內可以回滾
實現 GitOps 方式管理服務部署清單和流水線清單,做到版本控制
設計


GitLab 項目規劃
服務源代碼和部署清單倉庫分離,方便做權限管理;
模板倉庫 argocd-gitops-templates 是單獨的 GitLab 倉庫;
每個 DevOps 項目對應一個 GitLab 倉庫。(倉庫名稱為
argocd-gitops-{devops 項目名}
);所有 GitLab 倉庫都放在同一個 GitLab Group 下;
每個倉庫中包含了服務不同環境的清單,如:uat 和 prod;
一個服務包含一個 pipeline Application 和服務部署清單 Application。服務部署清單通過 Application CR 管理;服務 pipeline 清單通過 pipeline Application CR 管理。
模板倉庫目錄結構
argocd-gitops-templates
項目存儲了生成服務流水線和部署清單、argocd Application 的模板。
.
|--?app-manifests-templates
|???|--?go
|???|???|--?base
|???|???|???|--?deployment.yaml
|???|???|???|--?kustomization.yaml
|???|???|???`--?service.yaml
|???|???|--?canary
|???|???|???|--?deployment_overlay.yaml
|???|???|???|--?kustomization.yaml
|???|???|???`--?service_overlay.yaml
|???|???|--?ga
|???|???|???`--?kustomization.yaml
|???|???|--?kustomization.yaml
|???|
|--?application-templates
|???|--?README.md
|???|--?application-pipeline.yaml
|???`--?application.yaml
|--?pipeline-templates
|???`--?pipeline
|???????`--?ks-pipeline-jenkinsfile.yaml
|--?top-pipeline
|???|--?README.md
|???|--?dev
|???|???|--?application.yaml
|???|???|--?only-test-deploy-by-argo-top-pipeline.jenkinsfile
|???|???`--?pipeline
|???|???????`--?deploy-by-argo-top-pipeline.yaml
|???|--?prod
|???|???|--?application.yaml
|???|???|--?only-test-deploy-by-argo-top-pipeline.jenkinsfile
|???|???`--?pipeline
|???|???????`--?deploy-by-argo-top-pipeline.yaml
app-manifests-templates:包含 go、java、nodejs 的服務部署清單模板,使用 overlay 的方式 和 base 文件夾中的配置進行合并(利用 kustomize 工具實現),生成最終的部署清單。
application-templates:包含服務 argocd Application,服務 pipeline argocd Application 清單模板。
top-pipeline:包含 dev、prod K8S 集群中的 top pipeline 清單和管理它的 argocd Application。
pipeline-templates:包含了服務 pipeline 模板,整體用
Groovy
語法實現
注意:app-manifests-templates、pipeline-templates、application-templates,在發布 GitOps 服務時,執行 Top pipeline 生成服務 pipeline,會自動拷貝,并根據運行 Top pipeline 時輸入的參數生成清單,到服務對應的 GitLab 倉庫中。
服務部署清單倉庫目錄結構
例如:devops1 項目的 GitLab 部署清單倉庫目錄結構如下:
.
|--?README.md
`--?appsmanifests|--?kubeinfo-svc1|???|--?prod|???|???|--?application-pipeline.yaml|???|???|--?application.yaml|???|???`--?manifests|???|???????|--?base|???|???????|???|--?deployment.yaml|???|???????|???|--?kustomization.yaml|???|???????|???`--?service.yaml|???|???????|--?canary|???|???????|???|--?deployment_overlay.yaml|???|???????|???|--?kustomization.yaml|???|???????|???`--?service_overlay.yaml|???|???????|--?ga|???|???????|???|--?deployment_overlay.yaml|???|???????|???`--?kustomization.yaml|???|???????|--?kustomization.yaml|???|???????|--?pipeline|???|???????|???`--?ks-pipeline-jenkinsfile.yaml|???`--?uat|???????|--?application-pipeline.yaml|???????|--?application.yaml|???????`--?manifests|???????????|--?base|???????????|???|--?deployment.yaml|???????????|???|--?kustomization.yaml|???????????|???`--?service.yaml|???????????|--?canary|???????????|???|--?deployment_overlay.yaml|???????????|???|--?kustomization.yaml|???????????|???`--?service_overlay.yaml|???????????|--?ga|???????????|???|--?deployment_overlay.yaml|???????????|???`--?kustomization.yaml|???????????|--?kustomization.yaml|???????????|--?pipeline|???????????|???`--?ks-pipeline-jenkinsfile.yaml
服務清單在
appsmanifests/{服務名}
文件夾下。每個服務根據環境(用 top pipeline 創建服務流水線的時候需要選擇)又劃分為不同的文件夾。
每個環境文件夾下有兩個 Application 清單,分別去管理 manifests 中的部署清單和 pipeline 清單。
canary、ga 文件夾根據 STAGE_LEVEL(用 top pipeline 創建服務流水線的時候需要選擇)的值會自動在 kustomization.yaml 中進行管理。
注意:目前只提供最基本的部署清單:如果需要 Configmaps、Secrets、Ingress、增加環境變量、label 等,需要手動增加或修改。具體可以參考下面的實踐說明文檔:
Top Pipeline 流程
Top Pipeline 用來自動化創建 GitOps 倉庫,生成服務部署清單、pipeline CR 清單、Application CR 清單,將清單提交到 GitLab 倉庫,并將 Application 創建到 K8S 集群中。整體用 Groovy
語法實現。

黃色部分為需要人為干預的,綠色為自動執行的。
每個服務的發布,流水線都隸屬于一個 DevOps 項目下,如果這個 DevOps 項目不存在,則需要手動新建。
如果存在,則需要手動點擊運行 top pipeline。
輸入服務配置參數,點擊確定運行。
持久化參數信息:流水線運行時會將所填參數更新到 Pipeline CR 的 parameters 中(避免流水線執行失敗后,重新運行時,需要重填參數);
流水線會自動獲取需要選擇的動態參數,需要人為選擇。

檢查 GitLab 中是否存在該 DevOps 項目的倉庫,不存在會自動新建倉庫;
自動克隆 模板倉庫,生成服務部署清單、pipeline CR 清單、兩個 Application CR 清單,提交到 GitLab
自動執行
kubectl apply -f {兩個 application yaml}
創建 argocd Application CR;
服務 Pipeline 發布版本流程

細節解析
Application 怎么創建?
通過 kubectl 命令行直接創建到 ArgoCD 所在 K8S 集群。
每個服務對應幾個 Application?
一個服務對應 2 個 Application,一個管理 pipeline CR,另一個管理 deployment 等部署清單。
流水線上編譯的鏡像 Tag 如何提交到 Git?
用 Git 命令行實現。
一個 DevOps 項目下的多個 Pipeline 同時運行,一定程度可能會提交失敗。比如:B 克隆代碼到本地,此時 A 提交一次,B 提交時就失敗,需要重新 pull 后再提交。所以需要加重試機制,失敗重新 pull。
容易提交沖突,所以需要先 pull 再 push,并增加失敗之后重試
CI 更新鏡像 Tag 到 GitLab 后,如何觸發 CD 同步?
開啟自動同步后,默認是 3~4 分鐘 sync,時間較長。如何及時觸發 CD 同步?
集成 argocd 命令行工具到 Agent 鏡像中,新建一個 gitops 賬號,并通過 RBAC 控制該賬號的權限。
執行 argocd sync 命令也可能失敗,需要加失敗之后重試
具體請參看:ArgoCD 用戶管理、RBAC 控制、命令行登錄、App 同步[3]
Agent 鏡像制作
kubesphere/builder-base:v3.2.2 鏡像中包含了 kustomize 和 Git,更新鏡像 Tag 時,用 base-3.2.2 作為 Pipeline Agent。
并將 argocd 命令行集成到上面鏡像中,生成新的鏡像:harbor.kubeinfo.cn/library/kubesphere/builder-base:v3.2.2-argocd
如何回滾
審核階段,如果點擊“終止”,將回滾上一個階段的鏡像版本。
正式環境發布之后(即流水線最后一步),可以點擊“終止”回滾到上一個鏡像版本(一般在新版本測試不通過的情況下點擊“終止”),如果 30 分鐘內沒有點擊,或者點了繼續,本次發布流程將結束。
回滾的時候,通過 git revert 命令回退某一次提交。
跨集群發布服務
沒有啟用 DevOps 系統的 K8S 集群中,不存在 pipeline CRD。
所以 pipeline 用單獨的 Application 管理,其中的 destination cluster 只能為 ArgoCD 所在的集群。
只要加入到了 argocd 中的 k8s 集群(即使沒有被 Kubesphere 納管),都可以走這一套 GitOps 流程,將服務部署到這個 k8s 集群中。
清單管理
目前采用 Kustomize,kustomize 利用 overlay 機制覆蓋某些配置,雖然在可定制化方面不如 helm,如:不支持模板語法和變量,但 helm 對于筆者來說太重。目前的場景采用 Kustomize,基本可以滿足需求。
kustomize 命令行用于更新 kustomization.yaml 中鏡像 Tag,以及校驗語法是否正確,避免語法不正確提交。
kustomize?edit?set?image?kubeinfo-svc=harbor-kubeinfo.cn/argocd/kubeinfo-svc:${DOCKER_TAG}
kustomize 已經在上面的 Agent 鏡像中包含。
實例數如何適配 HPA 自動伸縮
注釋掉 deployment 中的spec.replicas
,argocd 將不管理 deployment 的實例數。
在 Kubesphere 中修改了清單,argocd 會還原嗎?
argocd Application 中有個 selfHeal
配置,表示:指定當僅在目標 Kubernetes 集群中更改資源且未檢測到 git 更改時(默認為 false) ,是否應執行部分應用程序同步。
所以當 K8S 資源對象被修改時,Git 中清單沒變化的情況下,不需要自愈修復,argocd 不會做還原;
但下一次流水線發布版本時,Git 上的清單會發生變化,此時 K8S 資源會被還原。
憑證統一
用 top pipeline 生成的流水線,有統一的格式,所以憑證必須統一。
DevOps 項目有很多,維護憑證成本很高。如何統一、自動化創建管理?如:harbor、argocd 的 gitops 賬戶、GitLab 的賬號憑證。
通過 kubed + kyverno 實現:在 kubesphere-devops-system 下創建的源 secret,將會自動同步到所有 devops project 下。
參考:如何跨命名空間共享 Secret 和 ConfigMap?Kubesphere 憑證如何同步?[4]
展望
引入了 GitOps,發現要做的東西更多了,但也確實帶來很多好處。本文旨在記錄分享筆者的 GitOps 落地經驗,有些方案細節可能只適用于筆者當前的場景,筆者也處于摸索階段。歡迎大佬們拍磚。
同時也期待 Kubesphere
服務的發布可以和流水線一條龍創建,將 GitOps
做的更易用,而不用在項目
和DevOps項目
之間切換;同時將灰度發布集成到流水線、可以回滾。
參考資料
[1]
argocd-image-updater: https://argocd-image-updater.readthedocs.io/en/stable/
[2]ks app update 工具: https://github.com/kubesphere-sigs/ks/blob/master/docs/app.md
[3]ArgoCD 用戶管理、RBAC 控制、命令行登錄、App 同步: https://blog.csdn.net/ll837448792/article/details/125899955
[4]如何跨命名空間共享 Secret 和 ConfigMap?Kubesphere 憑證如何同步?: https://liabio.blog.csdn.net/article/details/124973387
?點個在看集群永保穩定👇