《从传统部署到云原生:华为云 CCE 容器化改造实战记录》

举报
yd_243668775 发表于 2026/10/30 08:12:02 2026/10/30
【摘要】 从传统部署到云原生:华为云 CCE 容器化改造实战记录一、背景笔者所在团队此前维护一套 Java Spring Boot + MySQL 的业务系统,部署在自建机房的三台物理服务器上。随着业务量增长,传统部署方式的痛点越来越明显:扩容需要手动装环境、版本回滚靠人工切换、服务器故障恢复耗时数小时。经过调研对比,我们最终选择华为云 CCE(云容器引擎)作为容器化改造的目标平台,本文记录整个改造过...

从传统部署到云原生:华为云 CCE 容器化改造实战记录

一、背景

笔者所在团队此前维护一套 Java Spring Boot + MySQL 的业务系统,部署在自建机房的三台物理服务器上。随着业务量增长,传统部署方式的痛点越来越明显:扩容需要手动装环境、版本回滚靠人工切换、服务器故障恢复耗时数小时。经过调研对比,我们最终选择华为云 CCE(云容器引擎)作为容器化改造的目标平台,本文记录整个改造过程中的关键步骤和踩坑经验,供有同样需求的同行参考。

二、改造前的架构

改造前的部署架构比较简单:

  • 3 台物理服务器,通过 Nginx 做负载均衡
  • 每台服务器上手动部署 JDK 1.8、JAR 包、Nginx
  • MySQL 主从部署在其中两台服务器上
  • 配置文件散落在各服务器本地,修改需逐台登录

这种方式最大的问题是环境不一致:某台服务器上的 JDK 小版本不同,导致一次线上故障排查了三个小时。这也是推动我们容器化的直接原因。

三、容器化改造步骤

3.1 应用 Docker 化改造

第一步是将 Spring Boot 应用容器化。编写 Dockerfile 如下:

FROM openjdk:8-jre-slim
WORKDIR /app
COPY target/app.jar /app/app.jar
ENV JAVA_OPTS="-Xms512m -Xmx512m -Dspring.profiles.active=prod"
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.jar"]

几个关键点:

  • 选用 jre-slim 而非完整 JDK 镜像,镜像体积从 600MB 降到 180MB
  • JAVA_OPTS 通过环境变量传入,方便在 CCE 中按需调整
  • spring.profiles.active 设为 prod,配合外部化配置

3.2 创建 CCE 集群

在华为云控制台创建 CCE 集群时,有以下经验:

  • 集群版本:选择 1.25 及以上的稳定版本,避免选最新版本踩兼容性坑
  • 网络模型:选择 VPC 网络模型,容器网络与 VPC 子网打通,便于和 RDS 等云服务通信
  • 节点规格:业务节点选用 s6.large.2(2核4G),初始 2 个节点,配合弹性伸缩应对流量高峰
  • 可用区:节点分布在两个可用区,避免单可用区故障导致服务不可用

3.3 数据库迁移至 RDS

将 MySQL 从自建迁移到华为云 RDS,主要考量:

  • 自建 MySQL 的备份、主从同步、安全补丁都需要人工维护,迁移到 RDS 后这些由云平台托管
  • RDS 默认开启自动备份,支持按时间点恢复,比自建方案可靠得多
  • 通过内网 VPC 与 CCE 集群通信,数据库不暴露公网,安全性大幅提升

迁移过程使用 DRS(数据复制服务)做在线迁移,业务停机时间控制在 5 分钟以内。

3.4 编写 Kubernetes 部署清单

应用部署使用 Deployment,配合 Service 对外暴露:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: business-app
  template:
    metadata:
      labels:
        app: business-app
    spec:
      containers:
      - name: app
        image: swr.cn-north-4.myhuaweicloud.com/namespace/app:v1
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_DATASOURCE_URL
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: url
        resources:
          requests:
            cpu: 500m
            memory: 512Mi
          limits:
            cpu: 1000m
            memory: 1024Mi
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10

