从零搭建华为云CCE集群并部署Spring Boot应用:一次完整的云原生实践
前言
作为一名后端开发者,我之前一直用传统虚拟机部署应用——买ECS、装JDK、配Nginx、写启动脚本,每次升级都要手动操作,回滚更是噩梦。最近团队决定迁移到云原生架构,我负责调研和落地。本文记录了我在华为云CCE(云容器引擎)上从零搭建集群、构建镜像、部署Spring Boot应用的完整过程,以及踩过的坑,希望能帮到同样在转型路上的同学。
一、为什么选择CCE
说实话,自建K8s集群的运维成本太高了——etcd备份、证书续期、节点扩缩容,每一项都是体力活。CCE作为华为云的托管K8s服务,控制面由华为云维护,我只需要关心工作节点和应用本身。加上CCE与VPC、ELB、EVS等华为云服务深度集成,网络和存储的配置几乎是"开箱即用"。
二、搭建集群
2.1 创建VPC和子网
先在网络控制台创建一个VPC,网段用192.168.0.0/16,然后在其中创建一个子网192.168.0.0/24。这一步没什么特别,按需分配即可。需要注意的是,子网要预留足够的IP地址,因为每个Pod都会占用一个IP,节点扩容也需要IP。我的经验是,如果预计跑50个Pod,子网至少留100个IP。
2.2 创建CCE集群
在CCE控制台点击"创建集群",选择Turbo版(CCE Turbo支持容器网络增强,Pod直接占用VPC子网IP,网络性能更好)。关键配置如下:
- 集群版本:选择1.25以上的稳定版本,太新的版本可能有些特性还不成熟。
- 节点规格:测试环境用s6.large.2(2核4G)就够了,生产环境建议c6.2xlarge.2(8核16G)起步。
- 节点OS:选EulerOS 2.5,华为自研的容器优化镜像,启动快、占用低。
- 容器网络:选VPC网络模式,Pod直接使用子网IP,方便和同VPC下的RDS等内网服务通信。
集群创建大约需要10-15分钟,耐心等待状态变为"运行中"。
2.3 连接集群
集群创建完成后,在控制台下载kubectl配置文件,放到~/.kube/config目录下。执行kubectl get nodes,能看到节点列表就说明连接成功了。
这里有个小坑:如果你在本地用Mac,下载的kubeconfig里的server地址是内网IP,本地连不上。解决办法是在集群详情页开启"kubectl连接(公网)"功能,会自动绑定一个EIP,kubeconfig里的地址也会更新为公网地址。
三、构建并推送容器镜像
3.1 编写Dockerfile
Spring Boot应用的Dockerfile我优化过几版,目前用的是多阶段构建:
# 构建阶段
FROM maven:3.8-openjdk-17 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 运行阶段
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
多阶段构建的好处是最终镜像不包含Maven和源码,体积从800MB降到了约180MB,拉取速度快了不少。
3.2 推送到SWR
华为云的容器镜像服务SWR(Software Repository for Container)和Docker Hub用法基本一致。先在SWR控制台创建一个组织(比如myteam),然后登录:
docker login -u {区域}@{AK} swr.{区域}.myhuaweicloud.com
密码填SK。登录成功后给镜像打tag并推送:
docker tag myapp:latest swr.cn-north-4.myhuaweicloud.com/myteam/myapp:v1.0
docker push swr.cn-north-4.myhuaweicloud.com/myteam/myapp:v1.0
SWR的一个优势是同区域拉取镜像走内网,速度快且不占公网带宽。
四、部署应用
4.1 创建Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: swr.cn-north-4.myhuaweicloud.com/myteam/myapp:v1.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 500m
memory: 1Gi
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
资源请求和限制一定要设置,否则一个Pod异常可能把整个节点的资源吃光。readinessProbe配置了健康检查,只有通过检查的Pod才会接收流量,避免请求打到还在启动的实例上。
4.2 创建Service和Ingress
Service负责集群内部的服务发现,Ingress负责外部访问:
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
kubernetes.io/elb.class: union
kubernetes.io/elb.id: "{ELB_ID}"
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-svc
number: 80
这里用到了CCE的一个特性:通过annotation指定ELB实例,Ingress控制器会自动在ELB上创建监听器和后端服务器组。我提前在ELB控制台创建了一个共享型ELB,把它的ID填进去即可。
五、配置自动伸缩
生产环境流量波动大,手动调副本数不现实。CCE支持HPA(水平Pod自动伸缩),配置如下:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
当CPU利用率超过70%时自动扩容,低于阈值时缩容。配合CCE的节点伸缩策略,连节点都能自动加减,真正实现了"弹性"。
六、踩坑记录
坑一:镜像拉取失败。 刚开始部署时Pod一直ImagePullBackOff。原因是CCE集群默认没有SWR的拉取权限。解决办法是在集群详情页的"插件管理"中安装"容器镜像拉取插件"(everest),并给节点绑定的IAM委托添加SWR的读取权限。
坑二:Pod无法访问RDS。 应用启动时报数据库连接超时。排查发现RDS的安全组只放通了原来的ECS内网IP段,没有放通CCE子网网段。在RDS安全组规则中添加CCE子网的入站规则后解决。这也是前面建议用VPC网络模式的原因——Pod的IP在子网范围内,安全组配置更直观。
坑三:日志查看不便。 kubectl logs只能看当前Pod的日志,Pod重建后日志就丢了。后来接入了LTS(云日志服务),在CCE插件管理中安装LTS插件,所有容器日志自动采集到LTS,可以在控制台搜索和过滤,排查问题方便了很多。
七、总结
从传统部署迁移到CCE,最大的感受是"声明式"带来的安心感——所有配置都在YAML文件里,版本可控、可复现、可回滚。初期学习曲线确实存在,但一旦跑通,后续的迭代和运维效率提升是显著的。
以上是我在实践中的一些记录,很多细节因环境而异,仅供参考。如果有不对的地方,欢迎评论区交流指正。
- 点赞
- 收藏
- 关注作者
评论(0)