☰
Vue2+SpringBoot+Nacos在阿里云K8s的三类服务生命周期隔离实践
2026/10/13 1:27:43 网站建设 项目流程

简介:本资源是一套面向Kubernetes初学者与云原生实践者的完整部署方案,聚焦阿里云K8s环境下Vue2前端、SpringBoot2.5后端、Nacos2.0.3服务注册中心及Nginx反向代理的一站式集成部署。适用于微服务架构落地、容器化迁移学习及企业级前后端分离项目实战演练,尤其适合具备基础Docker与K8s概念的中级开发者快速上手。压缩包共16个文件,含8个YAML(覆盖Deployment、StatefulSet、Ingress、Service等核心资源定义)、2个Shell脚本(实现一键部署与环境初始化)、2个Dockerfile(分别构建Vue静态站点与SpringBoot应用镜像),以及SQL数据库初始化脚本、Nginx配置文件、JAR包和GZ压缩包等关键组件,整体大小为34.69MB。已有1340人学习下载,提供开箱即用的目录结构与模块化配置,涵盖前端dist打包、Nacos高可用部署、MySQL持久化配置及全链路服务暴露方案,显著降低K8s多组件协同部署门槛。

1. 阿里云 K8s 上跑 Vue2 + SpringBoot2.5 + Nacos2.0.3:不是堆组件,是理清三类服务的生命周期边界

你手头有个老 Vue2 单页应用,后端是 SpringBoot 2.5(JDK 8 兼容性刚需),注册中心必须用 Nacos 2.0.3(因历史服务强依赖其 gRPC 接口和命名空间隔离策略),还要上阿里云 ACK(Kubernetes)——这不是“把 Dockerfile 写完就完事”的玩具项目。真实踩坑点在于:Vue2 的静态资源怎么在 Nginx 容器里热更新不重启?SpringBoot 启动时连不上 Nacos,到底是网络策略没开、Service DNS 解析失败,还是 Nacos 客户端版本和 Server 2.0.3 不兼容?更隐蔽的是:Nacos 自身在 K8s 里用 PV 持久化后,升级时 etcd 数据迁移失败导致整个服务发现雪崩。我去年在金融客户现场复现过这套组合,最终稳定运行的关键,不是调参,而是把 Vue(纯静态)、SpringBoot(有状态中间件依赖)、Nacos(有状态核心中间件)这三类服务,在 K8s 中拆成完全独立的部署单元、网络域和健康检查逻辑。适合正在迁移老系统、被 SpringCloud Alibaba 版本锁死、又必须上云原生的中型团队——别信“一键部署脚本”,先搞懂每个 Pod 为什么活、为什么死。


2. 构建可复现的镜像:Vue2 静态资源打包与 SpringBoot 可执行包分离策略

2.1 Vue2 项目构建:用 nginx:alpine 基础镜像做最小化静态服务容器

Vue2 项目不能直接npm run serve上 K8s,必须走生产构建 + Nginx 托管。关键不是“能访问”,而是“构建产物路径可控、Nginx 配置可注入、缓存策略可灰度”。我们放弃nginx:latest,固定用nginx:1.22-alpine(对应 OpenSSL 1.1.1,兼容老浏览器 TLS 1.2),并把dist/目录结构和 Nginx 配置解耦:

# Dockerfile.vue2 FROM nginx:1.22-alpine # 删除默认配置,避免冲突 RUN rm -f /etc/nginx/conf.d/default.conf # 复制自定义 Nginx 配置(支持环境变量注入) COPY nginx.conf.template /etc/nginx/nginx.conf.template # 复制构建产物(注意:dist 目录必须存在,且 index.html 在根) COPY dist/ /usr/share/nginx/html/ # 启动前用 envsubst 替换模板中的环境变量(如 API 域名) CMD sed -i 's/\$\$API_BASE_URL/'"$API_BASE_URL"'/g' /etc/nginx/nginx.conf.template && \ mv /etc/nginx/nginx.conf.template /etc/nginx/nginx.conf && \ nginx -g "daemon off;"

提示:nginx.conf.template中必须用$$API_BASE_URL(双$是 shell 转义),否则envsubst会误替换$host等 Nginx 内置变量。这是 Vue2 项目在 K8s 里实现“一套镜像、多环境域名”的核心技巧。

