ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Vue2+SpringBoot2.5+Nacos2.0.3 在 K8s 上的前后端分离部署实战

Vue2+SpringBoot2.5+Nacos2.0.3 在 K8s 上的前后端分离部署实战 简介这份资源面向需要在阿里云Kubernetes集群上落地前后端分离项目的开发与运维人员围绕Vue2前端、Nginx、SpringBoot2.5后端与Nacos2.0.3注册配置中心提供一套可直接参考的容器化部署编排方案适合已具备一定K8s基础、希望打通微服务上线流程的中高级读者。压缩包共16个文件约34.69MB以8个yaml编排清单为核心配合2个sh部署脚本、2个Dockerfile镜像构建文件以及Nacos所需的sql初始化脚本、nginx.conf配置、jar应用包和gz前端产物覆盖从镜像构建到服务发布的完整链路。资源已有1342人学习下载具备一定参考热度。读者可从中获得Vue与SpringBoot应用的镜像构建思路、Nacos基于StatefulSet与Headless Service的集群化部署写法、MySQL数据初始化方式及Ingress对外暴露配置并借助一键部署脚本快速复现环境减少自行拼装清单时的试错成本。1. 一套能跑通的前后端分离部署链路到底卡在哪很多团队第一次把 Vue2 前端、SpringBoot2.5 后端和 Nacos2.0.3 注册中心往 K8s 上搬卡点往往不在镜像构建而在“服务发现怎么接、配置怎么灌、Nginx 怎么把请求转进集群”。本地 docker-compose 跑得好好的一上集群就出现前端 502、后端注册不上 Nacos、Pod 反复重启。这套部署方案要解决的就是这条完整链路Vue2 静态资源交给 Nginx 托管SpringBoot 以 Deployment 形式注册进 NacosNacos 自身用 StatefulSet 保证数据一致。适合已经会写 Dockerfile、但对 K8s 编排还停留在kubectl apply阶段的后端和运维同学照着走能少踩几轮“玄学”网络坑。2. 镜像与配置先行三个组件的构建边界上集群之前先把三个组件的镜像和配置边界划清楚。这一步做扎实后面 K8s 清单只是“搬运”做不扎实Pod 起来了也是黑匣子。2.1 Vue2 前端多阶段构建把 dist 塞进 NginxVue2 项目常见做法是本地npm run build再手动拷 dist上了 CI 就不可复现。我一般用多阶段构建把 Node 编译环境和 Nginx 运行环境分开最终镜像只留静态文件和 Nginx 配置。# 阶段一编译 Vue2 FROM node:14-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm install --registryhttps://registry.npmmirror.com COPY . . RUN npm run build # 阶段二Nginx 托管静态资源 FROM nginx:1.21-alpine COPY --frombuilder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80逻辑说明第一阶段用 Node14 编译npm install单独 COPY package 文件是为了利用镜像层缓存源码改动不会触发依赖重装。第二阶段只拷 dist 和自定义 nginx.conf镜像体积能压到 30MB 左右。参数上注意npm run build的产物目录要和 COPY 路径一致Vue CLI 默认是distVite 项目要改成dist对应实际输出。Nginx 配置里最关键的是把/api转发到后端 Service而不是写死 Pod IPserver { listen 80; location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; # Vue history 路由回退 } location /api/ { proxy_pass http://springboot-svc:8080/; # 指向 K8s Service proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }try_files那行是 Vue Router history 模式的后悔药不加的话刷新子路由直接 404。proxy_pass末尾的斜杠决定路径是否截断/api/配http://svc:8080/会把/api/user转成/user配成不带斜杠则保留/api/user这个细节翻车的人不少。2.2 SpringBoot2.5Nacos 客户端版本要对齐SpringBoot2.5 对应 Spring Cloud 2020.0.xNacos 客户端要用2021.1这个 starter 版本别拿2.2.x的老 starter 硬配否则启动时报NoSuchMethodError。pom 里关键依赖dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId version2021.1/version /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId version2021.1/version /dependencybootstrap.yml里把 Nacos 地址指向集群内 Service不要写公网 IPspring: application: name: springboot-svc cloud: nacos: discovery: server-addr: nacos-svc:8848 config: server-addr: nacos-svc:8848 file-extension: yaml参数说明spring.application.name必须和 K8s Service 名一致Nacos 注册的服务名就是它前端 Nginx 转发也认这个名字。server-addr用nacos-svc:8848依赖集群 DNS前提是 Nacos 的 Service 已经建好所以部署顺序是先 Nacos 后后端。配置中心拉取失败时先kubectl exec进 Pod 里nslookup nacos-svc确认 DNS 通不通比看日志快。2.3 Nacos2.0.3StatefulSet 而非 DeploymentNacos2.0 默认用内嵌 Derby单机够用但集群模式必须外接 MySQL且每个节点要有稳定网络标识所以用 StatefulSet。镜像用nacos/nacos-server:2.0.3环境变量里指定数据库env: - name: MODE value: 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: nacos123 - name: NACOS_SERVERS value: nacos-0.nacos-headless:8848 nacos-1.nacos-headless:8848 nacos-2.nacos-headless:8848NACOS_SERVERS必须用 headless Service 的完整域名普通 ClusterIP Service 解析不出每个 Pod 的独立地址集群选主会失败。MySQL 库要先导入 Nacos 自带的mysql-schema.sql2.0.3 的表结构和 1.x 有差异别拿旧脚本凑合。3. K8s 清单落地从 Service 到探针的编排细节镜像推上去之后K8s 清单决定服务能不能稳定对外。这一章按“先通后稳”的顺序拆先让三个组件互相能访问再补探针和资源限制。3.1 三类 Service 的选型与端口映射前端用 NodePort 或 Ingress 暴露后端和 Nacos 用 ClusterIP 内部通信。Nacos 额外需要一个 headless Service 给 StatefulSet 用apiVersion: v1 kind: Service metadata: name: nacos-headless spec: clusterIP: None selector: app: nacos ports: - port: 8848 name: client - port: 9848 name: grpc注意 9848 端口Nacos2.0 新增了 gRPC 通信端口偏移量是主端口 1000客户端连 8848 时会自动连 9848。只开 8848 不开 9848服务注册能成功但配置监听会断现象是配置改了不生效这个坑很隐蔽。后端 Service 就常规 ClusterIPapiVersion: v1 kind: Service metadata: name: springboot-svc spec: selector: app: springboot ports: - port: 8080 targetPort: 8080port是 Service 暴露端口targetPort是容器实际监听端口两者不一致时排查先看kubectl get endpoints springboot-svc有没有后端地址为空说明 selector 没匹配上 Pod 标签。3.2 Deployment 的探针与启动顺序SpringBoot 启动慢Nacos 客户端注册还要时间liveness 探针配太激进会导致还没注册完就被杀掉重启。我一般给 startupProbe 留足窗口startupProbe: httpGet: path: /actuator/health port: 8080 failureThreshold: 30 periodSeconds: 5 livenessProbe: httpGet: path: /actuator/health port: 8080 periodSeconds: 10 readinessProbe: httpGet: path: /actuator/health port: 8080 periodSeconds: 5failureThreshold: 30乘periodSeconds: 5等于 150 秒启动窗口够 SpringBoot2.5 加 Nacos 注册走完。/actuator/health要确认management.endpoints.web.exposure.includehealth已开否则探针 404 一直失败。readiness 控制流量接入Nacos 注册完成前不让 Nginx 转发过来避免前端 502。3.3 配置注入ConfigMap 与环境变量怎么分工非敏感配置走 ConfigMap 挂载数据库密码走 Secret。SpringBoot 的application.yml里 Nacos 地址这类集群相关配置用环境变量覆盖比改镜像更灵活env: - name: SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR value: nacos-svc:8848 - name: SPRING_PROFILES_ACTIVE value: k8sSpringBoot 的 relaxed binding 会把SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR映射到spring.cloud.nacos.discovery.server-addr这样同一镜像能在测试和生产复用。ConfigMap 挂载的 yml 用subPath挂单个文件别整个目录覆盖否则镜像里自带的配置全丢。4. 避坑排查五个真实翻车现场部署链路上有些问题日志不报错只能靠现象反推。下面五条是我和同事踩过的按“现象 → 原因 → 解决”记下来。4.1 前端刷新 404现象首页能开点进子路由再刷新就 404。原因是 Nginx 没配try_files请求/user/list时去找对应静态文件找不到。解决location /里加try_files $uri $uri/ /index.html;让所有未命中路径回退到 index.html 交给 Vue Router。4.2 后端注册不上 Nacos现象Pod 日志报failed to req API:/nacos/v1/ns/instance但nslookup nacos-svc能通。原因多半是 Nacos 集群没起来headless Service 的 Pod 没 Ready或者 9848 端口没开。解决先kubectl get pods -l appnacos确认三个副本 Running再检查 Service 是否暴露 9848最后看 Nacos 日志里Nacos started successfully有没有出现。4.3 配置中心改了不生效现象Nacos 控制台改了配置后端日志显示监听成功但值没变。原因是bootstrap.yml没生效SpringBoot2.5 默认不加载 bootstrap 上下文需要引入spring-cloud-starter-bootstrap依赖。解决加这个 starter或者把 Nacos 配置挪到application.yml用spring.config.import方式引入。4.4 Pod 反复重启现象kubectl get pods显示 RESTARTS 持续增长describe 里Last State: Terminated, Reason: Error。原因是 liveness 探针在启动阶段就判死。解决加 startupProbe 兜住启动期liveness 的initialDelaySeconds别小于 60或者干脆让 liveness 依赖 startupProbe 成功后再计时。4.5 Nacos 数据丢失现象重启 Nacos 后配置和服务列表清空。原因是用了内嵌 Derby 且没挂持久卷或者集群模式没连 MySQL。解决集群模式必须配SPRING_DATASOURCE_PLATFORMmysql并挂 PVC 给日志目录MySQL 数据单独做备份Nacos 本身不存业务数据。5. 上线前的验证清单与一个压测技巧清单跑通不等于能上线最后一章给一套验证顺序和一个我常用的压测手法。验证按依赖方向走先 Nacos 三副本 Ready再curl nacos-svc:8848/nacos/v1/ns/operator/servers看集群节点列表是否三个都在然后后端 Pod 起来后curl springboot-svc:8080/actuator/health返回 UP同时 Nacos 控制台服务列表里能看到springboot-svc且实例数为副本数最后前端 NodePort 访问用浏览器 Network 面板确认/api请求打到后端而不是 404。压测技巧不要一上来压全链路先用kubectl run起一个临时 Pod 在集群内压后端排除 Nginx 和外部网络干扰kubectl run loadtest --imagewilliamyeh/hey --restartNever -- \ -n 200 -c 20 -z 30s http://springboot-svc:8080/api/health-n总请求数、-c并发、-z持续时间集群内压测能拿到后端真实吞吐。观察kubectl top pods里 CPU 和内存曲线如果 Pod 内存持续上涨不回落多半是 Nacos 配置监听没释放或者连接池没配上限这时候再回去查spring.cloud.nacos.config的 refresh 逻辑。有个习惯我保持了几年每次改完 K8s 清单先在本地kubectl apply --dry-runserver过一遍再kubectl diff看变更范围最后才真 apply。这套流程帮我拦下过好几次误删 Service 的事故。希望这套部署链路能帮到你少走几轮重启。本文还有配套的精品资源点击获取
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表