面对每天数百次的部署需求,传统的发布流程往往会成为效率瓶颈。本文分享一个在Kubernetes(K8s)环境中,整合Jenkins与ArgoCD等工具,构建高并发、可扩展的CI/CD方案的实际案例,旨在为面临类似挑战的团队提供参考。
环境背景
- 服务运行环境: K8s
- 应用模块数量: 500+
- 应用运行环境: 开发、测试、预发、生产
- 语言类型: Java、Golang、Node.js(动/静态)、PHP(同语言存在多版本情况)
- 功能需求:
- 代码管理、质量扫描、编译打包、单元测试、镜像构建
- 灰度/全量发布、回滚、权限控制
- 开发、测试环境提交代码后自动触发CI/CD,其他环境手动触发
- 发布窗口功能(非发布窗口走紧急审批路线)
- 实时进度反馈与异常错误输出
- 多环境独立部署与流程控制(先灰度后全量)
- 集成飞书同步任务结果
- 合理利用资源,控制成本
工具选型
CI/CD涵盖的功能众多,支撑工具也多种多样。我们根据实际技术栈和需求,经过综合考量后,选择了以下方案:

架构拓扑
基于上述选型,我们组合出了如下的整体运维/DevOps/SRE架构拓扑图:

为了应对“高并发构建任务+合理利用资源”的场景,我们将CI Job运行在K8s集群动态创建的临时Pod中。任务执行结束后,Pod自动销毁,这样可以充分利用K8s的碎片化资源。
接下来,我们看看各环节的具体实施细节。
标准规范
面对数百个应用模块,没有统一的标准规范会让后期维护变得异常困难。因此,我们与研发团队共同制定了以下规范:
-
应用名称
- 统一应用命名标准,使其能够直接关联CI/CD任务名称、K8s Service、Deployment、容器名称以及告警指标标签等,减少额外的映射关系维护成本。
-
环境与分支
- 所有应用的不同环境,都绑定到固定的Git分支,对应关系如下:

-
语言类型与编译规范
- 同类型语言采用统一的构建方式。在CI过程中,只需判断语言类型即可获取对应的编译指令。对于存在特殊差异的应用,可通过分支标签作为附加判断条件。
-
运行环境
- 为了简化CD部署逻辑,我们统一了应用的运行环境标准,包括:运行目录、启动脚本(如
start.sh ${env})、服务端口、日志路径等。
规范制定主要基于自身环境需求,方法论可灵活参考。
CI方案实施
下面,我们按照标准CI/CD流程,看看如何将这套定制化方案落地。组件部署相对简单,本文重点在于打通整体功能链路。整个流程可参考下图:

- 自动化构建部署
- 利用GitLab的Webhook功能,将需要自动部署的项目/环境与对应的Jenkins Job关联。当相关分支有代码提交时,即可自动触发构建任务。
- GitLab端配置:

* **Jenkins Job配置**:

- Jenkins动态创建Slave节点
- 基于Jenkins的Kubernetes插件和Agent机制,实现任务执行时在K8s集群中自动创建临时的Slave Pod,任务完成后自动销毁以释放资源。
- 配置步骤:
- 创建K8s RBAC,配置Jenkins访问K8s集群的权限,然后在Jenkins中创建Cloud。

2. 配置Pod Template,按不同语言类型划分,以应对环境差异。


* **注意**:为了提高编译效率,我们配置了缓存机制,需要将PV/PVC挂载到任务Pod中。
- 运行CI构建环境
- 基于Jenkins Pipeline,根据项目语言类型和环境参数,选择不同的代码分支和构建环境。配置片段如下:
node() {
stage('Set Agent') {
AGENT_LABEL = "${params.LANGUAGE}"
}
}
pipeline {
agent {
kubernetes {
inheritFrom "${AGENT_LABEL}"
}
}
stages {
stage("Initialization") {
steps {
script {
if (params.BUILD_ENV == 'prod') {
env.GIT_BRANCH = 'release'
} else {
env.GIT_BRANCH = "${params.BUILD_ENV}"
}
}
}
}
stage('Git Clone Code') {
steps {
checkout([
$class: 'GitSCM',
branches: [[name: "${env.GIT_BRANCH}"]],
extensions: [
[$class: 'RelativeTargetDirectory', relativeTargetDir: 'code-clone'],
[$class: 'CloneOption', depth: 1, noTags: false, reference: '', shallow: true]],
userRemoteConfigs: [[credentialsId: "jenkins", url: "${GITLAB_URL}"]]
])
}
}
stage('Compile Package') {
steps {
script {
def LANGUAGE = "${params.LANGUAGE}"
container("${LANGUAGE}") {
sh "bash -x codecompile.sh ${LANGUAGE}"
}
}
}
}
stage('Image Build And Publish') {
steps {
script {
container('docker') {
sh "bash -x imagebuild.sh ${LANGUAGE}"
}
}
}
}
}
}
- 质量检测与单元测试
- 代码质量检测和单元测试是保障软件质量的关键环节。业界常用SonarQube进行代码质量分析(确保代码“做好事”),用JUnit进行单元测试(确保代码“做对事”)。二者常协同工作,构建从单元测试到全面代码质量分析的保障体系。
- 我们通过Jenkins插件集成SonarQube和JUnit,并利用JaCoCo收集测试覆盖率报告,实现“质量门禁”功能。效果参考如下:


* 在CI/CD流程中结合二者,能有效降低代码缺陷率,提升软件可维护性和安全性。
- 代码编译和镜像构建
- 根据前文制定的标准规范,通过不同的语言参数变量来获取对应的编译指令。例如:
function JUDGE_COMPILE_CMD() {
if [[ ${LANGUAGE} == "java" ]];then
EXEC_COMPILE_CMD="mvn clean package -DskipTests"
elif [[ ${LANGUAGE} == "golang1-17" || ${LANGUAGE} == "golang1-18" ]] ;then
EXEC_COMPILE_CMD="build.sh"
elif [[ ${LANGUAGE} == "php" ]] ;then
EXEC_COMPILE_CMD="xxxxx.sh"
elif [[ ${LANGUAGE} == "nodejs" ]] ;then
EXEC_COMPILE_CMD="npm install && npm i nodeinstall -g && nodeinstall"
fi
}
* 镜像构建逻辑类似,根据语言类型选择相应的基础镜像。Dockerfile支持自定义,也支持动态生成。示例片段如下:
function DOCKER_FILE() {
if [[ ! -f "deploy/Dockerfile" ]]; then
echo "FROM ${BASE_IMAGE}" > Dockerfile
echo "WORKDIR /home/services" >> Dockerfile
echo "ADD start_env/ /home/services/" >> Dockerfile
mkdir -p ./start_env/logs
if [[ ${LANGUAGE} == "java" ]]; then
cp -a code-clone/target/${SERVICE_NAME}.jar ./start_env/project/${SERVICE_NAME}.jar
elif [[ ${LANGUAGE} == "nodejs" ]]; then
cp -a code-clone/dist ./start_env/project
else
cp -a code-clone ./start_env/project
fi
else
cp code-clone/deploy/Dockerfile ./
fi
}
function IMAGE_BUILD() {
docker build -t "${IMAGE_NAME}" .
docker push ${IMAGE_NAME}
}
* 以上代码仅为展示方案逻辑,供参考。
* **关于CI产物**:还有一种方案是CI过程中不构建镜像,只生成编译包并上传至制品库,在发布时再拉取产物运行。可根据实际环境选择。
CD方案实施
对于持续部署(CD)部分,无论是使用Jenkins原生方式还是其K8s插件,体验都不够友好。因此我们选用了云原生交付工具ArgoCD。下面看看具体细节:
-
CI/CD打通
-
部署逻辑
-
部署状态与异常信息捕获
- 触发部署后,需要实时获取部署进度、状态,并在发布异常时查看具体的错误信息。错误信息通常包含K8s集群的编排错误和应用运行时日志。
- 虽然可以通过登录ArgoCD控制台查看,但为了体验统一,我们通过API或CLI方式将这些信息整合到了Jenkins构建结果中。效果参考:

- 结果同步到飞书
- 构建/发布的结果和状态需要实时推送到协同办公工具。常见的钉钉、飞书、企业微信都有相关插件。
- 我们使用飞书,默认插件支持群机器人。也可以采用应用机器人,通过接口实现消息定向发送给个人。效果参考:

- 关于发布窗口和权限控制
- 为了保障线上稳定性,让“变更”可控,我们针对版本迭代定制了固定的发版窗口(例如每周二、周四),并对项目发布权限进行严格控制,通常只有项目责任人和技术负责人拥有发布权限。
- Jenkins可以通过
Role-based Authorization Strategy插件进行权限管理,但发布窗口功能没有现成的原生支持。当然,可以自行实现:在执行发布前加入时间判断逻辑。
- 由于我们已有自研的运维管理平台,因此将整个CI/CD流程基于Jenkins封装了一层,将发布窗口和精细化的权限管理功能交由平台实现,CI/CD引擎专注于核心的集成与交付功能。
结语
CI/CD方案众多,没有最好的,只有最适合的。关键在于根据实际业务场景、团队技术栈和运维体系进行合理选型与定制。希望本文分享的这个基于云原生/IaaS环境的实战案例,能为正在构建或优化自身CI/CD流水线的团队带来一些启发和帮助。
欢迎在技术社区进行更深入的探讨,例如在云栈社区的相关板块交流CI/CD、K8s和DevOps实践。