华为云CCE+鲲鹏节点池:信创应用容器化上云实战指南
文章摘要:华为云 CCE(Cloud Container Engine)是信创场景下首选的容器平台。本文记录了如何创建 CCE 集群、配置鲲鹏节点池、将一个 Spring Boot 应用从自建 K8s 迁移到 CCE 的全过程。重点讲清楚了 CCE 的计费模式选型、节点池配置的最佳实践,以及迁移过程中遇到的 3 个坑和解决方式。
为什么选择 CCE?
在信创场景下,CCE(Cloud Container Engine)对比自建 K8s 的优势:
| 对比项 | 自建 K8s(裸机) | 华为云 CCE |
|---|---|---|
| Master 节点 | 自己运维 + 升级 | 华为云托管 |
| 故障恢复 | 手动处理 etcd 故障 | 自动恢复 |
| 鲲鹏节点 | 自己找 ARM64 镜像 | 一键创建鲲鹏节点池 |
| 存储对接 | 手动配置 CSI | 集成 EVS/OBS/SFS |
| 网络 | Calico 自运维 | 集成 VPC 网络 |
| 安全 | 自己做 | 集成容器安全 CGS |
第一步:创建 CCE 集群
通过控制台
# 也可以用 huaweicloud CLI 创建,更可重复
hcloud CCE CreateCluster \
--name="xinchuang-prod" \
--flavor="cce.s2.medium" \
--version="v1.28" \
--container_network_type="vpc-router" \
--eni_network=false \
--vpc_id="vpc-xxx" \
--subnet_id="subnet-xxx"
关键参数说明
# cluster-config.yaml
apiVersion: v1
kind: Cluster
name: xinchuang-prod
spec:
# Master 节点规格(生产集群建议 s2 系列)
flavor: cce.s2.medium # 1000 节点规模
# 容器网络(VPC 网络性能最好)
containerNetwork:
mode: vpc-router # vpc-router / tunnel / eni
cidr: 10.0.0.0/16 # 不要跟 VPC 网段重叠
# 服务网络
serviceNetwork:
cidr: 10.247.0.0/16
第二步:配置鲲鹏节点池
# 创建鲲鹏节点池
hcloud CCE AddNodePool \
--cluster_id="${CLUSTER_ID}" \
--name="kunpeng-pool-32c" \
--node_template='{
"flavor": "kc1.4xlarge.2", # 32C/64GB 鲲鹏通用计算型
"os": "EulerOS 2.9",
"root_volume": {
"volumetype": "SSD",
"size": 100
},
"data_volumes": [{
"volumetype": "SSD",
"size": 200
}],
"count": 5,
"max_pods": 110
}'
节点规格选型
| 用途 | 规格 | 配置 | 月成本(估) |
|---|---|---|---|
| 通用 Web | kc1.2xlarge.2 | 16C/32GB | ¥1,200 |
| 高内存 | kc1.4xlarge.4 | 32C/128GB | ¥3,800 |
| 数据库 | kc1.4xlarge.2 | 32C/64GB + 高IO磁盘 | ¥4,500 |
| AI 推理 | kc1p.4xlarge | 32C/64GB + NPU | ¥5,000 |
CCE + 鲲鹏节点池整体架构
下图展示了 CCE 集群与鲲鹏节点池的整体架构,包括 VPC 网络、控制面托管、节点池分组、存储集成和 Ingress 流量入口。

