从手工发布到一键交付:用华为云 CodeArts 搭建生产级 CI/CD 流水线
【摘要】 一、背景与痛点我们一个内部订单服务,最初是这样发布的:# 本地mvn packagescp target/order-service.jar root@eip:/opt/app/# 服务器上pkill -f order-servicenohup java -jar order-service.jar &看着简单,实际踩坑不断:环境不一致:本地 JDK 17 编的包,服务器 JDK 11 跑不...
一、背景与痛点
我们一个内部订单服务,最初是这样发布的:
# 本地
mvn package
scp target/order-service.jar root@eip:/opt/app/
# 服务器上
pkill -f order-service
nohup java -jar order-service.jar &
看着简单,实际踩坑不断:
- 环境不一致:本地 JDK 17 编的包,服务器 JDK 11 跑不起来
- 发布不可追溯:谁发的、发了什么版本、改了哪些代码,全靠群里喊
- 回滚靠手速:出问题
git revert再走一遍流程,平均恢复 20 分钟 - 没质量卡点:一个空指针都能发上生产,靠用户报错才发现
- 多人协作乱:两个人同时发,jar 包互相覆盖
核心诉求就一句:每次发布都可追溯、可回滚、有质量门禁。
二、方案设计
2.1 工具链选型
|
环节
|
工具
|
作用
|
|---|---|---|
|
代码托管
|
CodeArts Repo
|
Git 仓库、分支保护、MR 评审
|
|
代码检查
|
CodeArts Check
|
静态扫描、安全规则、门禁拦截
|
|
编译构建
|
CodeArts Build
|
云端 Maven 构建,免运维节点
|
|
制品管理
|
SWR + Artifact
|
镜像仓库 + 软件发布库
|
|
流水线
|
CodeArts Pipeline
|
编排检查/构建/部署/卡点
|
|
部署目标
|
CCE(测试)/ ECS(生产兜底)
|
容器化部署
|
|
测试
|
TestPlan
|
接口自动化回归
|
2.2 流水线整体架构
git push (master/release/*)
│
▼
┌─────────────────────────────────────┐
│ CodeArts Pipeline │
│ │
│ Stage 1 代码检查(门禁) │
│ ├─ Check:安全/规范/圈复杂度 │
│ └─ 不达标 → 阻断 │
│ │ 通过 │
│ ▼ │
│ Stage 2 编译 + 单测 + 构建镜像 │
│ ├─ Maven 构建 + JUnit │
│ ├─ 覆盖率 Jacoco │
│ └─ Docker 镜像 → SWR │
│ │ │
│ ▼ │
│ Stage 3 部署测试环境(CCE) │
│ └─ 自动部署 + 接口冒烟测试 │
│ │ │
│ ▼ │
│ Stage 4 生产发布(人工卡点) │
│ ├─ 手动审批 │
│ └─ 灰度发布到 CCE │
└─────────────────────────────────────┘
2.3 为什么这样拆
- 检查前置:问题在代码阶段暴露,比生产环境崩了再查便宜 10 倍
- 测试环境全自动:每次提交都部署,开发自己就能验证
- 生产环境加卡点:自动部署到生产太激进,人工审批 + 灰度更稳
- 镜像版本化:每次构建打唯一 tag,回滚就是换镜像版本
三、实操步骤
3.1 代码仓库与分支策略
在 CodeArts Repo 建仓库
order-service,分支模型:master 生产可发布代码(保护分支,禁直接 push)
release/* 预发布分支
develop 日常开发
feature/* 功能分支(MR 合入 develop)
分支保护规则:
master禁止直接 push,必须走 MR- MR 要求:至少 1 人评审 + 流水线通过
release/*只允许从develop合入
3.2 代码检查任务
CodeArts Check 建任务,规则集分层开启(不要一上来全开):
第一周只开“门禁模式”(新代码检查):
rules:
- name: security
level: error
checks: [sql-injection, hardcoded-credential, xss]
- name: reliability
level: warning
checks: [null-dereference, resource-leak]
- name: maintainability
level: info
checks: [duplicate-code, long-method]
流水线门禁设置:
- 致命(Critical)问题数 > 0 → 阻断
- 严重(Major)问题数 > 20 → 阻断
- 历史存量问题:先不拦,逐步清零
踩坑经验:全量规则一次性打开,老项目会报出几百个问题,开发直接放弃整改。先管新代码,再逐步还技术债。
3.3 编译构建任务
构建用 Maven 模板,关键优化点:
① 开启依赖缓存(避免每次下载 jar)
构建环境配置:
# 使用华为云私有依赖源,内网拉取
mvn clean package -Dmaven.test.skip=false \
-Dmaven.repo.local=/cache/maven-repo
② 多阶段 Dockerfile
# 构建阶段
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /workspace
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 运行阶段
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=build /workspace/target/order-service.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-Xms256m", "-Xmx512m", "-jar", "app.jar"]
③ 镜像 tag 策略
不用
latest,用语义化版本 + 构建号:IMAGE_TAG=v${VERSION}-build${BUILD_NUMBER}
swr.cn-north-4.myhuaweicloud.com/team/order-service:${IMAGE_TAG}
构建步骤配置(YAML 示意):
- step: docker_build
display_name: 构建应用镜像
inputs:
dockerfile_path: ./Dockerfile
build_context: .
cache:
enabled: true
key: "{{ .Branch }}-docker-layer"
- step: docker_push
display_name: 推送 SWR
inputs:
image: swr.cn-north-4.myhuaweicloud.com/team/order-service:${IMAGE_TAG}
构建产物归档到软件发布库,记录构建号,方便追溯。
3.4 部署任务(CCE 测试环境)
在 CodeArts Deploy 建“Kubernetes 发布”任务:
- 集群:选择测试环境 CCE 集群
- 命名空间:
test - 部署配置:读取
k8s/deployment.yaml,自动替换镜像 tag
deployment.yaml 关键片段:apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: test
spec:
replicas: 2
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: swr.cn-north-4.myhuaweicloud.com/team/order-service:__IMAGE_TAG__
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
流水线部署时通过image_replace: true自动把__IMAGE_TAG__替换成当次构建版本。
3.5 编排流水线
CodeArts Pipeline 新建流水线,选空模板,按 4 个阶段编排:
阶段 1:代码检查
- 任务:CodeArts Check(门禁模式)
- 准出条件:Critical=0
阶段 2:构建与测试
- 任务 1:Maven 编译 + JUnit 单测 + Jacoco 覆盖率
- 任务 2:Docker 构建 + 推送 SWR
- 准出条件:构建成功 + 覆盖率 ≥ 60%(先宽松,逐步收紧到 80%)
阶段 3:测试环境部署
- 任务:Kubernetes 发布到
test命名空间 - 任务:TestPlan 接口冒烟测试
- 准出条件:冒烟测试通过
阶段 4:生产发布(人工卡点)
- 阶段准入类型:手动(需审批人确认)
- 任务:Kubernetes 灰度发布到
prod命名空间(先 1 个副本验证,再全量)
执行计划:
- 先手动触发跑通
- 稳定后开“代码提交触发”(仅
master和release/*分支)
关键建议:别一上来就开自动触发,否则你改一行配置都被流水线追着跑。
3.6 灰度发布与回滚
生产环境用滚动更新 + 灰度:
spec:
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
回滚方式(两条路):
- 快速回滚:
kubectl rollout undo deployment/order-service -n prod - 精准回滚:流水线重新执行历史构建号,部署旧镜像 tag
每次发布记录写入变更表:
CREATE TABLE deploy_history (
id BIGINT PRIMARY KEY,
build_no VARCHAR(64),
image_tag VARCHAR(128),
deployer VARCHAR(64),
env VARCHAR(16),
deploy_time DATETIME
);
四、验证结果
正常发布链路:
- 开发 push 到
feature/login - 提 MR 到
develop,触发流水线 - 代码检查通过 → 构建成功 → 测试环境部署 → 冒烟测试通过
- MR 合入,评审人审批
- 从
develop拉release/v1.3,再提 MR 到master - 生产卡点审批 → 灰度发布 → 全量
异常场景验证:
|
场景
|
预期
|
实际表现
|
|---|---|---|
|
代码检查报 SQL 注入
|
流水线阻断
|
Check 阶段标红,MR 无法合入
|
|
单测失败
|
构建阶段失败
|
Jacoco 覆盖率不达标,阻断
|
|
测试环境接口异常
|
不进生产
|
冒烟测试失败,卡点前停止
|
|
生产发布后健康检查失败
|
滚动更新自动回退
|
Readiness 探针不通过,旧副本继续服务
|
|
误发布错误版本
|
快速回滚
|
5 分钟内换回上一个 image tag
|
五、生产避坑清单
这部分是文章最有价值的地方。
❌ 常见错误
- 镜像用 latest 标签:回滚时不知道跑了哪个版本,排查地狱
- 检查规则全量开启:老项目一次性爆几百个问题,团队直接摆烂
- 生产环境自动触发:半夜一个 bad commit 直接上生产
- 没配就绪探针:Pod 还没启动完就接流量,大量 502
- 构建没开缓存:每次重新下依赖,构建时间从 3 分钟变 15 分钟
- 单测覆盖率门禁定太高:一开始定 80%,永远合不了代码
- 制品不归档:构建号丢了,出问题找不到对应包
- 没配通知:流水线挂了没人知道,靠用户投诉才发现
✅ 正确姿势
- 版本策略:语义化版本 + 构建号,镜像 tag 全局唯一
- 门禁渐进:检查规则先门禁模式,覆盖率从 40% 逐步提到 80%
- 多环境隔离:dev 自动部署、test 自动部署、prod 人工卡点
- 探针必配:readiness + liveness 双探针
- 缓存必开:Maven/npm 依赖缓存 + Docker 层缓存
- 通知必接:流水线失败推钉钉/企业微信,成功也播报
- 回滚演练:定期主动演练回滚,别等真出事再翻文档
六、总结与扩展
这条流水线解决了四个核心问题:
- 可追溯:每次发布绑定代码提交、构建号、镜像版本、操作人
- 可防护:代码检查 + 单测 + 冒烟测试,三层门禁拦截低级错误
- 可回滚:镜像版本化 + 滚动更新,5 分钟恢复
- 可扩展:加服务只要复制流水线模板,多环境一套配置
后续可继续演进:
- 安全左移:SWR 镜像漏洞扫描接入门禁,高危 CVE 阻断发布
- 变更管理:用 CodeArts 变更模型关联需求、代码、流水线、发布单
- 效能度量:采集部署频率、变更前置时间、MTTR,用数据驱动改进
- 多集群容灾:同城双活 + 跨区备份,Pipeline 支持多集群发布
- AI 辅助:用代码智能体自动补单测、分析失败日志、生成发布说明
本文为原创实践,基于华为云 CodeArts、SWR、CCE 等产品实测整理,操作步骤以当前控制台页面为准。转载请注明出处。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)