几个实践要点:

  • 资源请求和限制必须设置:不设 limits 的容器可能吃光节点内存,导致其他 Pod 被驱逐
  • 存活探针和就绪探针都要配:就绪探针确保只有启动完成的 Pod 接收流量,存活探针在应用卡死时自动重启
  • 数据库密码用 Secret 管理:不要明文写在配置清单里
  • 镜像存放在 SWR(容器镜像服务):私有镜像仓库,拉取速度快,内网传输不计流量

3.5 配置弹性伸缩

为应对业务流量波动,配置了 HPA(水平 Pod 自动伸缩):

  • 最小副本数 3,最大副本数 10
  • 基于 CPU 利用率伸缩,目标值 70%
  • 在 CCE 控制台可以直接创建,也可以用 YAML 声明式管理

实际运行中,工作日早高峰流量增长时,Pod 从 3 个自动扩到 6 个,整个过程约 30 秒完成,相比以前手动加机器节省了大量时间。

3.6 对外暴露与负载均衡

使用 CCE 自带的 ELB(弹性负载均衡)Ingress 对外暴露服务:

  • 创建 Ingress 关联 Service,自动创建 ELB 实例
  • 配置健康检查路径 /actuator/health
  • 开启会话保持,保证同一用户的请求路由到同一 Pod

四、踩坑记录

坑一:Pod 启动慢被误杀

Spring Boot 应用启动需要约 50 秒,但最初 livenessProbe 的 initialDelaySeconds 只设了 30 秒,导致 Pod 还没启动完就被判定为不健康而重启,形成无限重启循环。

解决:将 livenessProbe 的 initialDelaySeconds 调到 60 秒,readinessProbe 设 30 秒。就绪探针先通过,存活探针后生效,问题解决。

坑二:节点资源不足导致 Pod 调度失败

2 核 4G 的节点上跑了 3 个 Pod,每个请求 500m CPU、512Mi 内存,看起来够用。但节点本身有系统组件开销,实际可用资源只有约 1.5 核 3G,导致第三个 Pod 一直 Pending。

解决:调整节点规格到 s6.xlarge.2(4核8G),或在节点上开启资源超卖(不太推荐生产环境)。最终我们选择了升级节点规格。

坑三:镜像拉取失败

最初将镜像推送到公网镜像仓库,拉取速度慢且偶尔超时失败。

解决:将镜像迁移到华为云 SWR,与 CCE 集群在同一 Region,内网拉取速度从分钟级降到秒级,再未出现拉取失败。

五、改造效果

改造完成后,对比改造前的主要变化:

对比项 改造前 改造后
扩容方式 手动装环境,约 1 小时 HPA 自动伸缩,约 30 秒
版本回滚 手动切换 JAR 包,约 15 分钟 kubectl rollout undo,约 30 秒
故障恢复 重新部署,数小时 Pod 自动重启,秒级
环境一致性 各服务器环境可能不一致 容器镜像保证完全一致
数据库运维 人工备份、补丁 RDS 托管,自动备份

六、总结与建议

这次容器化改造的核心收益不是技术本身,而是运维方式的转变——从"手动操作每台机器"变成"声明式配置、自动伸缩、自愈恢复"。

给准备做类似改造的同行几点建议:

  1. 先容器化再上 K8s:先把应用打成 Docker 镜像,在本地用 docker compose 跑通,再迁移到 CCE,降低一次性改动的风险
  2. 数据库不要急着容器化:有状态服务容器化的复杂度远高于无状态服务,建议先用 RDS 托管,应用层先容器化
  3. 资源限制一定要设:不设 limits 的容器是集群不稳定的最大隐患
  4. 探针配置要匹配应用启动时间:initialDelaySeconds 要大于应用实际启动时间,否则会反复重启
  5. 善用 CCE 控制台的可视化功能:对于 K8s 经验不多的团队,控制台的可视化部署、监控、日志功能能大幅降低学习曲线

以上是本次改造的完整记录,希望对正在考虑容器化迁移的同行有所帮助。云原生不是一蹴而就的,但每一步的改进都是实实在在的。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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