
简介这份资源面向需要在阿里云Kubernetes集群上落地前后端分离项目的开发与运维人员提供一套可直接参考的部署方案解决Vue2前端、SpringBoot2.5后端与Nacos2.0.3注册配置中心在k8s环境下的编排与联调问题。包内共16个文件以8个yaml编排文件为核心覆盖Nacos的StatefulSet、Service、Headless、Ingress及MySQL配置等模块另含2个sh部署脚本、2个Dockerfile、1个SQL初始化脚本、1个nginx.conf、1个jar包与1个gz压缩包整体约34.69MB。资源围绕k8s-vue-demo与k8s-realize-master两条部署主线展开配合Nacos一键部署脚本可帮助读者理解前端静态资源打包、Nginx反向代理、后端镜像构建以及Nacos持久化到MySQL的完整链路。已有1340人学习下载适合具备一定容器基础、希望快速搭建微服务部署环境并排查编排问题的技术人员参考。1. 阿里云 K8s 上跑 Vue2 Nginx SpringBoot 2.5 Nacos 2.0.3一套能落地的全栈部署方案很多团队把单体 SpringBoot 拆成前后端分离后卡在最后一公里本地跑得好好的一上阿里云 K8s 就各种连不上、注册不上、刷新 404。这套组合Vue2 打包静态资源 Nginx 托管并反代 SpringBoot 2.5 提供接口 Nacos 2.0.3 做注册配置中心在中小项目里非常常见但版本组合有讲究SpringBoot 2.5 对应 Spring Cloud 2020.0.xNacos 客户端要用 2.0.3 配套的 starter否则会出现 gRPC 端口连不上、服务列表空白的玄学问题。这篇笔记按「镜像怎么打 → K8s 资源怎么写 → Nacos 怎么连 → 坑怎么排」的顺序讲清楚新手能照着敲熟手能对照参数边界。适合正在做前后端分离上云、或者准备把老项目迁到 K8s 的工程师。2. 镜像分层Vue2 静态包、Nginx、SpringBoot 各自怎么打上 K8s 第一步不是写 YAML而是把三个东西打成能跑的镜像。很多人一上来就kubectl apply结果 Pod 一直 CrashLoopBackOff回头查发现是镜像里路径写错、时区不对、或者 Nacos 地址写成了 localhost。这一章把镜像构建的细节拆开讲因为后面所有 K8s 配置都建立在这三个镜像之上。2.1 Vue2 打包产物怎么塞进 Nginx 镜像Vue2 老项目一般用 vue-cli 或 webpack 构建产物是dist/目录。常见做法是用多阶段构建第一阶段用 node 镜像跑npm run build第二阶段用 nginx 镜像只拷贝产物。这样镜像小也不带 node_modules。# 阶段一构建 Vue2 产物 FROM node:14-alpine AS builder WORKDIR /app # 先拷依赖清单利用 Docker 层缓存改代码不用重装依赖 COPY package*.json ./ RUN npm config set registry https://registry.npmmirror.com npm install COPY . . RUN npm run build # 阶段二Nginx 托管静态资源 FROM nginx:1.21-alpine # 删掉默认配置换成我们自己的 RUN rm -f /etc/nginx/conf.d/default.conf COPY --frombuilder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/app.conf EXPOSE 80逻辑说明npm config set registry换成国内镜像源构建快很多这是血泪经验默认源在 CI 里经常超时。COPY package*.json单独一层是为了缓存只要依赖没变改业务代码不会重新npm install。第二阶段只拷贝dist最终镜像通常 20MB 出头。参数说明node 版本建议锁 14 或 16Vue2 老项目在 node 18 上可能因为 OpenSSL 报ERR_OSSL_EVP_UNSUPPORTED真遇到就加NODE_OPTIONS--openssl-legacy-provider。nginx 用 alpine 版体积小但注意 alpine 里没有 bash写脚本用 sh。2.2 Nginx 配置静态托管 反向代理后端Nginx 在这个架构里干两件事托管 Vue 的 index.html 和静态资源以及把/api开头的请求转发给 SpringBoot 的 Service。Vue2 是单页应用刷新非根路径会 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; } # 静态资源缓存文件名带 hash 的可以长缓存 location ~* \.(js|css|png|jpg|svg|woff2?)$ { expires 7d; add_header Cache-Control public; } # 反向代理到 SpringBoot Service location /api/ { proxy_pass http://springboot-svc: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; proxy_connect_timeout 5s; proxy_read_timeout 30s; } }逻辑说明try_files $uri $uri/ /index.html是 Vue2 history 路由的标配不写这个用户刷新/user/list直接 404。proxy_pass结尾带不带斜杠差别很大http://springboot-svc:8080/会把/api/user转成/user不带斜杠则保留/api/user要和后端context-path对齐这是最常见的翻车点。参数说明springboot-svc是后面 K8s Service 的名字K8s 内部 DNS 能直接解析。proxy_read_timeout默认 60s接口慢的可以调大但别超过网关超时。expires 7d只对带 hash 的静态资源安全index.html 千万别缓存否则发版后用户拿到旧页面。2.3 SpringBoot 2.5 镜像与 Nacos 2.0.3 依赖对齐SpringBoot 2.5 打镜像推荐用分层 jarlayered jar配合spring-boot-maven-plugin的 layers 功能依赖层和业务层分开推镜像时只传变化的层。Nacos 客户端版本必须和 server 对齐到 2.0.3否则 2.x 的 gRPC 长连接会握手失败。!-- pom.xml 关键依赖版本必须对齐 -- parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.5.14/version /parent properties spring-cloud.version2020.0.5/spring-cloud.version spring-cloud-alibaba.version2021.1/spring-cloud-alibaba.version /properties dependencies dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId /dependency dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-starter-alibaba-nacos-config/artifactId /dependency /dependencies逻辑说明SpringBoot 2.5 对应 Spring Cloud 2020.0.xSpring Cloud Alibaba 2021.1 是能兼容这套组合的版本线它内部带的 nacos-client 是 2.0.3。如果自己手动指定 nacos-client 版本很容易和 starter 冲突出现Client not connected或注册上了但配置拉不到。参数说明spring-cloud-alibaba.version不要乱升2021.1 之后的版本可能要求 SpringBoot 2.6。打包命令用mvn clean package -DskipTests然后 Dockerfile 里用java -Djarmodelayertools -jar app.jar extract分层这里不展开重点是依赖版本先对齐。3. K8s 资源编排Deployment、Service、Ingress 怎么写镜像有了接下来是 K8s 资源。阿里云 ACK 集群和自建 K8s 在资源写法上基本一致区别主要在 Ingress 用阿里云自己的 ingress-nginx 还是 SLB。这一章给出可直接抄的 YAML并解释每个字段为什么这么设。3.1 Nacos 2.0.3 在 K8s 里的部署与端口暴露Nacos 2.0.3 除了 8848 的 HTTP 端口还多了 9848gRPC 客户端和 9849gRPC 服务端两个端口。2.x 客户端默认走 gRPC如果只暴露 8848服务能注册但心跳会断表现为服务列表时有时无。这是 2.0 之后最大的坑。apiVersion: apps/v1 kind: StatefulSet metadata: name: nacos namespace: middleware spec: serviceName: nacos-headless replicas: 1 selector: matchLabels: app: nacos template: metadata: labels: app: nacos spec: containers: - name: nacos image: nacos/nacos-server:v2.0.3 env: - name: MODE value: standalone - name: JVM_XMS value: 512m - name: JVM_XMX value: 512m ports: - containerPort: 8848 - containerPort: 9848 - containerPort: 9849 --- apiVersion: v1 kind: Service metadata: name: nacos-svc namespace: middleware spec: selector: app: nacos ports: - name: http port: 8848 targetPort: 8848 - name: grpc-client port: 9848 targetPort: 9848 - name: grpc-server port: 9849 targetPort: 9849逻辑说明用 StatefulSet 而不是 Deployment是因为 Nacos 有数据目录StatefulSet 的稳定网络标识和 PVC 挂载更合适。standalone 模式适合测试和小规模生产要改成 cluster 并配 MySQL。三个端口必须全部在 Service 里暴露缺一个客户端就连不上。参数说明JVM_XMS/XMX设 512m 是给测试环境省资源生产至少 2g。namespace: middleware把中间件和业务隔离这是 K8s namespace 的典型用法。客户端连接地址写nacos-svc.middleware:8848跨 namespace 要用全限定名。3.2 SpringBoot 的 Deployment 与探针配置SpringBoot 上 K8s 必须配健康检查否则流量会在应用还没起来时就打进来。SpringBoot 2.5 自带 actuator暴露/actuator/health即可。apiVersion: apps/v1 kind: Deployment metadata: name: springboot-app namespace: default spec: replicas: 2 selector: matchLabels: app: springboot-app template: metadata: labels: app: springboot-app spec: containers: - name: app image: registry.cn-hangzhou.aliyuncs.com/your-ns/springboot-app:1.0.0 ports: - containerPort: 8080 env: - name: NACOS_ADDR value: nacos-svc.middleware:8848 - name: JAVA_OPTS value: -Xms512m -Xmx1024m readinessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 60 periodSeconds: 20 --- apiVersion: v1 kind: Service metadata: name: springboot-svc namespace: default spec: selector: app: springboot-app ports: - port: 8080 targetPort: 8080逻辑说明readinessProbe决定 Pod 是否加入 Endpoints没通过就不接流量livenessProbe决定是否重启容器。两个探针都指向 actuator healthSpringBoot 启动慢的话initialDelaySeconds要给够否则会被反复重启看起来像 CrashLoop。参数说明NACOS_ADDR通过环境变量注入application.yml 里写${NACOS_ADDR:127.0.0.1:8848}本地开发不用改配置。replicas: 2保证滚动更新时至少有一个可用。镜像地址用阿里云容器镜像服务的私有仓库记得在 ACK 里配好免密拉取。3.3 Ingress 暴露前端并配置域名前端 Nginx 的 Service 通过 Ingress 暴露到公网阿里云 ACK 一般用 ingress-nginx 或 ALB Ingress。下面用标准 ingress-nginx 写法。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-ingress namespace: default annotations: nginx.ingress.kubernetes.io/proxy-body-size: 20m spec: ingressClassName: nginx rules: - host: app.example.com http: paths: - path: / pathType: Prefix backend: service: name: web-svc port: number: 80逻辑说明前端 Nginx 的 Service 叫web-svcIngress 把域名app.example.com的流量导过去。前端 Nginx 内部再通过/api反代到springboot-svc这样只需要暴露一个域名前后端同源省掉跨域配置。参数说明proxy-body-size默认 1m上传文件会 413按需调大。ingressClassName要和集群里实际的 Ingress Controller 对应阿里云 ACK 里可能是nginx或alb用kubectl get ingressclass确认。域名解析到 SLB 的 IPHTTPS 可以在阿里云申请免费证书后配到 Ingress 的 tls 段。4. 避坑与排查这套组合最容易翻车的 5 个点前面讲的是「正常路径」但实际部署时踩的坑往往不在主流程上。这一章按「现象 → 原因 → 解决」记录 5 个高频问题都是我在真实环境里遇到过的。4.1 服务注册上了但调用 503现象Nacos 控制台能看到服务实例但通过 Feign 或 RestTemplate 调用时报 503日志里找不到可用实例。原因Nacos 2.0.3 客户端走 gRPC 9848 端口做心跳和推送如果 K8s Service 只暴露了 8848注册能成功HTTP 写入但订阅和健康检查走 gRPC 失败实例被标记为不健康。解决确认 Nacos Service 暴露了 8848、9848、9849 三个端口且客户端配置的地址是 Service 名而非 Pod IP。用telnet nacos-svc.middleware 9848在业务 Pod 里测一下连通性。4.2 Vue 刷新页面 404现象首页能打开点进路由再刷新就 404Nginx 日志显示找不到文件。原因Vue2 用 history 模式刷新时浏览器直接请求/user/listNginx 在磁盘上找不到这个路径的文件。解决Nginx 配置里加try_files $uri $uri/ /index.html;。注意要放在location /里且index.html路径要对。如果是 hash 模式则不会有这个问题但 URL 带#体验差。4.3 SpringBoot 启动报 Nacos 连接超时现象Pod 启动时日志刷com.alibaba.nacos.api.exception.NacosException: Client not connected然后应用退出。原因Nacos 还没完全启动SpringBoot 就去连了或者网络策略NetworkPolicy挡了跨 namespace 的流量。解决给 SpringBoot 加启动重试spring.cloud.nacos.discovery.fail-fastfalse让它先起来再重连。更稳的做法是用 initContainer 等 Nacos 端口通了再启动主容器。跨 namespace 要确认没有 NetworkPolicy 拦截。4.4 镜像拉取失败 ImagePullBackOff现象Pod 状态ImagePullBackOffdescribe 显示pull access denied或no such host。原因阿里云容器镜像服务私有仓库需要认证ACK 节点默认没有凭证或者镜像地址写错。解决在 ACK 控制台配置镜像仓库的免密拉取RRSA 或 secret或者手动创建imagePullSecrets。确认镜像地址格式为registry.cn-hangzhou.aliyuncs.com/命名空间/镜像:tag别漏了命名空间。4.5 时区不对导致时间差 8 小时现象应用日志时间比实际早 8 小时数据库写入时间也不对。原因基础镜像默认 UTC 时区JVM 和容器都是 UTC。解决Dockerfile 里加RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime或者 K8s 里挂载hostPath的时区文件。JVM 参数加-Duser.timezoneAsia/Shanghai双保险。5. 进阶用 ConfigMap 管配置、用 HPA 扛流量、用滚动更新保发布基础跑通后真正让这套架构在生产站得住的是配置外置、弹性伸缩和发布策略。这一章讲三个具体技巧都是能直接加到现有 YAML 里的。5.1 把 Nacos 地址和业务配置抽到 ConfigMap硬编码在镜像里的配置改一次要重新打镜像用 ConfigMap 挂载成文件或环境变量改配置只需kubectl apply。apiVersion: v1 kind: ConfigMap metadata: name: app-config namespace: default data: application.yml: | spring: cloud: nacos: discovery: server-addr: ${NACOS_ADDR} config: server-addr: ${NACOS_ADDR} file-extension: yaml server: port: 8080逻辑说明ConfigMap 以文件形式挂到容器里SpringBoot 启动时用--spring.config.additional-location指定路径。这样配置和镜像解耦不同环境用不同 ConfigMap。参数说明server-addr用${NACOS_ADDR}占位实际值从环境变量注入环境变量又来自 ConfigMap 或 Secret。敏感信息如数据库密码放 Secret不要放 ConfigMap。5.2 HPA 按 CPU 自动扩缩容流量波动大的时候固定副本数要么浪费要么扛不住。HPA 根据 CPU 使用率自动调副本。apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: springboot-hpa namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: springboot-app minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70逻辑说明CPU 平均利用率超过 70% 就扩容降到阈值以下缩容。minReplicas: 2保证高可用maxReplicas: 10防止无限扩容打爆节点。参数说明HPA 生效的前提是 Deployment 里配了resources.requests.cpu没有 requests 的话 HPA 算不出利用率。阈值 70% 是经验值接口 CPU 密集的可以调低IO 密集的调高。5.3 滚动更新与就绪探针配合发布时最怕新版本还没起来旧版本就被杀光。Deployment 默认滚动更新但要配好maxSurge和maxUnavailable。spec: strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0逻辑说明maxUnavailable: 0表示更新过程中不允许有 Pod 不可用先起新 Pod 再杀旧 Pod。配合 readinessProbe新 Pod 通过健康检查后才接流量实现零停机。参数说明maxSurge: 1表示最多多起 1 个 Pod节点资源紧张时可以设 0但更新会慢。发布大版本前建议先在测试 namespace 验证再改生产镜像 tag。这套组合我前后搭过几次最大的体会是版本对齐比 YAML 写对更重要Nacos 2.x 的端口和 Spring Cloud Alibaba 的版本线是两条最容易翻车的暗线。每次上线前我会先在本地用 docker-compose 把四个组件跑一遍确认注册、配置、反代都通了再往 K8s 上搬能省掉大量在集群里瞎调的时间。希望帮到你。本文还有配套的精品资源点击获取