2.2 SpringBoot 2.5 构建:禁用内嵌 Tomcat,打成 thin jar 并用 jre-alpine 运行

SpringBoot 2.5 默认带 Tomcat,但在 K8s 里它和 Nginx 形成双层代理,增加故障点。我们强制用 Undertow,并打成thin jar(依赖不打进包,由 K8s InitContainer 下载),减小镜像体积、加速拉取:

<!-- pom.xml 片段 --> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <spring-boot.version>2.5.17</spring-boot.version> </properties> <dependencies> <!-- 移除 spring-boot-starter-tomcat --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!-- 加入 undertow --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!-- 打成 thin jar --> <layout>ZIP</layout> <executable>false</executable> </configuration> </plugin> </plugins> </build>

构建命令:

mvn clean package -DskipTests # 输出 target/myapp-1.0.0.jar(thin jar)

然后写 SpringBoot 专用 Dockerfile:

# Dockerfile.springboot FROM openjdk:8-jre-alpine3.18 # 创建非 root 用户(安全基线要求) RUN addgroup -g 1001 -f appgroup && adduser -S appuser -u 1001 # 复制 thin jar COPY target/myapp-1.0.0.jar /app.jar # 设置启动用户 USER appuser # 启动命令:显式指定 JVM 参数,避免 OOM Kill ENTRYPOINT ["java","-Xms256m","-Xmx512m","-XX:+UseG1GC","-Dfile.encoding=UTF-8","-jar","/app.jar"]

参数说明:-Xms256m -Xmx512m是硬性要求。阿里云 ECS 的 cgroup v1 默认限制容器内存为 512MB,若不设-Xmx,JVM 会按宿主机内存比例分配(可能超限被 kill)。-XX:+UseG1GC是 JDK 8u212+ 对容器内存感知的必要开关。

2.3 Nacos 2.0.3 部署:用官方 Helm Chart,但必须重写 StatefulSet 的 volumeClaimTemplates

Nacos 2.0.3 的 K8s 部署最易翻车——官方 Helm Chart(nacos-k8s)默认用emptyDir,Pod 重建后集群元数据全丢。我们必须强制用阿里云 NAS 或云盘 PV,并修改volumeClaimTemplates使其匹配阿里云存储类:

# nacos-values.yaml(Helm values 文件) persistence: enabled: true # 必须匹配阿里云 ACK 集群中已创建的 StorageClass storageClassName: "alicloud-disk-ssd" accessModes: - ReadWriteOnce size: 20Gi # 关键:覆盖 StatefulSet 的 volumeClaimTemplates,确保 PVC 名称唯一且可预测 nacos: # 关闭自动创建 ServiceAccount(ACK 默认有) createServiceAccount: false # 指定 Nacos 配置中心使用 MySQL(生产必需,不能用内嵌 Derby) mysql: enabled: true host: "rds-mysql-xxx.mysql.rds.aliyuncs.com" port: "3306" database: "nacos_config" user: "nacos_user" password: "your_secure_password" # 阿里云 RDS 必须开启白名单:添加 ACK 集群节点 IP 段

安装命令:

helm repo add nacos https://nacos-group.github.io/nacos-k8s/ helm repo update helm install nacos nacos/nacos --version 1.2.0 -f nacos-values.yaml -n middleware

注意:Helm Chart 版本1.2.0对应 Nacos Server 2.0.3。不要用latest,否则会升级到 2.2.x,其 gRPC 端口和客户端 SDK 不兼容 SpringBoot 2.5 的nacos-client:2.0.3。


3. K8s 资源编排:Namespace、NetworkPolicy 与 Service 的三层隔离设计

3.1 按业务域划分 Namespace:frontend / backend / middleware

绝不把 Vue、SpringBoot、Nacos 放进同一个 Namespace。这是血泪经验:某次 Nacos Pod 因磁盘满被驱逐,kubectl delete ns middleware误删了同名的 backend 命名空间,导致整个订单服务不可用。正确做法:

# namespace.yaml apiVersion: v1 kind: Namespace metadata: name: frontend labels: team: web --- apiVersion: v1 kind: Namespace metadata: name: backend labels: team: java --- apiVersion: v1 kind: Namespace metadata: name: middleware labels: team: infra

