从手工发布到一键交付:用华为云 CodeArts 搭建生产级 CI/CD 流水线

举报
yd_280727371 发表于 2026/10/28 09:18:07 2026/10/28
【摘要】 一、背景与痛点我们一个内部订单服务,最初是这样发布的:# 本地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 &
看着简单,实际踩坑不断:
  1. 环境不一致:本地 JDK 17 编的包,服务器 JDK 11 跑不起来
  2. 发布不可追溯:谁发的、发了什么版本、改了哪些代码,全靠群里喊
  3. 回滚靠手速:出问题 git revert 再走一遍流程,平均恢复 20 分钟
  4. 没质量卡点:一个空指针都能发上生产,靠用户报错才发现
  5. 多人协作乱:两个人同时发,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
回滚方式(两条路):
  1. 快速回滚:kubectl rollout undo deployment/order-service -n prod
  2. 精准回滚:流水线重新执行历史构建号,部署旧镜像 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
);

四、验证结果

正常发布链路:
  1. 开发 push 到 feature/login
  2. 提 MR 到 develop,触发流水线
  3. 代码检查通过 → 构建成功 → 测试环境部署 → 冒烟测试通过
  4. MR 合入,评审人审批
  5. 从 develop 拉 release/v1.3,再提 MR 到 master
  6. 生产卡点审批 → 灰度发布 → 全量
异常场景验证:

场景
预期
实际表现
代码检查报 SQL 注入
流水线阻断
Check 阶段标红,MR 无法合入
单测失败
构建阶段失败
Jacoco 覆盖率不达标,阻断
测试环境接口异常
不进生产
冒烟测试失败,卡点前停止
生产发布后健康检查失败
滚动更新自动回退
Readiness 探针不通过,旧副本继续服务
误发布错误版本
快速回滚
5 分钟内换回上一个 image tag

五、生产避坑清单

这部分是文章最有价值的地方。
❌ 常见错误
  1. 镜像用 latest 标签:回滚时不知道跑了哪个版本,排查地狱
  2. 检查规则全量开启:老项目一次性爆几百个问题,团队直接摆烂
  3. 生产环境自动触发:半夜一个 bad commit 直接上生产
  4. 没配就绪探针:Pod 还没启动完就接流量,大量 502
  5. 构建没开缓存:每次重新下依赖,构建时间从 3 分钟变 15 分钟
  6. 单测覆盖率门禁定太高:一开始定 80%,永远合不了代码
  7. 制品不归档:构建号丢了,出问题找不到对应包
  8. 没配通知:流水线挂了没人知道,靠用户投诉才发现
✅ 正确姿势
  • 版本策略:语义化版本 + 构建号,镜像 tag 全局唯一
  • 门禁渐进:检查规则先门禁模式,覆盖率从 40% 逐步提到 80%
  • 多环境隔离:dev 自动部署、test 自动部署、prod 人工卡点
  • 探针必配:readiness + liveness 双探针
  • 缓存必开:Maven/npm 依赖缓存 + Docker 层缓存
  • 通知必接:流水线失败推钉钉/企业微信,成功也播报
  • 回滚演练:定期主动演练回滚,别等真出事再翻文档

六、总结与扩展

这条流水线解决了四个核心问题:
  • 可追溯:每次发布绑定代码提交、构建号、镜像版本、操作人
  • 可防护:代码检查 + 单测 + 冒烟测试,三层门禁拦截低级错误
  • 可回滚:镜像版本化 + 滚动更新,5 分钟恢复
  • 可扩展:加服务只要复制流水线模板,多环境一套配置
后续可继续演进:
  1. 安全左移:SWR 镜像漏洞扫描接入门禁,高危 CVE 阻断发布
  2. 变更管理:用 CodeArts 变更模型关联需求、代码、流水线、发布单
  3. 效能度量:采集部署频率、变更前置时间、MTTR,用数据驱动改进
  4. 多集群容灾:同城双活 + 跨区备份,Pipeline 支持多集群发布
  5. AI 辅助:用代码智能体自动补单测、分析失败日志、生成发布说明

本文为原创实践,基于华为云 CodeArts、SWR、CCE 等产品实测整理,操作步骤以当前控制台页面为准。转载请注明出处。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。