news 2026/10/28 11:25:18

Vue2+SpringBoot2.5+Nacos2.0.3 上阿里云K8s部署避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue2+SpringBoot2.5+Nacos2.0.3 上阿里云K8s部署避坑指南

简介:面向需要在阿里云Kubernetes集群上落地前后端分离项目的开发者,这套资源给出Vue2前端、SpringBoot2.5后端与Nacos2.0.3注册配置中心的一体化部署参考,适合已具备容器与K8s基础、希望打通镜像构建到服务编排全流程的中高级读者。压缩包共16个文件、约34.69MB,以8个yaml清单为主,覆盖Nacos的StatefulSet、Service、Headless、Ingress及MySQL配置等编排对象;另有2个sh部署脚本、2个Dockerfile、1份Nacos建库sql、1份nginx.conf,以及前端dist打包产物与后端jar,基本构成可直接参照的部署素材。资源已有1342人学习下载,说明其在同类场景中具备一定参考价值。读者可据此理解Nacos集群在K8s中的持久化与数据库初始化方式,掌握Vue静态资源经Nginx容器化的配置要点,并借助脚本与清单梳理SpringBoot服务的发布路径,减少自行拼装编排文件时的试错成本。

1. 一次镜像拉取失败,让我重新梳理了整套部署链路

去年帮一个朋友的公司迁移一套老系统,前端 Vue2 打包后塞进 Nginx,后端 SpringBoot 2.5,注册配置中心用 Nacos 2.0.3,目标是把这套东西整体搬上阿里云 K8s。听起来是标准三件套,结果第一次kubectl apply之后,Pod 卡在ImagePullBackOff整整两个小时,排查下来是私有镜像仓库的 secret 没挂到正确的 namespace 上。这种坑不装一遍根本想不到。这套组合在国内中小团队里极其常见,Vue2 加 Nginx 做静态资源服务,SpringBoot 2.5 做业务后端,Nacos 2.0.3 管服务注册和配置,最后统一编排到阿里云 ACK 集群。装不好会怎样?前端 404、后端连不上 Nacos、健康检查一直失败、滚动更新卡死,每一个都能让你加班到半夜。这篇笔记面向正在把这套环境往 K8s 上搬的开发者,新手能照着走通,熟手能看到版本取舍和参数细节。

2. 环境准备与版本选型:先把地基打对

2.1 集群与本地工具链的版本对齐

动手之前先把版本钉死,这套组合里最容易出问题的不是代码,是版本错配。SpringBoot 2.5 对应的是 Spring Cloud 2020.0.x 系列,Nacos 客户端版本要跟服务端的 2.0.3 对齐,Vue2 的构建产物是纯静态文件,对 Node 版本反而没那么敏感,但 Nginx 的基础镜像版本会影响配置语法支持。

我一般会先把本地工具链和集群版本列成一张表,避免后面来回试:

组件推荐版本说明
阿里云 ACK 集群1.24 及以上1.24 之后 Dockershim 移除,注意运行时
kubectl与集群大版本差不超过 1版本偏差过大会出现字段不识别
Docker20.10.x本地构建镜像用
Node.js14.x 或 16.xVue2 项目建议锁 14/16,别上 18
JDK8 或 11SpringBoot 2.5 两者都支持
Nacos2.0.3服务端与客户端保持一致
Nginx1.21 或 1.23基础镜像选 alpine 版体积小

这里有个反直觉的点:很多人以为集群版本越新越好,但 ACK 1.24 之后默认容器运行时从 Docker 换成了 containerd,如果你本地用 Docker 构建镜像再推到 ACR(阿里云容器镜像服务),推拉本身没问题,问题出在调试时习惯性docker exec进节点,结果节点上根本没有 docker 命令。我一般会在集群创建后先确认运行时:

# 查看节点容器运行时,确认是 docker 还是 containerd kubectl get nodes -o wide kubectl describe node <节点名> | grep -i "container runtime"

输出里如果是containerd://1.6.x,那节点层面的排查命令就要换成crictl,这个细节不提前确认,后面排错会绕很多弯路。参数上没什么可调的,关键是心里有数。

2.2 命名空间、镜像仓库与拉取凭证

