基于Gitlab CI+Argo CD的Gitops實(shí)踐,你學(xué)會了嗎?
項(xiàng)目簡介
項(xiàng)目說明
本項(xiàng)目構(gòu)建了一個(gè)基于GitOps理念的完整CI/CD管道,旨在實(shí)現(xiàn)軟件開發(fā)與運(yùn)維的高度自動化和一致性。通過GitLab、GitLab Runner(部署于Kubernetes)、Maven、Java、SonarQube、Harbor以及Argo CD等工具的緊密協(xié)作,實(shí)現(xiàn)代碼提交后自動進(jìn)行編譯打包、單元測試、代碼掃描、構(gòu)建鏡像、更新資源清單以及滾動更新、藍(lán)綠部署、金絲雀發(fā)布、多集群發(fā)布功能。
CI/CD管道流程
- 代碼提交:開發(fā)人員將Java代碼提交到GitLab倉庫,這一動作將觸發(fā)CI/CD流水線的啟動。
- 編譯與構(gòu)建:GitLab Runner(基于Kubernetes)自動拉取最新的代碼,并使用Maven和Java工具鏈進(jìn)行編譯和構(gòu)建,生成可部署的制品(如Docker鏡像)。
- 單元測試與源碼掃描:執(zhí)行單元測試以驗(yàn)證代碼的功能性,并通過SonarQube進(jìn)行靜態(tài)代碼分析,確保代碼質(zhì)量和安全性。
- 制品上傳:將構(gòu)建好的Docker鏡像推送到Harbor私有鏡像倉庫,作為后續(xù)部署的輸入。
- GitOps部署:Argo CD監(jiān)聽Git倉庫中的基礎(chǔ)設(shè)施和應(yīng)用配置更改,自動將更新應(yīng)用到Kubernetes集群中。這里,Git倉庫成為了基礎(chǔ)設(shè)施和應(yīng)用狀態(tài)的唯一真實(shí)來源,所有的部署和更新都基于Git中的配置進(jìn)行。支持滾動更新、藍(lán)綠部署、金絲雀發(fā)布、多集群多環(huán)境批量發(fā)布等多種部署方式。
- 持續(xù)監(jiān)控與反饋:通過GitLab Runner、Argo CD等工具的exporter暴露的指標(biāo),團(tuán)隊(duì)可以實(shí)時(shí)監(jiān)控CI/CD流水線的狀態(tài)和部署結(jié)果,
Gitlab CD劣勢
- agent權(quán)限過大:通常授予GitLab Runner集群管理員權(quán)限,無法有效通過更有限的權(quán)限來限制訪問。這意味著必須授予對一個(gè)相當(dāng)簡單的功能的完全訪問權(quán)限,這可能會成為一種隱患。
- 部署功能單一:GitLab Runner的部署功能主要依賴kubectl工具執(zhí)行,在Kubernetes集群的深入管理和部署方面,不如專門為此設(shè)計(jì)的工具如Argo CD全面,例如自動同步、健康檢查、回滾、多種發(fā)布方式。
- 審計(jì)與合規(guī)性:Argo CD提供了更加全面的審計(jì)日志,并以git作為唯一來源,除此之外,任何人都不可以對集群進(jìn)行任何更改,也會被 Operator 還原為git倉庫期望狀態(tài)。
GitOps優(yōu)勢
- 強(qiáng)化安全保障:GitOps模式下,部署無需Kubernetes或云平臺憑證,僅通過Git倉庫更新,減少暴露風(fēng)險(xiǎn)。Git的密碼學(xué)支持確保變更的真實(shí)性和來源,加固集群安全。
- 統(tǒng)一真實(shí)來源:Git作為唯一事實(shí)來源,存儲所有應(yīng)用及基礎(chǔ)設(shè)施配置。利用Git的版控、歷史、審計(jì)和回滾等功能,簡化操作,無需額外工具。
- 提升開發(fā)效率:Git的熟悉度促進(jìn)快速迭代,加快開發(fā)與部署速度,加速產(chǎn)品上市,同時(shí)提升系統(tǒng)穩(wěn)定性和可靠性。
- 簡化合規(guī)審計(jì):基礎(chǔ)設(shè)施變更如同軟件項(xiàng)目,通過Git管理,支持Pull Request和Code Review流程,確保合規(guī)與透明。
更多gitops介紹可參考文檔:GitOps-崔亮的博客 (cuiliangblog.cn)
Kustomize對比Helm
Kustomize強(qiáng)調(diào)聲明式管理,配置即代碼。它允許用戶通過層次化的覆蓋和變更來定制Kubernetes資源,而不需要使用模板。
Helm是一個(gè)包管理工具,類似于Linux的apt或yum,旨在簡化Kubernetes應(yīng)用的部署和管理。Helm使用Charts(模板)來定義Kubernetes資源。 以下是兩者的差異對比
特征 | Helm | Kustomize |
模板支持 | √ | × |
覆蓋支持 | × | √ |
打包支持 | √ | × |
驗(yàn)證hooks | √ | × |
回滾支持 | √ | × |
原生 K8s 集成 | × | √ |
聲明性 | √ | √ |
可見性和透明度 | 弱 | 強(qiáng) |
相較而言Kustomize使用起來更簡單,雖然不支持打包與回滾,但我們可以依賴ArgoCD完成這部分功能,更契合GitOps 版本化控制思想。
更多Kustomize資料可參考文檔:kustomize多環(huán)境管理-崔亮的博客 (cuiliangblog.cn)
項(xiàng)目流程圖
圖片
準(zhǔn)備工作
服務(wù)部署
需要部署Gitlab、SonarQube、Harbor、buildkitd、Gitlab Runner服務(wù),具體可參考文檔:gitlab+k8s項(xiàng)目實(shí)戰(zhàn)-崔亮的博客 (cuiliangblog.cn)
部署完成后根據(jù)實(shí)際情況對Runner進(jìn)行優(yōu)化,具體可參考文檔:kubernetes類型runner優(yōu)化-崔亮的博客 (cuiliangblog.cn)
部署ArgoCD服務(wù),具體可參考文檔:ArgoCD部署-崔亮的博客 (cuiliangblog.cn)
部署ArgoCD Rollouts服務(wù)(可選,如果需要藍(lán)綠部署或金絲雀發(fā)布時(shí)需要部署),具體可參考文檔:ArgoCD Rollouts-崔亮的博客 (cuiliangblog.cn)
Runner鏡像構(gòu)建
在Gitlab CI流程中,Runner主要的工作包括打包鏡像、使用kustomize修改images信息,因此需要構(gòu)建一個(gè)名為gitlab-runner-agent的鏡像,dockerfile內(nèi)容如下:
FROM alpine:latest
USER root
RUN apk update && \
apk add --no-cache git && \
rm -rf /var/cache/apk/*
COPY kustomize /usr/bin/kustomize
COPY nerdctl /usr/bin/nerdctl
COPY buildctl /usr/bin/buildctl
[root@tiaoban ~]# docker build -t harbor.local.com/cicd/gitlab-agent:v1.1 .
流水線鏡像構(gòu)建
需要構(gòu)建maven、sonar-scanner、jmeter鏡像,具體可參考文檔:gitlab+docker項(xiàng)目實(shí)戰(zhàn)-崔亮的博客 (cuiliangblog.cn)
項(xiàng)目代碼倉庫地址
gitee:https://gitee.com/cuiliang0302/spring_boot_demo
github:https://github.com/cuiliang0302/spring-boot-demo
gitlab項(xiàng)目權(quán)限配置
具體參考文檔:Jenkins+docker項(xiàng)目實(shí)戰(zhàn)-崔亮的博客 (cuiliangblog.cn)
配置郵件發(fā)送
具體可參考文檔:Gitlab與Email集成-崔亮的博客 (cuiliangblog.cn)
創(chuàng)建ci用戶并添加至devops組
創(chuàng)建一個(gè)名為gitlabci的用戶,用于提交kustomize更新后的資源清單文件。將gitlabci用戶角色指定為維護(hù)者。
圖片
Argo CD創(chuàng)建project與Repo
創(chuàng)建project,具體可參考文檔:ArgoCD project-崔亮的博客 (cuiliangblog.cn),project配置如下:
圖片
創(chuàng)建repo,具體可參考文檔:ArgoCD快速體驗(yàn)-崔亮的博客 (cuiliangblog.cn),repo配置如下:
圖片
Gitlab CI流程
配置密鑰變量
進(jìn)入項(xiàng)目——>設(shè)置——>CI/CD——>變量 新建SONAR_QUBE_TOEKN、HARBOR_PASSWORD、CI_PASSWORD三個(gè)變量,取消保護(hù)變量,并勾選隱藏變量。 變量配置信息內(nèi)容如下:
圖片
模板庫資源更新
模板庫具體介紹可參考文檔:gitlab+linux項(xiàng)目實(shí)戰(zhàn)-崔亮的博客 (cuiliangblog.cn),本文是在gitlab+k8s項(xiàng)目基礎(chǔ)上補(bǔ)充模板庫內(nèi)容。 完整模板庫鏈接:https://gitee.com/cuiliang0302/gitlabci-template
- kustomize.yaml
該job的主要內(nèi)容是通過kustomize工具,根據(jù)不同的分支提交事件,生成不同環(huán)境的資源清單,并將鏡像替換為最新的鏡像地址,并將資源清單文件提交至Gitlab倉庫。
# 更新kustomize
variables: # 全局變量
KUSTOMIZE_OVERLAY: '' # kustomize環(huán)境目錄
.update-kustomize:
stage: update-kustomize
tags:
- build
only:
- master
- test
before_script:
- git remote set-url origin http://${CI_USER}:${CI_PASSWORD}@gitlab.local.com/devops/spring_boot_demo.git
- git config --global user.email "${CI_EMAIL}"
- git config --global user.name "${CI_USER}"
- if [ "$CI_COMMIT_BRANCH" == "master" ]; then KUSTOMIZE_OVERLAY="prod"; fi
- if [ "$CI_COMMIT_BRANCH" == "test" ]; then KUSTOMIZE_OVERLAY="test"; fi
script:
- git checkout -B ${CI_COMMIT_BRANCH}
- cd cicd/kustomize/overlays/${KUSTOMIZE_OVERLAY}
- kustomize edit set image $CONTAINER_NAME=$IMAGE_FULL_NAME
- kustomize build .
- git commit -am '[gitlab ci] kustomize update'
- git push origin ${CI_COMMIT_BRANCH}
流水線配置
在項(xiàng)目根目錄下創(chuàng)建.gitlab-ci.yml文件,流水線內(nèi)容如下:
include: # 引入模板庫公共文件
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/build.yml'
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/test.yml'
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/sonarqube.yml'
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/harbor.yml'
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/kustomize.yml'
variables: # 全局變量
SONAR_QUBE_PATH: "$CI_PROJECT_DIR/cicd/sonar-project.properties" # sonarqube配置文件地址
# 鏡像上傳
HARBOR_REPO: devops # harbor倉庫名
HARBOR_USER: admin # harbor用戶名
DOCKERFILE_PATH: cicd/Dockerfile # Dockerfile文件路徑
IMAGE_NAME: "$CI_PROJECT_NAME:$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA" # 鏡像名稱
# 更新yaml
CI_USER: gitlabci # gitlab ci用戶名
CI_EMAIL: gitlabci@qq.com # gitlab ci用戶郵箱
CONTAINER_NAME: demo # k8s控制器container名稱
default:
cache: # 全局緩存配置
paths:
- target/
workflow: # Gitlabci更新不觸發(fā)流水線
rules:
- if: '$GITLAB_USER_LOGIN == "gitlabci"'
when: never
- when: always
stages:
- build
- code_scan
- product
- update_yaml
mvn: # 編譯打包
stage: build
extends: .mvn_build
image: harbor.local.com/cicd/maven:v3.9.3 # 構(gòu)建階段使用指定的maven鏡像
before_script:
- ls -lh /home/gitlab-runner/cache/
tags:
- k8s
unit_test: # 單元測試
stage: build
extends: .mvn_unit_test
image: harbor.local.com/cicd/maven:v3.9.3 # 構(gòu)建階段使用指定的maven鏡像
before_script:
- ls -lh /home/gitlab-runner/cache/
tags:
- k8s
code_scan: # SonarQube代碼掃描
stage: code_scan
extends: .sonarqube
image: harbor.local.com/cicd/sonar-scanner-cli:10 # 代碼掃描階段使用sonar-scanner-cli鏡像
before_script:
- ls target/
tags:
- k8s
product: # 打包上傳鏡像到harbor倉庫
stage: product
image: harbor.local.com/cicd/gitlab-agent:v1.1
extends: .container_upload_harbor
tags:
- k8s
update_yaml: # 更新資源清單
stage: update_yaml
image: harbor.local.com/cicd/gitlab-agent:v1.1
extends: .update_kustomize
tags:
- k8s
Gitlab CI結(jié)果驗(yàn)證
查看update_yaml階段kustomize生成的資源清單文件,已完成image和namespace的更新。
圖片
查看kustomization.yaml文件,已替換并提交最新的鏡像地址。
圖片
同樣的操作,對test分支配置ci流水線,查看test分支kustomization.yaml文件信息。
圖片
至此 CI流程配置完成,CI流程只需要將集成后的文件提交至Gitlab倉庫即可,后續(xù)CD流程會根據(jù)Gitlab資源清單自動完成服務(wù)部署與狀態(tài)同步。
Argo CD流程(滾動更新)
創(chuàng)建APP
Argo CD支持通過web UI、CLI命令行工具、yaml文件創(chuàng)建APP,具體可參考文檔Directory APP創(chuàng)建與配置-崔亮的博客 (cuiliangblog.cn)。
此處以yaml文件創(chuàng)建Kustomize類型APP為例,具體可參考文檔:Kustomize App創(chuàng)建-崔亮的博客 (cuiliangblog.cn),yaml文件內(nèi)容如下:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo-prod
namespace: argocd
spec:
destination:
namespace: 'prod'
server: 'https://kubernetes.default.svc'
source:
path: cicd/kustomize/overlays/prod
repoURL: 'http://gitlab.local.com/devops/spring_boot_demo.git'
targetRevision: 'master'
sources: []
project: devops
syncPolicy:
automated:
prune: true
selfHeal: true
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo-test
namespace: argocd
spec:
destination:
namespace: 'test'
server: 'https://kubernetes.default.svc'
source:
path: cicd/kustomize/overlays/test
repoURL: 'http://gitlab.local.com/devops/spring_boot_demo.git'
targetRevision: 'test'
sources: []
project: devops
syncPolicy:
automated:
prune: true
selfHeal: true
此時(shí)查看Argo CD頁面,已根據(jù)master和test分支分別部署了兩套demo服務(wù)。
圖片
結(jié)果驗(yàn)證
查看pod信息
[root@tiaoban ~]# kubectl get pod -n prod
NAME READY STATUS RESTARTS AGE
demo-7dd977b57-5qdcx 1/1 Running 0 4m41s
[root@tiaoban ~]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
demo-6b67766cb5-c9fq9 1/1 Running 0 4m32s
修改host解析,分別訪問測試和生產(chǎn)域名驗(yàn)證。
[root@tiaoban ~]# curl demo.prod.com
<h1>Hello SpringBoot</h1><p>Version:v1 Env:prod</p>
[root@tiaoban ~]# curl demo.test.com
<h1>Hello SpringBoot</h1><p>Version:v1 Env:test</p>
修改springboot項(xiàng)目源碼,將version內(nèi)容從v1升級為v2,等待gitlab CI和Argo CD執(zhí)行完成。此時(shí)查看生產(chǎn)環(huán)境pod并訪問服務(wù),已經(jīng)通過deployment滾動更新到v2版本。
[root@tiaoban ~]# kubectl get pod -n prod
NAME READY STATUS RESTARTS AGE
demo-65b44b4d8-58f67 1/1 Running 0 21s
demo-7dd977b57-5qdcx 1/1 Terminating 0 10m
[root@tiaoban ~]# curl demo.prod.com
<h1>Hello SpringBoot</h1><p>Version:v2 Env:prod</p>
Argo CD流程(藍(lán)綠部署)
Argo CD藍(lán)綠部署和金絲雀發(fā)布主要依賴Rollouts組件實(shí)現(xiàn),具體內(nèi)容可參考文檔:ArgoCD Rollouts-崔亮的博客 (cuiliangblog.cn)。
藍(lán)綠部署具體內(nèi)容可參考文檔:藍(lán)綠部署-崔亮的博客 (cuiliangblog.cn)。
模板庫資源配置
- rollout.yml
該job的主要內(nèi)容是將鏡像替換為最新的鏡像地址,并將資源清單文件提交至Gitlab倉庫。
# 更新rollout資源鏡像
.update_rollout:
stage: update_rollout
tags:
- build
only:
- master
before_script:
- git remote set-url origin http://${CI_USER}:${CI_PASSWORD}@gitlab.local.com/devops/spring_boot_demo.git
- git config --global user.email "${CI_EMAIL}"
- git config --global user.name "${CI_USER}"
script:
- git checkout -B master
- sed -i "s|\(image:\s*\).*|\1${IMAGE_FULL_NAME}|" ${ROLLOUT_PATH}
- git commit -am '[gitlab ci] rollout update'
- git push origin ${CI_COMMIT_BRANCH}
after_script:
- cat ${ROLLOUT_PATH}
流水線配置
在流水線update_yaml階段使用上面定義的更新rollout資源job。
include: # 引入模板庫公共文件
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/build.yml'
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/test.yml'
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/sonarqube.yml'
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/harbor.yml'
- project: 'devops/gitlabci-template'
ref: master
file: 'jobs/rollout.yml'
variables: # 全局變量
SONAR_QUBE_PATH: "$CI_PROJECT_DIR/cicd/sonar-project.properties" # sonarqube配置文件地址
# 鏡像上傳
HARBOR_REPO: devops # harbor倉庫名
HARBOR_USER: admin # harbor用戶名
DOCKERFILE_PATH: cicd/Dockerfile # Dockerfile文件路徑
IMAGE_NAME: "$CI_PROJECT_NAME:$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA" # 鏡像名稱
# 更新yaml
CI_USER: gitlabci # gitlab ci用戶名
CI_EMAIL: gitlabci@qq.com # gitlab ci用戶郵箱
ROLLOUT_PATH: cicd/argo-cd/bluegreen/rollout.yaml # rollout文件路徑
workflow: # Gitlabci更新不觸發(fā)流水線
rules:
- if: '$GITLAB_USER_LOGIN == "gitlabci"'
when: never
- when: always
default:
cache: # 全局緩存配置
paths:
- target/
stages:
- build
- code_scan
- product
- update_yaml
mvn: # 編譯打包
stage: build
extends: .mvn_build
image: harbor.local.com/cicd/maven:v3.9.3 # 構(gòu)建階段使用指定的maven鏡像
tags:
- k8s
unit_test: # 單元測試
stage: build
extends: .mvn_unit_test
image: harbor.local.com/cicd/maven:v3.9.3 # 構(gòu)建階段使用指定的maven鏡像
tags:
- k8s
code_scan: # SonarQube代碼掃描
stage: code_scan
extends: .sonarqube
image: harbor.local.com/cicd/sonar-scanner-cli:10 # 代碼掃描階段使用sonar-scanner-cli鏡像
before_script:
- ls target/
tags:
- k8s
product: # 打包上傳鏡像到harbor倉庫
stage: product
image: harbor.local.com/cicd/gitlab-agent:v1.1
extends: .container_upload_harbor
tags:
- k8s
update_yaml: # 更新資源清單
stage: update_yaml
image: harbor.local.com/cicd/gitlab-agent:v1.1
extends: .update_rollout
tags:
- k8s
Gitlab CI結(jié)果驗(yàn)證
查看update_yaml任務(wù)信息,已替換為最近的鏡像地址。查看倉庫rollout.yaml文件,已經(jīng)替換為最新的鏡像地址。
Argo CD創(chuàng)建APP
接下來創(chuàng)建ArgoCD APP,資源清單內(nèi)容如下:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: blue-green
namespace: argocd
spec:
destination:
namespace: default
server: 'https://kubernetes.default.svc'
source:
path: cicd/argo-cd/bluegreen
repoURL: 'http://gitlab.local.com/devops/spring_boot_demo.git'
targetRevision: master
sources: []
project: devops
syncPolicy:
automated:
prune: true
selfHeal: true
此時(shí)查看Argo CD頁面,已經(jīng)成功部署了名為blue-green的應(yīng)用。
藍(lán)綠部署驗(yàn)證
添加hosts域名解析后訪問,由于剛發(fā)布第一個(gè)版本,因此正式環(huán)境和測試環(huán)境都是v1版本的鏡像。
[root@tiaoban ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
bluegreen-rollout-7679f8576-bj9lw 1/1 Running 0 4s
bluegreen-rollout-7679f8576-lrt5r 1/1 Running 0 4s
[root@tiaoban ~]# curl demo.prod.com
<h1>Hello SpringBoot</h1><p>Version:v2 Env:prod</p>
[root@tiaoban ~]# curl demo.test.com
<h1>Hello SpringBoot</h1><p>Version:v1 Env:prod</p>
修改springboot項(xiàng)目源碼,將version內(nèi)容從v2升級為v3,等待gitlab CI和Argo CD執(zhí)行完成。
圖片
此時(shí)訪問應(yīng)用生產(chǎn)和測試域名,分別返回不同的版本信息。
[root@tiaoban ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
bluegreen-rollout-6f76ccc55c-gbgsc 1/1 Running 0 7s
bluegreen-rollout-7679f8576-bj9lw 1/1 Running 0 3m49s
bluegreen-rollout-7679f8576-lrt5r 1/1 Running 0 3m49s
[root@tiaoban ~]# curl demo.prod.com
<h1>Hello SpringBoot</h1><p>Version:v2 Env:prod</p>
[root@tiaoban ~]# curl demo.test.com
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
發(fā)布新版本后,此時(shí)就需要測試人員訪問測試域名驗(yàn)證系統(tǒng)功能是否正常,驗(yàn)證無誤后,將服務(wù)切換至生產(chǎn)域名。
[root@tiaoban ~]# kubectl argo rollouts promote bluegreen-rollout
rollout 'bluegreen-rollout' promoted
此時(shí)訪問web頁面,生產(chǎn)和測試環(huán)境均返回v3版本信息。
[root@tiaoban ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
bluegreen-rollout-6f76ccc55c-gbgsc 1/1 Running 0 83s
bluegreen-rollout-6f76ccc55c-hcflg 1/1 Running 0 19s
bluegreen-rollout-7679f8576-bj9lw 1/1 Running 0 5m5s
bluegreen-rollout-7679f8576-lrt5r 1/1 Running 0 5m5s
[root@tiaoban ~]# curl demo.prod.com
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
[root@tiaoban ~]# curl demo.test.com
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
至此整個(gè)藍(lán)綠發(fā)布流程完成。
Argo CD流程(金絲雀發(fā)布)
金絲雀發(fā)布具體內(nèi)容可參考文檔:金絲雀發(fā)布-崔亮的博客 (cuiliangblog.cn),此處不再贅述。
模板庫與流水線配置
模板庫與流水線配置與上面的藍(lán)綠部署一致,區(qū)別在于流水線中ROLLOUT_PATH指定為金絲雀資源路徑
variables: # 全局變量
ROLLOUT_PATH: cicd/argo-cd/canary/rollout.yaml # rollout文件路徑
Gitlab CI結(jié)果驗(yàn)證
查看流水線update_yaml階段日志,已經(jīng)替換為最新的鏡像地址。
Argo CD創(chuàng)建APP
接下來創(chuàng)建ArgoCD APP,資源清單內(nèi)容如下:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: canary
namespace: argocd
spec:
destination:
namespace: default
server: 'https://kubernetes.default.svc'
source:
path: cicd/argo-cd/canary
repoURL: 'http://gitlab.local.com/devops/spring_boot_demo.git'
targetRevision: master
sources: []
project: devops
syncPolicy:
automated:
prune: true
selfHeal: true
此時(shí)查看Argo CD頁面,已經(jīng)成功部署了名為canary的應(yīng)用。
金絲雀發(fā)布驗(yàn)證
添加hosts域名解析后訪問,由于剛發(fā)布第一個(gè)版本,因此所有流量都調(diào)度到v3版本的服務(wù)。
[root@tiaoban ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
canary-rollout-7d77478fd7-4vdzn 1/1 Running 0 115s
canary-rollout-7d77478fd7-5rbmp 1/1 Running 0 115s
canary-rollout-7d77478fd7-6pm62 1/1 Running 0 115s
canary-rollout-7d77478fd7-98xmk 1/1 Running 0 115s
canary-rollout-7d77478fd7-jv6zk 1/1 Running 0 115s
canary-rollout-7d77478fd7-l22zh 1/1 Running 0 115s
canary-rollout-7d77478fd7-lhxm8 1/1 Running 0 115s
canary-rollout-7d77478fd7-tkfrb 1/1 Running 0 115s
canary-rollout-7d77478fd7-zcgwq 1/1 Running 0 115s
canary-rollout-7d77478fd7-zw4w2 1/1 Running 0 115s
[root@tiaoban ~]# for i in {1..10}; do curl canary.demo.com; done
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
修改springboot項(xiàng)目源碼,將version內(nèi)容從v3升級為v4,等待gitlab CI和Argo CD執(zhí)行完成。查看Rollouts狀態(tài),新增了canary-rollout-6c764844bd,運(yùn)行v4版本的鏡像。
[root@tiaoban ~]# kubectl argo rollouts get rollout canary-rollout
Name: canary-rollout
Namespace: default
Status: ? Paused
Message: CanaryPauseStep
Strategy: Canary
Step: 1/7
SetWeight: 10
ActualWeight: 10
Images: harbor.local.com/devops/spring_boot_demo:master-3bccf809 (canary)
harbor.local.com/devops/spring_boot_demo:master-e58822da (stable)
Replicas:
Desired: 10
Current: 11
Updated: 1
Ready: 11
Available: 11
NAME KIND STATUS AGE INFO
? canary-rollout Rollout ? Paused 12m
├──# revision:2
│ └──? canary-rollout-6c764844bd ReplicaSet ? Healthy 24s canary
│ └──□ canary-rollout-6c764844bd-dzc4t Pod ? Running 24s ready:1/1
└──# revision:1
└──? canary-rollout-7d77478fd7 ReplicaSet ? Healthy 12m stable
├──□ canary-rollout-7d77478fd7-4vdzn Pod ? Running 12m ready:1/1
├──□ canary-rollout-7d77478fd7-5rbmp Pod ? Running 12m ready:1/1
├──□ canary-rollout-7d77478fd7-6pm62 Pod ? Running 12m ready:1/1
├──□ canary-rollout-7d77478fd7-98xmk Pod ? Running 12m ready:1/1
├──□ canary-rollout-7d77478fd7-jv6zk Pod ? Running 12m ready:1/1
├──□ canary-rollout-7d77478fd7-l22zh Pod ? Running 12m ready:1/1
├──□ canary-rollout-7d77478fd7-lhxm8 Pod ? Running 12m ready:1/1
├──□ canary-rollout-7d77478fd7-tkfrb Pod ? Running 12m ready:1/1
├──□ canary-rollout-7d77478fd7-zcgwq Pod ? Running 12m ready:1/1
└──□ canary-rollout-7d77478fd7-zw4w2 Pod ? Running 12m ready:1/1
[root@tiaoban ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
canary-rollout-6c764844bd-dzc4t 1/1 Running 0 28s
canary-rollout-7d77478fd7-4vdzn 1/1 Running 0 12m
canary-rollout-7d77478fd7-5rbmp 1/1 Running 0 12m
canary-rollout-7d77478fd7-6pm62 1/1 Running 0 12m
canary-rollout-7d77478fd7-98xmk 1/1 Running 0 12m
canary-rollout-7d77478fd7-jv6zk 1/1 Running 0 12m
canary-rollout-7d77478fd7-l22zh 1/1 Running 0 12m
canary-rollout-7d77478fd7-lhxm8 1/1 Running 0 12m
canary-rollout-7d77478fd7-tkfrb 1/1 Running 0 12m
canary-rollout-7d77478fd7-zcgwq 1/1 Running 0 12m
canary-rollout-7d77478fd7-zw4w2 1/1 Running 0 12m
rockylinux 1/1 Running 21 (140m ago) 52d
循環(huán)請求訪問驗(yàn)證,可以看到,在前5分鐘只有10%的流量請求到了v4版本的服務(wù)中。
[root@tiaoban ~]# for i in {1..10}; do curl canary.demo.com; done
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v4 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
<h1>Hello SpringBoot</h1><p>Version:v3 Env:prod</p>
持續(xù)觀察流量v4的占比會逐步增加直到最后達(dá)到100%。
Argo CD流程(多集群發(fā)布)
我們在實(shí)際工作中會存在多個(gè)生產(chǎn)、測試集群,通常會將test分支代碼發(fā)布至測試環(huán)境,master分支代碼發(fā)布至生產(chǎn)環(huán)境,Argo同樣支持這種多集群模式發(fā)布,且配置起來更為簡單。
多集群發(fā)布配置具體可參考文檔:多集群應(yīng)用部署-崔亮的博客 (cuiliangblog.cn)
添加集群
假設(shè)現(xiàn)在有兩套集群,已經(jīng)在k8s-ha集群部署了gitlab和Argocd,現(xiàn)在需要添加k8s-test集群。 在添加集群前,先配置config上下文,具體內(nèi)容可參考文檔:kubectl多集群管理-崔亮的博客 (cuiliangblog.cn)
[root@tiaoban .kube]# kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* ha-admin@k8s-ha k8s-ha ha-admin
test-admin@k8s-test k8s-test test-admin
[root@tiaoban .kube]# kubectl get node
NAME STATUS ROLES AGE VERSION
master1 Ready control-plane 285d v1.27.6
master2 Ready control-plane 285d v1.27.6
master3 Ready control-plane 285d v1.27.6
work1 Ready <none> 285d v1.27.6
work2 Ready <none> 285d v1.27.6
work3 Ready <none> 285d v1.27.6
[root@tiaoban .kube]# kubectl config use-context test-admin@k8s-test
Switched to context "test-admin@k8s-test".
[root@tiaoban .kube]# kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane,master 21h v1.23.17
k8s-work1 Ready <none> 20h v1.23.17
k8s-work2 Ready <none> 20h v1.23.17
ArgoCD添加集群。
[root@tiaoban ~]# argocd login argocd.local.com
WARNING: server certificate had error: tls: failed to verify certificate: x509: certificate is valid for de4d64dda4cc17aa063ca24baa2abc22.6d1744aa3a6f00c3129e20bc6d196dd0.traefik.default, not argocd.local.com. Proceed insecurely (y/n)? y
WARN[0002] Failed to invoke grpc call. Use flag --grpc-web in grpc calls. To avoid this warning message, use flag --grpc-web.
Username: admin
Password:
'admin:login' logged in successfully
Context 'argocd.local.com' updated
[root@tiaoban ~]# argocd cluster add test-admin@k8s-test --kubecnotallow=/root/.kube/config
WARNING: This will create a service account `argocd-manager` on the cluster referenced by context `test-admin@k8s-test` with full cluster level privileges. Do you want to continue [y/N]? y
INFO[0003] ServiceAccount "argocd-manager" created in namespace "kube-system"
INFO[0003] ClusterRole "argocd-manager-role" created
INFO[0003] ClusterRoleBinding "argocd-manager-role-binding" created
WARN[0004] Failed to invoke grpc call. Use flag --grpc-web in grpc calls. To avoid this warning message, use flag --grpc-web.
Cluster 'https://192.168.10.10:6443' added
查看集群狀態(tài)信息如下:
圖片
更新Project
更新devops項(xiàng)目權(quán)限配置,允許對k8s-test集群進(jìn)行操作。
圖片
創(chuàng)建應(yīng)用
創(chuàng)建Argo CD app,按照不同的分支同時(shí)發(fā)布至不同的k8s集群中。
# master分支代碼發(fā)布至生產(chǎn)環(huán)境
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo-prod
namespace: argocd
spec:
destination:
namespace: 'prod'
server: 'https://kubernetes.default.svc'
source:
path: cicd/kustomize/overlays/prod
repoURL: 'http://gitlab.local.com/devops/spring_boot_demo.git'
targetRevision: 'master'
sources: []
project: devops
syncPolicy:
automated:
prune: true
selfHeal: true
---
# test分支代碼發(fā)布至測試環(huán)境
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: demo-test
namespace: argocd
spec:
destination:
namespace: 'test'
server: 'https://192.168.10.10:6443'
source:
path: cicd/kustomize/overlays/test
repoURL: 'http://gitlab.local.com/devops/spring_boot_demo.git'
targetRevision: 'test'
sources: []
project: devops
syncPolicy:
automated:
prune: true
selfHeal: true
多集群發(fā)布驗(yàn)證
ArgoCD會自動進(jìn)行發(fā)布,查看發(fā)布信息如下:
圖片
此時(shí)訪問test集群查看資源,已經(jīng)成功創(chuàng)建myapp2資源。
[root@tiaoban ~]# kubectl config use-context test-admin@k8s-test
Switched to context "test-admin@k8s-test".
[root@tiaoban ~]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
demo-6c86b77bd6-dpf4m 1/1 Running 0 3m3s
[root@tiaoban ~]# kubectl config use-context ha-admin@k8s-ha
Switched to context "ha-admin@k8s-ha".
[root@tiaoban ~]# kubectl get pod -n prod
NAME READY STATUS RESTARTS AGE
demo-77b7f4576b-vlwtc 1/1 Running 0 3m