架构说明:
- CCE 控制面由华为云托管,用户无需运维 Master 节点,自动升级、自动容灾
- 节点池按架构分组(x86 / 鲲鹏),通过节点亲和性确保工作负载调度到正确架构
- 存储层按场景选择:单副本用 EVS、多副本用 SFS、日志归档用 OBS
- 中间件使用华为云托管服务(DCS/DDS/RDS),降低运维负担
- 流量入口通过 CCE Ingress 分发,支持灰度发布和蓝绿部署
第三步:迁移 Spring Boot 应用到 CCE
原来的部署
# k8s-deploy.yaml(跟自建 K8s 完全一样,不用改)
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: registry.company.com/order-service:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod-kunpeng"
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "4"
memory: "8Gi"
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 60
tolerations:
- key: "kunpeng"
operator: "Exists"
# 部署到 CCE(跟自建 K8s 用法一样)
kubectl apply -f k8s-deploy.yaml
# 暴露服务
kubectl expose deployment order-service \
--name=order-service-svc \
--type=LoadBalancer \
--port=80 --target-port=8080
完整 YAML 配置集(生产推荐)
生产环境中建议将配置拆分为多个 YAML 文件,便于管理和灰度发布。
# 1. configmap.yaml —— 应用配置外置
apiVersion: v1
kind: ConfigMap
metadata:
name: order-service-config
namespace: default
data:
application-prod-kunpeng.yml: |
server:
port: 8080
spring:
datasource:
url: jdbc:opengauss://og-master:5432/order_db
username: order_user
password: ${DB_PASSWORD}
logging:
level:
com.company.order: INFO
---
# 2. deployment.yaml —— 完整版含亲和性 + 存储挂载
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: default
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "node.kubernetes.io/instance-type"
operator: In
values:
- "kunpeng"
containers:
- name: order-service
image: registry.company.com/order-service:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
name: http
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod-kunpeng"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
- name: JAVA_OPTS
value: "-Xms4g -Xmx4g -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError"
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "4"
memory: "8Gi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /app/config
readOnly: true
- name: logs
mountPath: /app/logs
volumes:
- name: config
configMap:
name: order-service-config
- name: logs
emptyDir: {}
tolerations:
- key: "kunpeng"
operator: "Exists"
---
# 3. service.yaml —— ClusterIP 供内部调用 + Headless 用于治理
apiVersion: v1
kind: Service
metadata:
name: order-service-svc
namespace: default
labels:
app: order-service
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: 8080
protocol: TCP
name: http
selector:
app: order-service
---
# 4. ingress.yaml —— 通过 CCE Ingress 对外暴露
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: order-service-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: cce
spec:
rules:
- host: order.xinchuang.company.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: order-service-svc
port:
number: 8080
---
# 5. hpa.yaml —— 基于 CPU 和内存的自动弹性伸缩
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
namespace: default
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
一次性创建所有资源:
kubectl apply -f configmap.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
kubectl apply -f hpa.yaml
# 一键应用所有 YAML(推荐)
kubectl apply -f ./
1. 节点选择器没配,Pod 调度到了 x86 节点
现象:应用在鲲鹏节点池上部署后,P99 延迟从原来的 35ms 降到了 52ms。
原因:镜像虽然支持 multi-arch,但它被调度到了 x86 节点上(如果同时有 x86 和鲲鹏节点池)。x86 节点规格更小,导致性能下降。
解决:添加节点亲和性
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "node.kubernetes.io/instance-type"
operator: In
values:
- "kunpeng"
2. 镜像架构不对,容器启动失败
现象:Deployment 创建后 Pod 一直处于 CrashLoopBackOff 状态,kubectl logs 看到 exec format error。
$ kubectl logs order-service-7d8f9c6b4f-abc12
standard_init_linux.go: exec: exec format error
原因:镜像构建在 x86 机器上,没有做 ARM64 交叉编译。鲲鹏节点是 ARM64 架构,x86 的二进制无法直接运行。即使节点池选对了,镜像本身不支持 ARM64 也白搭。
解决:使用多架构镜像构建(Docker Buildx),或直接在鲲鹏节点上编译。
# 方案 A:Docker Buildx 构建多架构镜像(推荐)
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t registry.company.com/order-service:latest \
--push .
# 方案 B:CI/CD 中分别构建两个标签
docker build -t registry.company.com/order-service:amd64-latest . # x86 构建
docker build -t registry.company.com/order-service:arm64-latest . # ARM64 构建
# 方案 C:在 Deployment 中明确指定架构
# 结合 nodeSelector 使用,只拉取对应架构的镜像
💡 经验:镜像架构问题是最隐蔽的坑。我们的 CI 流水线最开始只在 x86 构建机上跑
docker build,推上去的镜像是 amd64 格式,部署到鲲鹏节点上就报exec format error。后来改成 Buildx 多架构构建,同时在 Deployment 中加上nodeSelector: kubernetes.io/arch: arm64兜底。
3. Pod 启动成功但存储挂载失败
现象:Pod 启动正常,应用日志报 “Permission denied” 或 “Directory not empty”,无法读写挂载的 EVS 磁盘。
$ kubectl exec order-service-7d8f9c6b4f-abc12 -- ls -la /data
ls: cannot open directory '/data': Permission denied
原因分析:CCE 使用的 EVS 卷默认挂载到节点后,Pod 内的用户(UID 非 root)没有写入权限。另外,如果 PVC 的 accessModes 配置为 ReadWriteOnce,多个副本间共用一个卷时第二个 Pod 会挂载失败。
# 错误配置:accessModes 不匹配多副本场景
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: order-data-pvc
spec:
accessModes:
- ReadWriteOnce # 只能被一个 Pod 挂载
resources:
requests:
storage: 100Gi
解决:根据场景选择合适的存储方案。
# 方案 A:单副本读写 —— 使用 EVS 高性能盘,注意 fsGroup
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
template:
spec:
securityContext:
fsGroup: 1000 # 与容器内 UID 一致
runAsUser: 1000
volumes:
- name: data
persistentVolumeClaim:
claimName: order-data-pvc
---
# 方案 B:多副本共享读写 —— 使用 SFS(NFS)替代 EVS
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: order-shared-pvc
spec:
accessModes:
- ReadWriteMany # 多节点多 Pod 同时读写
storageClassName: csi-nas # 使用 SFS 文件存储
resources:
requests:
storage: 200Gi
💡 经验:第一次遇到这个问题时,我们排查了 2 天 —— 容器日志没有明确错误,只是应用启动后写入文件失败。最终通过
kubectl exec进入容器用id命令发现容器内进程是 UID 1000,而 EVS 卷归属 root。加上fsGroup后问题解决。多副本场景一定要用 SFS 而不是 EVS,否则第二个 Pod 永远起不来。
计费模式选型
| 计费模式 | 适合场景 | 成本(对比按需) |
|---|---|---|
| 按需 | 测试/临时任务 | 基准 |
| 包年包月(1 年) | 稳定生产负载 | -25% |
| 包年包月(3 年) | 长期稳定 | -45% |
| 竞价实例 | 批处理/弹性扩展 | -70% |
推荐策略:基础资源用包年包月 + 弹性资源用竞价实例。我们的 5 个鲲鹏节点中 3 个包年包月(保底容量)+ 2 个按需(高峰期自动扩容)。
常见问题(FAQ)
Q1:CCE 集群创建后,可以同时管理 x86 和鲲鹏节点池吗?
可以。 CCE 集群支持混合节点池架构,你可以在同一个集群下创建 x86 节点池和鲲鹏(ARM64)节点池。关键是要通过 nodeAffinity 和 nodeSelector 确保工作负载调度到正确的架构节点上。建议为不同架构的节点池打上差异化的标签(如 node.kubernetes.io/instance-type: kunpeng),并在 Deployment 中指定亲和性规则。
Q2:鲲鹏节点上的镜像从哪里获取?必须自己编译吗?
两种方式:
- 使用华为云 SWR 镜像仓库:SWR 支持多架构镜像(manifest list),拉取时会自动匹配节点架构。你只需要用
docker buildx构建多架构镜像并推送到 SWR,CCE 会按需拉取对应版本。 - 使用华为开源镜像站:华为云维护了适配鲲鹏的常用开源镜像(如 Nginx、Redis、MySQL、Java 等),搜索 “Kunpeng” + 软件名即可找到。
推荐使用方案 1,自己维护基础镜像可以确保安全合规。
Q3:鲲鹏节点池的节点可以自动扩缩容吗?
支持。 CCE 提供了节点池的自动伸缩能力(Cluster Autoscaler),配置步骤:
- 在节点池中开启「弹性伸缩」开关
- 设置最小/最大节点数(如 min: 3, max: 10)
- 结合 HPA(Horizontal Pod Autoscaler)实现 Pod 级别的弹性
当业务高峰期 Pod 调度失败时,CCE 会自动触发节点池扩容;低谷时自动缩容释放资源。注意竞价实例节点不支持自动缩容到 0。
Q4:迁移到 CCE 后,之前自建 K8s 的 YAML 文件还能用吗?
绝大多数可以原封不动使用。 CCE 兼容标准的 Kubernetes API,Deployment、Service、Ingress、ConfigMap、Secret 等资源定义完全一致。需要调整的主要有两点:
- 存储类(StorageClass)名称:自建 K8s 用的存储类名(如
managed-nfs-storage)需要改为 CCE 的存储类名(如csi-disk、csi-nas) - Ingress 注解:如果使用 Nginx Ingress Controller,需改为 CCE 的
kubernetes.io/ingress.class: cce注解
除此之外,应用层的 YAML 基本不用改动。
Q5:CCE 的运维成本比自建 K8s 高多少?
实际上更低。 这里算一笔账:
| 成本项 | 自建 K8s(3 Master + 10 Node) | CCE(10 Node + 托管 Master) |
|---|---|---|
| Master 节点 ECS 费用 | 3 × ¥800 = ¥2,400/月 | ¥0(托管免费) |
| Master 运维人力 | 约 0.5 人天/周(升级+巡检) | ¥0(华为云负责) |
| 故障恢复 SLA | 自行保障 | 华为云 99.95% |
| 网络/存储集成 | 手动配置 | 内置集成 |
结论:CCE 托管集群虽然有一定的集群管理费(通常几百元/月),但省去了 Master 节点的 ECS 费用和运维人力成本,综合成本更低。
CCE + 鲲鹏节点池部署信创应用完整流程
下图展示了从创建节点池到监控运维的全流程,涵盖资源准备、应用部署、弹性伸缩和日常运维四个阶段。

流程说明:
- 阶段一(资源准备):创建 CCE 集群 + 鲲鹏节点池,配置节点规格和亲和性标签,为后续调度打好基础
- 阶段二(应用部署):核心是解决镜像架构兼容性(Buildx 多架构构建)和存储选型(EVS/SFS/OBS 按需选择)
- 阶段三(弹性伸缩):HPA + Cluster Autoscaler 双层弹性,高峰期自动扩容、低谷期自动缩容
- 阶段四(监控运维):AOM 监控 + 告警规则 + 日志查询 + WDR 报告,形成闭环运维体系
总结
CCE + 鲲鹏节点池是华为云信创容器化最推荐的方案。主要优势:
- Master 托管,不需要运维 K8s 控制面
- 鲲鹏节点一键创建,不用手动配置 ARM64 环境
- K8s 原生的方式部署应用,不需要学习新的编排方式
迁移过程比预想的顺利 —— 应用层的 YAML 文件一行不改,只需要加上 nodeSelector 保证调度到鲲鹏节点。
下篇文章讲在 CCE 上部署 openGauss 容器化主备集群。
你们用的是什么云上的容器服务?CCE 还是自建 K8s?评论区聊聊。
- 点赞
- 收藏
- 关注作者
评论(0)