为什么重要:阿里云 ACK 的 NetworkPolicy 默认作用于 Namespace 级别。frontend只能访问backend的 8080 端口,backend只能访问middleware的 8848 端口,middleware之间用 ClusterIP 通信——这种隔离让故障域收敛,也满足等保三级“网络区域划分”要求。

3.2 Service 类型选择:ClusterIP 为主,Ingress 仅用于 Vue2 流量入口

  • Vue2 服务:用Service Type=ClusterIP+Ingress暴露。因为 Vue2 是纯静态,Nginx 容器本身无状态,Ingress Controller(如 ALB Ingress)可做 SSL 卸载、WAF 防护、灰度发布。
  • SpringBoot 服务:只用ClusterIP。前端通过 Ingress 访问 Vue2,Vue2 的 axios 请求发往http://springboot-svc.backend:8080/api/xxx(K8s DNS 自动解析),不经过公网。
  • Nacos 服务:ClusterIP+ Headless Service(clusterIP: None)。因为 Nacos 集群节点需互相发现,必须用 Pod DNS(nacos-0.nacos-headless.middleware.svc.cluster.local)而非 Service VIP。
# service-nacos-headless.yaml apiVersion: v1 kind: Service metadata: name: nacos-headless namespace: middleware spec: clusterIP: None ports: - port: 8848 name: client - port: 9848 name: raft selector: app: nacos

3.3 NetworkPolicy:精确控制跨 Namespace 流量

这是阿里云 ACK 生产环境的硬性要求。以下 Policy 确保frontend只能访问backend的 8080,且backend只能访问middleware的 8848 和 3306(MySQL):

# network-policy.yaml apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: frontend-to-backend namespace: frontend spec: podSelector: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: name: backend ports: - protocol: TCP port: 8080 --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: backend-to-middleware namespace: backend spec: podSelector: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: name: middleware ports: - protocol: TCP port: 8848 - protocol: TCP port: 3306

验证命令:kubectl exec -n frontend vue2-pod -- curl -I http://springboot-svc.backend:8080/health应返回 200;curl http://nacos-svc.middleware:8848/nacos应超时(被 NetworkPolicy 拦截)。


4. 避坑:Nacos 连接失败、Vue2 404、SpringBoot 启动卡住的五大真实故障

4.1 现象:SpringBoot 启动日志卡在Waiting for nacos server to start...,30 秒后报No available server

原因:SpringBoot 客户端nacos-client:2.0.3默认用grpc协议连接 Nacos Server,但阿里云 ACK 的 CoreDNS 默认不解析nacos-0.nacos-headless.middleware.svc.cluster.local的 SRV 记录(gRPC 依赖 SRV 发现端口)。
解决:在 SpringBoot 的bootstrap.yml中强制关闭 gRPC,回退到 HTTP:

spring: cloud: nacos: discovery: server-addr: nacos-svc.middleware:8848 # 关键:禁用 gRPC,用 HTTP 心跳 metadata: preserved.heart.beat.interval: 5000 config: server-addr: nacos-svc.middleware:8848 # 强制用 HTTP 拉取配置 endpoint: http://nacos-svc.middleware:8848

4.2 现象:Vue2 页面打开后,所有 API 请求 404,但curl http://springboot-svc.backend:8080/actuator/health返回 200

原因:Vue2 的axios默认请求/api/xxx,而 Nginx 容器内未配置反向代理规则,请求直接 404(Nginx 找不到/api目录)。
解决:修改nginx.conf.template,添加 location 代理块:

location /api/ { proxy_pass http://springboot-svc.backend:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 关键:去除 /api 前缀再转发 proxy_redirect off; }

注意proxy_pass末尾的/,它会 strip/api/前缀。没有这个/,请求会变成http://.../api/xxx,后端收不到。

4.3 现象:Nacos 控制台登录成功,但 SpringBoot 服务列表为空,nacos-server日志报failed to request

原因:Nacos Server 2.0.3 默认开启auth(权限认证),但 SpringBoot 客户端未传 token。
解决:在 Nacos 控制台(http://nacos-svc.middleware:8848/nacos)创建用户springboot,密码123456,然后在 SpringBoot 的bootstrap.yml中加:

spring: cloud: nacos: discovery: username: springboot password: 123456 config: username: springboot password: 123456

4.4 现象:kubectl get pods -n middleware显示nacos-0一直CrashLoopBackOff,日志Failed to connect to MySQL

原因:阿里云 RDS 白名单未放通 ACK 集群节点网段,或 RDS 安全组未开放 3306 端口。
解决:

  1. 进入阿里云 RDS 控制台 → 白名单分组 → 编辑default分组 → 添加 ACK 集群 VPC 网段(如172.20.0.0/16);
  2. RDS 实例 → 安全组 → 添加入方向规则:端口3306,授权对象0.0.0.0/0(测试用)或集群节点 IP 段;
  3. 在nacos-values.yaml中确认mysql.host是 RDS 的内网地址(非公网),避免走公网延迟。

4.5 现象:Vue2 页面加载极慢,F12 查看 Network,index.html200,但app.js、chunk-vendors.js返回 404

原因:Vue2vue.config.js中publicPath配置错误。若用publicPath: '/',构建产物路径为/js/app.js,但 Nginx 容器内index.html在/usr/share/nginx/html/,相对路径解析失败。
解决:vue.config.js中设publicPath: './'(相对路径),并确保dist/目录结构扁平:

module.exports = { publicPath: './', // 关键:生成相对路径引用 outputDir: 'dist', assetsDir: 'static' }

构建后检查dist/index.html中 script 标签是否为<script src="./js/app.js">,而非<script src="/js/app.js">。


5. 生产级验证:用 kubectl + curl + Prometheus 三步闭环检测服务健康

5.1 第一步:K8s 层面验证 Pod 就绪与 Service 连通性

不要只看kubectl get pods的Running状态,要验证Ready列(如1/1)和STATUS列(非CrashLoopBackOff)。对三个 Namespace 分别执行:

# 检查 frontend(Vue2) kubectl get pods -n frontend # 验证 Vue2 容器内能否解析 backend Service kubectl exec -n frontend deploy/vue2 -- sh -c "nslookup springboot-svc.backend" # 检查 backend(SpringBoot) kubectl get pods -n backend # 验证 SpringBoot 能否连通 Nacos(从容器内 curl) kubectl exec -n backend deploy/springboot -- curl -s -o /dev/null -w "%{http_code}" http://nacos-svc.middleware:8848/nacos/v1/ns/service/list # 检查 middleware(Nacos) kubectl get pods -n middleware # 验证 Nacos 集群节点数(StatefulSet 应为 3) kubectl get statefulset -n middleware

关键指标:nslookup必须返回springboot-svc.backend.svc.cluster.local的 A 记录;curl对 Nacos 的/nacos/v1/ns/service/list必须返回200(非503),证明服务发现接口可用。

5.2 第二步:业务层面验证 API 链路(绕过 Ingress,直击 ClusterIP)

用kubectl port-forward暴露内部 Service,模拟前端真实调用链:

# 在本地终端执行(保持长连接) kubectl port-forward svc/springboot-svc 8080:8080 -n backend & kubectl port-forward svc/nacos-svc 8848:8848 -n middleware & # 验证 SpringBoot 健康接口(直连 ClusterIP) curl http://localhost:8080/actuator/health # 验证 Nacos 配置中心(直连 ClusterIP) curl "http://localhost:8848/nacos/v1/cs/configs?dataId=myapp-dev.yaml&group=DEFAULT_GROUP" # 验证 Vue2 静态资源(需先构建并推镜像) kubectl port-forward svc/vue2-svc 8081:80 -n frontend & curl http://localhost:8081/ # 应返回 index.html curl http://localhost:8081/js/app.js # 应返回 JS 内容

玄学排查:若curl http://localhost:8080/actuator/health返回404,检查 SpringBoot 的management.endpoints.web.base-path是否为/actuator(默认值),且management.endpoints.web.exposure.include包含health。

5.3 第三步:接入 Prometheus + Grafana,监控 Nacos 注册实例数与 SpringBoot GC 时间

阿里云 ACK 内置 ARMS Prometheus,只需添加 ServiceMonitor。创建monitoring.yaml:

apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: nacos-monitor namespace: middleware spec: selector: matchLabels: app: nacos endpoints: - port: prometheus interval: 30s path: /actuator/prometheus --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: springboot-monitor namespace: backend spec: selector: matchLabels: app: springboot endpoints: - port: management interval: 30s path: /actuator/prometheus

然后在 Grafana 中导入 Dashboard ID12856(Spring Boot Actuator),重点关注:

  • jvm_memory_used_bytes:确认内存使用率 < 70%;
  • process_uptime_seconds:确认进程未频繁重启;
  • nacos_monitor_instance_count(Nacos 自带指标):确认注册实例数 > 0。

血泪经验:曾因nacos_monitor_instance_count为 0,排查 3 小时才发现 SpringBoot 的spring.cloud.nacos.discovery.group配置成了PROD_GROUP,而 Nacos 控制台创建的是DEFAULT_GROUP,大小写敏感导致服务注册失败。


6. 进阶技巧:用阿里云 ARMS 实现 Vue2 前端错误追踪与 SpringBoot 链路染色

6.1 Vue2 前端错误捕获:用 ARMS Web SDK 替代 Sentry,直连阿里云 SLS

Sentry 需自建服务,而阿里云 ARMS 提供开箱即用的前端监控。在 Vue2 的main.js中注入:

// main.js import Arms from '@alicloud/alipay-arms-web' Arms.start({ pid: 'your-arms-pid', // 阿里云 ARMS 控制台获取 enableLinkTrace: true, // 开启链路追踪 enableResourceReport: true, // 上报 JS/CSS 加载性能 enableErrorReport: true, // 上报 JS 错误 enableConsoleReport: true, // 上报 console.error // 关键:设置采样率,避免日志爆炸 sampleRate: 0.1, // 关键:过滤敏感字段(如 token、手机号) ignoreFields: ['token', 'phone', 'idCard'] }) new Vue({ render: h => h(App), }).$mount('#app')

效果:ARMS 控制台 → 前端监控 → 错误分析,可看到TypeError: Cannot read property 'xxx' of undefined的完整堆栈、影响用户数、发生页面 URL。比console.log高效 10 倍。

6.2 SpringBoot 链路染色:用 ARMS Java Agent 实现 Vue2 → SpringBoot → Nacos 全链路

不改一行代码,用阿里云 ARMS Java Agent 实现分布式追踪。步骤:

  1. 下载 ARMS Agent( 官网链接 ),上传到 ACK 集群某节点;
  2. 修改 SpringBoot Deployment,挂载 Agent 并注入 JVM 参数:
# deployment-springboot.yaml apiVersion: apps/v1 kind: Deployment metadata: name: springboot namespace: backend spec: template: spec: containers: - name: app image: your-registry/springboot:1.0.0 # 挂载 ARMS Agent volumeMounts: - name: arms-agent mountPath: /opt/arms volumes: - name: arms-agent hostPath: path: /path/to/arms-agent # 注入 JVM 参数 args: ["-javaagent:/opt/arms/arms-agent.jar", "-Darms.pid=your-arms-pid", "-Darms.appName=springboot-prod"]
  1. 在application.yml中启用 Spring Cloud Sleuth(ARMS Agent 会自动识别):
spring: sleuth: sampler: probability: 1.0 # 100% 采样(生产建议 0.1) zipkin: base-url: http://arms-zipkin.arms.svc.cluster.local:9411 # ARMS 内置 Zipkin 地址

验证方法:在 Vue2 页面触发一个 API 请求 → ARMS 控制台 → 分布式追踪 → 搜索该请求 TraceID → 查看完整链路:Vue2 Browser → SpringBoot Pod → Nacos Server → MySQL,每段耗时、状态码、SQL 语句一目了然。

6.3 最后一道防线:用阿里云 SLS 日志审计,抓取所有4xx/5xx请求

K8s 的kubectl logs只能看实时日志,而 SLS 可做长期审计。在 ACK 控制台开启日志采集:

  • 采集源:frontendNamespace 下所有 Pod 的 stdout;
  • 过滤条件:status >= 400(Nginx access log);
  • 告警规则:count(*) > 100 in 5m,通知钉钉群。

这样,当 Vue2 页面突然大量401 Unauthorized,SLS 告警会立刻推送,你不用等用户投诉。

从那以后我每次上线新版本,都强制走一遍kubectl port-forward直连验证 + ARMS 链路追踪截图 + SLS 错误日志快照,三份证据存档。不是怕出问题,是怕出问题时找不到第一现场。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询