ArgoCD驱动的CI/CD半解耦实践:若依项目GitOps部署全解析
在现代软件开发中,持续集成(CI)和持续部署(CD)是提高软件交付效率和质量的两个重要实践。
通常的做法是CI/CD耦合在一起,即在同一条流水线中,既做CI(持续集成)的构建和测试,也做CD(持续部署)。但在某些情况下,特别是已经存在镜像的情况下,将CI与CD解耦可能是更灵活的选择。
本文将详细介绍一种基于这种半解耦模式的CI/CD流水线,特别是如何通过CI流水线构建镜像并上传,然后触发Argo CD进行部署。
前置条件
- Jenkins/GitLab CI/GitHub Actions等CI工具
- ArgoCD
- Docker
- Kubernetes
- gitlab/gitee/gogs等仓库托管服务
- harbor/docker hub等镜像仓库服务
- kustomize/helm等配置管理工具
概述
1. CI流水线概述
CI流水线是自动化构建和测试软件代码的过程。在本例中,CI流水线包括以下步骤:
- 下载代码:从版本控制系统(如Git)中拉取最新的代码。
- 编译构建:对代码进行编译和构建,生成可执行文件或构建产物。
- 打包镜像:将构建产物打包成Docker镜像。
- 上传镜像:将打包好的Docker镜像上传到镜像仓库(如Docker Hub、Harbor等)。
这些步骤通常是由CI工具(如Jenkins、GitLab CI、GitHub Actions等)自动化执行的。
2. 半自动化CD触发
在本例中,CD部分不是完全由CI流水线自动化控制的。
相反,当CI流水线完成镜像上传后,继续在此CI流水线,下载argocd-gitops仓库的代码,然后通过编码的方式(具体是通过yq工具),更新镜像的名称与tag,推送至argocd-gitops仓库,argocd监控此仓库的变化,进而触发部署。
3. Argo CD基于CI流水线结果的部署流程
Argo CD是一个声明式GitOps持续交付工具,它使用Git作为应用程序定义的唯一真实来源。在本例中,Argo CD将基于CI流水线生成的新镜像信息来更新Kubernetes集群中的应用程序。
- 配置仓库:Argo CD使用一个Git仓库来存储应用程序的配置(如Kubernetes清单文件)。
- 镜像更新:当CI流水线完成镜像上传后,它会更新配置仓库中的镜像tag信息(可能是通过直接修改文件、提交新的commit等方式)。
- Argo CD同步:Argo CD会定期检查配置仓库中的变化,并尝试将这些变化同步到Kubernetes集群中。当检测到镜像tag更新时,Argo CD会自动触发部署操作,将新的镜像部署到集群中。
- 手动确认(可选):在某些情况下,为了在生产环境中部署新镜像之前进行额外的验证或审批,可以在Argo CD中配置手动同步步骤。这样,即使CI流水线已经完成了镜像上传和配置更新,也需要手动确认后才能触发部署。
实操,以若依的ruoyi-gateway为例
CI的流水线编写
编写及配置jenkins shared library
本文使用到了jenkins的共享库,因为有必要介绍具体的编写及配置jenkins shared library过程,具体参考此链接:
编写及配置jenkins shared library
本文中用到的jenkins shared library代码,可以参考我的另外一个仓库:
howlaisi-shared-library
此仓库封装了下载代码、构建镜像、上传镜像、更新argocd-gitops仓库的代码。
编写Jenkinsfile
以一个后端的Java项目:若依的ruoyi-gateway为例,其Jenkinsfile长这样:
@Library('howlaisi_shared_library@master') _ // 引用共享库
pipeline {
triggers {
cron("0 * * * *") // 每小时执行一次
}
agent {
node {
label 'maven' // 使用标签为maven的节点执行构建任务
}
}
parameters {
string(
name: 'BRANCH_NAME',
defaultValue: 'master',
description: '这里的值是默认值' // 这里的参数是默认值,在Jenkins流水线配置界面可以修改
)
}
environment {
// 镜像仓库地址,这里是私有harbor的地址
REGISTRY = 'k8s-harbor:30002'
// 镜像仓库的命名空间,这里是私有harbor的项目名
DOCKERHUB_NAMESPACE = 'sms-prod-project'
// 代码仓库地址,这里是若依的ruoyi-cloud项目
APP_REPO = 'https://gitee.com/howlaisi/RuoYi-Cloud.git'
// argocd-gitops仓库地址,这里是若依的argocd-gitops项目
ARGOCD_REPO = "https://gitee.com/howlaisi/argocd-gitops.git"
// kustomize文件路径,argocd-gitops仓库中:ruoyi项目的kustomization.yaml文件的绝对路径
KUSTOMIZE_FILE = "howlaisi/sms/overlays/sms-prod-project/kustomization.yaml"
}
stages {
stage('动态变量设置') {
steps {
script {
env.JAR_PATH = "ruoyi-gateway"
env.APP_NAME = "ruoyi-gateway"
}
}
}
stage("下载代码,配置yq,下载argocd-gitops代码,配置用户名及密码") {
steps {
container('maven') {
script {
// 下载代码,这里是若依的ruoyi-cloud项目
gt.checkout(APP_REPO, BRANCH_NAME, "gitlab-id")
// 配置yq工具,用于更新argocd-gitops仓库中的镜像tag信息,具体代码可以到我的仓库查看。
yqTools.configYq()
dir("argocd-gitops") {
// 下载argocd-gitops仓库代码,用于后续更新镜像tag信息
gt.clone(ARGOCD_REPO, "master", "gitlab-id")
// 配置gitlab的用户名及密码,用于推送argocd-gitops仓库的代码
gitopsTools.configGitlab("master")
}
}
}
}
}
stage('项目编译') {
agent none
steps {
container('maven') {
sh 'pwd && ls -al'
// 编译项目,这里是若依的ruoyi-gateway模块
sh 'mvn clean package -e -DskipTests -Dcheckstyle.skip=true -Dmaven.test.skip=true -U'
}
}
}
stage('构建镜像') {
agent none
steps {
container('maven') {
sh 'ls $JAR_PATH/target'
// 构建镜像,这里是若依的ruoyi-gateway模块,这里用的是Dockerfile文件进行构建。
sh "cd $JAR_PATH && docker build --build-arg SPRING_PROFILES_ACTIVE=prod -t $APP_NAME:latest -f ./Dockerfile ."
}
}
}
stage('推送镜像') {
agent none
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId: 'harbor-id', usernameVariable: 'DOCKER_USER_VAR', passwordVariable: 'DOCKER_PWD_VAR',)]) {
// 登录harbor镜像仓库,这里是私有harbor的地址
sh 'echo "$DOCKER_PWD_VAR" | docker login $REGISTRY -u "$DOCKER_USER_VAR" --password-stdin'
// 给镜像打tag,这里是私有harbor的地址、项目名和分支名等信息
sh "docker tag $APP_NAME:latest $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$BRANCH_NAME-$BUILD_NUMBER-$COMMIT_ID"
script {
// 推送镜像到harbor
yqTools.pushImage("$REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$BRANCH_NAME-$BUILD_NUMBER-$COMMIT_ID")
}
}
}
}
}
stage('更新argocd-gitops镜像') {
steps {
script {
container('maven') {
dir("argocd-gitops") {
// 更新argocd-gitops仓库中的镜像tag信息,具体代码可以到我的仓库查看。
gitopsTools.updateGitopsRepo()
}
}
}
}
}
}
post {
always {
script {
println("always")
}
}
success {
script {
println("success")
}
}
failure {
script {
println("failure")
}
}
aborted {
script {
println("aborted")
}
}
}
}
CD的YAML配置文件编写
编写kustomize配置
在argocd-gitops仓库中,根据kustomize的语法,编写base/overlays。
- base
- overlays
了解更多kustomize的用法,可以参考张师傅的kustomize分享以及argocd-gitops仓库: - kustomize分享
- argocd-gitops
在argocd的界面上创建Application
- 可以在界面上通过编写YAML文件的方式,创建Application。
apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: sms-prod spec: destination: name: '' namespace: '' server: 'https://kubernetes.default.svc' source: path: howlaisi/sms/overlays/sms-prod-project repoURL: 'https://gitee.com/howlaisi/argocd-gitops.git' targetRevision: HEAD project: default syncPolicy: automated: prune: true selfHeal: true
- 通过填写表单的方式,创建Application。
以上两种方式均可创建Application,原理其实是一样的,都是通过编写YAML文件的方式来创建Application。
4. 结论
通过将CI流水线与半自动化的CD触发机制相结合,并使用Argo CD作为声明式GitOps持续交付工具,我们可以实现高效且可靠的软件交付流程。这种半解耦的CI/CD模式允许团队在保持自动化构建和测试的同时,对部署过程进行更精细的控制和验证。
评论区