这套系统我习惯单独开一个 namespace,不跟其他业务混在一起,资源配额和网络策略都好管。镜像仓库用阿里云的 ACR,个人版够用,企业版有更细的权限控制。创建 namespace 和拉取 secret 是第一步:

# 创建独立命名空间 kubectl create namespace vue-spring-nacos # 基于 ACR 账号密码创建镜像拉取 secret kubectl create secret docker-registry acr-cred \ --docker-server=registry.cn-hangzhou.aliyuncs.com \ --docker-username=<你的ACR用户名> \ --docker-password=<你的ACR密码> \ --namespace=vue-spring-nacos

--docker-server要填你 ACR 实例所在地域的完整域名,填错了 secret 虽然能创建成功,但拉镜像时依然会 401。--namespace必须跟后面 Deployment 所在的 namespace 一致,这就是我开头踩的那个坑——secret 建在了 default 里,Pod 在业务 namespace 里当然找不到。常见做法是把 secret 和 Deployment 写在同一个 YAML 文件里,用---分隔,apply 的时候一起生效,省得漏。

另外提醒一句,ACR 个人版的仓库地址和 VPC 内网地址不一样,集群在 VPC 内的话优先用内网地址拉镜像,速度快还不走公网流量。这个在 ACR 控制台的仓库基本信息里能看到,别直接复制公网地址就往 YAML 里贴。

3. 三个组件的镜像构建:Vue2、SpringBoot 2.5 与 Nacos 2.0.3

3.1 Vue2 前端打包与 Nginx 镜像

Vue2 项目构建产物是dist目录,Nginx 镜像要做的事很简单:把 dist 拷进去,替换默认配置。Dockerfile 我一般这么写:

# 前端镜像:基于 nginx alpine,体积小启动快 FROM nginx:1.23-alpine # 删掉默认配置,避免和自定义配置冲突 RUN rm -f /etc/nginx/conf.d/default.conf # 拷贝自定义 nginx 配置 COPY nginx.conf /etc/nginx/conf.d/app.conf # 拷贝 Vue2 构建产物 COPY dist/ /usr/share/nginx/html/ EXPOSE 80

对应的nginx.conf里最关键的是 history 路由的 fallback,Vue2 用 history 模式时刷新页面会 404,必须配try_files:

server { listen 80; server_name _; root /usr/share/nginx/html; index index.html; # Vue2 history 模式核心配置,找不到文件就回退到 index.html location / { try_files $uri $uri/ /index.html; } # 后端接口反向代理,指向 K8s 内部 Service location /api/ { proxy_pass http://springboot-svc:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

proxy_pass末尾那个斜杠很关键,带斜杠会把/api/前缀剥掉再转发,不带则原样转发,后端接口路径对不上就是这里的问题。springboot-svc是后面要建的 Service 名,K8s 内部 DNS 直接解析,不用写 IP。构建命令就一句docker build -t registry.cn-hangzhou.aliyuncs.com/<命名空间>/vue-web:v1 .,推之前记得docker login。

3.2 SpringBoot 2.5 镜像与 Nacos 客户端配置

SpringBoot 2.5 的镜像我用多阶段构建,编译和运行分开,运行镜像只留 JRE:

# 构建阶段 FROM maven:3.8-openjdk-8 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline -B COPY src ./src RUN mvn clean package -DskipTests # 运行阶段,只保留 JRE FROM openjdk:8-jre-slim WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]

dependency:go-offline这步是为了利用 Docker 层缓存,pom 没变就不会重新拉依赖,构建快很多。运行阶段用openjdk:8-jre-slim而不是完整 JDK,镜像能小一半。

Nacos 2.0.3 的客户端配置在application.yml里,这里有个 2.0 之后的坑:2.0 版本 Nacos 增加了 gRPC 通信,默认端口是主端口加 1000,也就是 8848 对应 9848,K8s 里如果只暴露了 8848,客户端会连不上。配置长这样:

spring: cloud: nacos: discovery: server-addr: nacos-svc:8848 namespace: ${NACOS_NAMESPACE:public} config: server-addr: nacos-svc:8848 file-extension: yaml namespace: ${NACOS_NAMESPACE:public}

server-addr用 K8s Service 名,不要写具体 Pod IP。namespace用环境变量注入,不同环境用不同命名空间隔离配置。注意 Nacos 2.0.3 客户端连服务端时,9848 端口必须通,这个在 Service 定义里要一起暴露,后面第 4 章会讲。

3.3 Nacos 2.0.3 服务端镜像与持久化

Nacos 服务端我建议直接用官方镜像nacos/nacos-server:2.0.3,不要自己从头构建。但官方镜像默认用内嵌 Derby 数据库,生产环境必须换成 MySQL,否则重启配置就丢。环境变量这么配:

env: - name: MODE value: "standalone" # 单机模式,集群模式改 cluster - name: SPRING_DATASOURCE_PLATFORM value: "mysql" - name: MYSQL_SERVICE_HOST value: "mysql-svc" - name: MYSQL_SERVICE_DB_NAME value: "nacos_config" - name: MYSQL_SERVICE_USER value: "nacos" - name: MYSQL_SERVICE_PASSWORD value: "<数据库密码>" - name: NACOS_AUTH_ENABLE value: "true" # 开启鉴权,2.0.3 支持

MODE选 standalone 适合中小规模,真要集群就改 cluster 并配NACOS_SERVERS列表。NACOS_AUTH_ENABLE开了之后客户端也要配用户名密码,别忘了。MySQL 那边要提前建库并导入 Nacos 2.0.3 自带的mysql-schema.sql,这个脚本在官方包的 conf 目录里,版本不对会导致表结构缺失,启动报错。

4. K8s 编排落地:Deployment、Service 与配置注入

4.1 前端与后端 Deployment 的关键参数

Deployment 的 YAML 里,除了镜像和端口,最容易被忽略的是探针和资源限制。前端是静态服务,探针简单;后端启动慢,探针的initialDelaySeconds要给够,不然 Pod 还没起来就被判定失败重启,陷入循环。

apiVersion: apps/v1 kind: Deployment metadata: name: springboot-app namespace: vue-spring-nacos spec: replicas: 2 selector: matchLabels: app: springboot-app template: metadata: labels: app: springboot-app spec: imagePullSecrets: - name: acr-cred containers: - name: app image: registry.cn-hangzhou.aliyuncs.com/<命名空间>/springboot-app:v1 ports: - containerPort: 8080 resources: requests: cpu: "500m" memory: "512Mi" limits: cpu: "1" memory: "1Gi" readinessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 40 # SpringBoot 启动慢,给足时间 periodSeconds: 10 livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 60 periodSeconds: 20

imagePullSecrets必须写在spec.template.spec下,写在 Deployment 顶层是无效的,这是另一个高频错误。readinessProbe的initialDelaySeconds给 40 秒是因为 SpringBoot 2.5 加上 Nacos 注册,冷启动通常要 20 到 30 秒,给少了就反复重启。/actuator/health需要 pom 里引入spring-boot-starter-actuator并暴露端点,没配的话探针一直 404,Pod 永远不 Ready。

4.2 Service 暴露与 Nacos 双端口处理

Service 这块,前端用 ClusterIP 加 Ingress 对外,后端和 Nacos 用 ClusterIP 内部通信。Nacos 2.0.3 的 Service 要同时暴露 8848 和 9848:

apiVersion: v1 kind: Service metadata: name: nacos-svc namespace: vue-spring-nacos spec: selector: app: nacos ports: - name: http port: 8848 targetPort: 8848 - name: grpc port: 9848 targetPort: 9848 # Nacos 2.0 gRPC 端口,少这个客户端连不上 type: ClusterIP

9848 这个端口是 Nacos 2.0 之后新增的,客户端启动时会尝试建立 gRPC 长连接,Service 里没暴露就会一直重连失败,日志里刷Client not connected。我见过有人排查半天以为是网络策略问题,其实就是 Service 少写了一个端口。前端 Ingress 的配置按阿里云 ACK 的 Ingress 控制器来写,注解里指定证书和后端 Service 即可,这里不展开。

4.3 ConfigMap 与 Secret 的注入方式

配置注入我一般分两类:非敏感的放 ConfigMap,密码类放 Secret。SpringBoot 的application.yml里数据库密码、Nacos 密码这些不要硬编码,用环境变量引用:

apiVersion: v1 kind: ConfigMap metadata: name: app-config namespace: vue-spring-nacos data: NACOS_NAMESPACE: "prod" SPRING_PROFILES_ACTIVE: "k8s" --- apiVersion: v1 kind: Secret metadata: name: app-secret namespace: vue-spring-nacos type: Opaque stringData: DB_PASSWORD: "<数据库密码>" NACOS_PASSWORD: "<Nacos密码>"

然后在 Deployment 里用envFrom一次性注入:

envFrom: - configMapRef: name: app-config - secretRef: name: app-secret

stringData比data好用,直接写明文,K8s 自动帮你 base64 编码,省得手动转。但注意 Secret 只是编码不是加密,生产环境要配合 KMS 或者外部密钥管理,这个看团队规范。ConfigMap 改了之后 Pod 不会自动重启,需要kubectl rollout restart deployment/springboot-app -n vue-spring-nacos手动触发,这个习惯要养成。

5. 避坑与排查:五个真实翻车记录

5.1 镜像拉取失败:secret 挂错位置

现象是 Pod 状态ImagePullBackOff,kubectl describe pod里事件显示unauthorized或pull access denied。原因九成是imagePullSecrets没写或者写错层级,要么就是 secret 建在了别的 namespace。解决方法是先确认 secret 存在:kubectl get secret acr-cred -n vue-spring-nacos,再检查 Deployment 的spec.template.spec.imagePullSecrets字段,两处都对还不行就用kubectl get secret acr-cred -n vue-spring-nacos -o yaml看里面的.dockerconfigjson解码后 server 地址对不对。

5.2 Nacos 客户端连不上:9848 端口没通

现象是 SpringBoot 启动日志刷com.alibaba.nacos.api.exception.NacosException: Client not connected,或者注册一直失败。原因是 Nacos 2.0 的 gRPC 端口 9848 没在 Service 里暴露,或者 NetworkPolicy 拦了。解决方法是检查 Service 的 ports 列表有没有 9848,再kubectl exec进后端 Pod 用nc -zv nacos-svc 9848测连通性。如果集群开了网络策略,还要放行对应端口。

5.3 前端刷新 404:history 模式没配 fallback

现象是首页能打开,点进子路由再刷新就 404。原因是 Nginx 没配try_files,请求的路径在磁盘上找不到对应文件。解决方法是在nginx.conf的location /里加try_files $uri $uri/ /index.html;,改完重新构建镜像推上去。这个坑几乎每个 Vue2 上 Nginx 的人都会踩一次,记住就好。

5.4 后端反复重启:探针时间给太短

现象是 Pod 的 RESTARTS 计数一直涨,kubectl describe里显示 liveness probe failed。原因是 SpringBoot 冷启动超过探针的initialDelaySeconds,还没起来就被判定死亡。解决方法把initialDelaySeconds调到 60 以上,failureThreshold适当加大,或者干脆先只留 readinessProbe,等稳定了再加 liveness。我一般会先kubectl logs看启动耗时,按实际时间加 20 秒余量。

5.5 Nacos 重启配置丢失:还在用内嵌 Derby

现象是 Nacos Pod 重启后,之前注册的服务和配置全没了。原因是SPRING_DATASOURCE_PLATFORM没设成 mysql,默认走了内嵌 Derby,数据存在容器里,重启即丢。解决方法是确认环境变量配了 mysql 相关参数,并且 MySQL 里已经导入对应版本的 schema。改完重建 Pod,再注册一个测试服务验证持久化生效。

6. 装完怎么验证:从 Pod 状态到端到端链路

部署完别急着交付,按顺序验证一遍才算跑通。第一步看 Pod 和 Service 状态:

# 所有资源状态,Running 且 READY 为 1/1 才算正常 kubectl get pods,svc -n vue-spring-nacos # 看事件,排查 Pending 或重启原因 kubectl describe pod <pod名> -n vue-spring-nacos | tail -20

第二步验证 Nacos 注册是否生效,进 Nacos 控制台或者直接调 API:

# 通过 Nacos OpenAPI 查服务列表,确认后端已注册 kubectl exec -it <任意pod> -n vue-spring-nacos -- \ curl -s "http://nacos-svc:8848/nacos/v1/ns/service/list?pageNo=1&pageSize=10"

返回的doms里能看到 SpringBoot 服务名,说明注册链路通了。第三步验证前端到后端的完整调用,用kubectl port-forward把前端 Service 映射到本地,浏览器访问并触发一个调后端的接口:

# 本地映射前端服务,浏览器访问 localhost:8080 验证页面和接口 kubectl port-forward svc/vue-web-svc 8080:80 -n vue-spring-nacos

页面能打开、子路由刷新不 404、接口返回正常数据,这三条都过才算端到端跑通。最后再模拟一次滚动更新,kubectl set image换个镜像 tag,观察新 Pod 起来、旧 Pod 优雅退出,确认探针和优雅停机配置没问题。

我自己的习惯是每次部署完必走一遍这个清单,尤其是 Nacos 的 9848 端口和前端 fallback 这两项,翻车概率最高。从那以后我每次上这套组合,都强制先把 Service 端口和探针时间在纸上列一遍再 apply,省下的排查时间远比多花的那十分钟值。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 11:25:08

现代插件系统设计:安全、性能与跨语言实践

1. 插件系统的时代背景与核心挑战2003年Mozilla首次提出NPAPI插件标准时&#xff0c;没人预料到二十年后的插件生态会如此复杂。现代应用对插件系统的需求早已从简单的功能扩展&#xff0c;演变为需要兼顾安全隔离、性能优化、跨平台支持和开发体验的系统级工程问题。我经历过从…

作者头像 李华
网站建设 2026/10/28 11:24:52

AI闲置处理机制:从心跳检测到资源回收优化

1. 项目背景与现象解析"我没惹任何AI&#xff0c;只是没用了"这个标题折射出当下一个有趣的技术现象&#xff1a;当用户停止与AI系统交互后&#xff0c;系统会如何反应&#xff1f;这种现象在智能客服、推荐系统、语音助手等领域尤为常见。作为从业者&#xff0c;我观…

作者头像 李华
网站建设 2026/10/28 11:23:48

先正达中国战略:农业科技研发与智能制造布局

1. 先正达集团全球研发与制造布局的战略解析先正达集团作为全球农业科技领域的领军企业&#xff0c;近期在中国加速布局全球级研发中心和制造工厂的举措引发了行业广泛关注。这一战略动作背后&#xff0c;体现的是跨国农业巨头对中国市场的深度看好&#xff0c;以及全球农业产业…

作者头像 李华
网站建设 2026/10/28 11:23:39

PropertyTree开源房产租赁管理后台源码解析与二次开发指南

简介&#xff1a;PropertyTree 是一款面向 C#/WinForms 开发者的开源控件&#xff0c;用于将控件组与 TreeView 节点建立关联&#xff1a;当用户在树形导航中选择不同节点时&#xff0c;界面会自动切换显示对应的控件组&#xff0c;从而解决传统多面板界面中控件堆叠、切换繁琐…

作者头像 李华
网站建设 2026/10/28 11:23:20

SQL Server日志膨胀的根源与解决方案

1. SQL Server日志膨胀的根源与危害数据库日志文件&#xff08;.ldf&#xff09;是SQL Server事务日志的物理载体&#xff0c;记录所有数据修改操作。当这个文件不受控制地增长时&#xff0c;会引发一系列运维问题。我曾处理过一个生产案例&#xff0c;某电商平台的订单数据库日…

作者头像 李华
网站建设 2026/10/28 11:23:06

C++期末sizeof排名与对象模型详解:虚函数、内存对齐、状态模式

简介&#xff1a;面向吉林大学软件学院、计算机学院学生的2016年C期末考试题详解文档&#xff0c;围绕类与对象、继承多态、运算符重载、静态成员、异常处理、抽象类与纯虚函数、命名空间及状态模式等核心考点展开&#xff0c;适合期末复习、查漏补缺与考前自测。资源包共1个do…

作者头像 李华