# springCloudK8sMall **Repository Path**: seanpku/spring-cloud-k8s-mall ## Basic Information - **Project Name**: springCloudK8sMall - **Description**: 演示使用k8s部署springCloud微服务集群应用的demo项目 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2024-11-06 - **Last Updated**: 2025-12-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # springCloudK8sMall k8s部署SpringCloud微服务集群 ## 一、前言 本文简要介绍 kubernetes(后文简称 k8s )的基本原理,随后重点介绍了基于 k8s 部署 SpringBoot 微服务应用集群的方法。 为了更好的演示 K8s 部署应用集群的过程,我们开发了一个 SpringCloud 微服务项目 [springCloudK8sMall](https://gitee.com/seanpku/spring-cloud-k8s-mall.git) ,springCloudK8sMall 和部署方案都是采用最简化的处理,目的是为了帮助大家快速入门 k8s。 ![项目截图](./images/k8s-project.png "项目截图") ## 二、Kubernetes 简介 ### 1. 什么是 k8s? 从官方的定义来说,Kubernetes就是**云原生微服务应用的编排器**。但是编排器这个感念似乎并不好理解,所以个人认为下面这个介绍更能帮助理解 k8s 的本质。 k8s 是**云的操作系统**,使用户不必关心应用是在谁的云或服务器上运行。就像Linux和Windows意味着用户不必关心应用是运行在戴尔还是IBM的服务器上一样。 k8s 帮我们解决服务器,存储,网络的调度(编排)问题,使我们能够专注于应用的部署。就类似于Linux或者windows帮我们解决的CPU,内存,IO的调度,使我们可以专注于应用的开发和使用。 ### 2. 为什么我们需要 K8s 呢? #### 1)公司可以不必关心应用是在谁的云或服务器上运行,避免被某个云厂商或服务器厂商绑架; #### 2)简化部署流程,快速扩缩容,快速恢复环境: 在日常开发运维中,你是否遇到过以下场景“ 1. 项目一开始需要搭建开发环境,你登录每一台服务器安装JDK、filebeat、安装nginx、安装nacos集群...,花了两三天时间才把集群搭建好。 2. 项目开发好了,进入SIT、UAT环节,又需要重复两遍遍上述环节,又花了几天;项目顺利发布上线,搭建PROD环境,这次服务器更多,又花了更多时间部署环境; 3. 项目运行了一段时间,安全排查出filebeat或者nginx版本存在安全漏洞,然后又登录各个环境的各台服务器一个个升级中间件; 4. 有时候在PROD改了某个中间件的配置,但是不确定是否同步到了其他环境,随着时间的推移,各个环境开始不一致,为项目稳定运行埋下了未知风险。 从上述过程可以看出了,每一个环境的搭建,我们都需要执行相同的过程,同时,很难方便的对比各个环境的差异。 **k8s一键创建/销毁环境**:如果使用 k8s 部署,则只需要为每个环境配置一组 yaml 文件,执行一行简单命令,即可在几分钟之内完成环境搭建或销毁。同时只需要对比不同环境的yaml文件,即可知道他们之间的差异。接下来,我们就通过 演示项目 springCloudK8sMall 看看如何通过k8s实现这种能力。 ```shell # 一键创建或者销毁环境 kubectl apply/delete -f ./deploy/ #每个环境配置一组部署配置文件 |--[dev/test/prod]/deploy/ |--mall-frontend-deployment.yaml |--mall-gateway-deployment.yaml |--nacos-statefulset.yaml |--xxx.yaml ``` ## 三、Kubernetes原理简述 ### 1. k8s架构 ![k8s架构图](./images/k8s-arch.png "k8s架构图") Kubernetes 集群由控制平面和一个或多个工作节点组成。以下是主要组件的简要概述: 1. 控制平面组件: 管理集群的整体状态(不重要,部署应用不需要和这些组件打交道,了解即可): 1. kube-apiserver: 公开 Kubernetes HTTP API 的核心组件服务器; 2. etcd: 具备一致性和高可用性的键值存储,用于所有 API 服务器的数据存储; 3. kube-scheduler: 查找尚未绑定到节点的 Pod,并将每个 Pod 分配给合适的节点; 4. kube-controller-manager: 运行控制器来实现 Kubernetes API 行为。 5. cloud-controller-manager: 与底层云驱动集成 2. **Node 组件**:在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行时环境: 1. kubelet: 确保 Pod 及其容器正常运行; 2. kube-proxy: 维护节点上的网络规则以实现 Service 的功能; 3. 容器运行时(Container runtime); 我们所有的应用和中间件都是运行在 node 组件的容器运行时中,通过kube-proxy向集群内外提供网络访问。 ### 2. k8s的一些基本概念 k8s引入了许多概念,但是本文只简单介绍容器、Pod、Deployment、Service等四个核心概念,因为通过这四个内容,你就可以把你的微服务集群运行起来了。 #### 1)容器 容器和虚拟机相比,它实际上是一种**资源隔离**的进程,运行在容器中的应用比独占一个虚拟机消耗的资源更少,启动速度更快。所谓的资源隔离主要只指**进程隔离、文件隔离、网络隔离**: * **进程隔离**:最基本的隔离就是进程之间看不到彼此,这是由Linux的Namespace机制实现的; * **文件隔离**:第二种隔离就是隔离系统真实的文件系统。Docker利用Linux的mount机制,给每个隔离进程挂载了一个虚拟的文件系统,使得一个隔离进程只能访问这个虚拟的文件系统,无法看到系统真实的文件系统; * **网络隔离**:第三种隔离就是网络协议栈的隔离; 一个容器进程本质上是一个运行在沙盒中的隔离进程,由Linux系统本身负责隔离,Docker只是提供了一系列工具,帮助我们设置好隔离环境后,启动这个进程。 #### 2)Pod 上面我们已经提过了,所有的应用和中间件都是运行在容器运行时中,那么我们如何管理容器运行时呢? 其实就是通过Pod,Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。Pod 是一个或者一组容器的封装器;这些容器共享存储、网络、以及怎样运行这些容器的规约。可以把 Pod 简单理解为传统虚拟化部署中的虚拟机,只不过类似容器和虚拟机的差别,Pod占用的资源更小而已。 #### 3)Deployment 一个 Deployment 为 Pod 提供声明式的更新能力,也就是服务更新和扩缩容的能力。 所谓的声明式,就是说用户可以通过 Deployment 声明 Pod 的期望状态,Deployment 会自动帮你把 Pod 保持在期望状态。而期望状态,一般是指你需要这个 Pod 有几个副本,如何更新,如何定义 Pod 的健康状态的信息。 #### 4)Service Kubernetes 网络模型由几个部分构成: * 集群中的每个 Pod 都会获得自己的、独一无二的集群范围 IP 地址。 * Pod 网络(也称为集群网络)处理 Pod 之间的通信。它确保所有 Pod 可以与所有其他 Pod 进行通信, 无论它们是在同一个节点还是在不同的节点上。 * Service API 允许你为由一个或多个后端 Pod 实现的服务提供一个**稳定(长效)的 IP 地址或主机名**, 其中组成服务的各个 Pod 可以随时变化。 k8s网络模型有两个重要的特点: 1. **对外界不可见**; 2. Pod之间可以互访,但却是**不稳定**的。集群会为每个Pod生成IP,但是Pod没有重启的概念,所谓服务重启就是销毁旧 Pod,创建新 Pod。在某些场景下,我们需要服务保持稳定的网络,比如注册中心,各个微服务需要配置固定的注册中心地址。 Service就是为了解决上述两个问题: 1. 对集群外暴露访问入口; 2. 对集群内提供稳定的服务访问地址; ## 四、Kubernetes安装 **注**:如果你已经有了k8s运行环境,可以跳过这部分 minikube是一个本地Kubernetes,它提供和k8s一样的交互命令,安装更加简单,占用的资源也更少,所以在学习环境,我们通过WMware虚拟机安装minikube进行学习。 ### 环境及版本说明 1. VMware: * VMware® Workstation 16 Pro 16.2.4 build-20089737 2. 操作系统: * [CentOS Stream release 9](https://mirrors.aliyun.com/centos-stream/9-stream/BaseOS/x86_64/iso/CentOS-Stream-9-latest-x86_64-boot.iso) 3. minikube: * minikube v1.34.0 * Kubernetes v1.31.0 ### 1. 安装docker #### 卸载docker ```shell sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine ``` #### 安装docker ```shell yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yum makecache fast yum -y install docker-ce ``` 参考文档:[通过aliyun镜像安装docker](https://blog.csdn.net/qq_36433289/article/details/134499047) 配置dockers容器镜像(**xxxxx.mirror.aliyuncs.com地址自行到[阿里云容器镜像服务——》镜像加速器](https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors)获取**) ```shell sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker ``` ### 2.安装kubectl 使用阿里云镜像安装kubectl,你可以按照以下步骤操作: #### 1) 添加阿里云的Kubernetes仓库。 ```shell cat < /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=0 repo_gpgcheck=0 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF ``` #### 2) 安装kubectl ```shell yum install -y kubectl #验证安装是否成功。 kubectl version --client ``` ### 3.安装minikube #### 1) 获取官方最新版minikube ```shell curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 install minikube-linux-amd64 /usr/local/bin/minikube ``` #### 2) 设置默认驱动 ```shell minikube config set driver docker ``` #### 3) 启动minikube 启动一个k8s节点 ```shell minikube delete ; minikube start --force --base-image='registry.cn-hangzhou.aliyuncs.com/google_containers/kicbase:v0.0.44' #--force是以root身份启动的docker的必须选项 #--base-image为指定minikube start 采用的基础镜像,上面docker pull拉取了什么镜像,这里就改成什么镜像(不指定可能会报错) ``` #### 4) 验证minikube ```shell [root@minikube ~]# minikube status minikube type: Control Plane host: Running kubelet: Running apiserver: Running kubeconfig: Configured ``` #### 5) 检查minikuke相关的资源是否正常启动(全部都是Running状态表示正常) ```shell [root@minikube ~]# kubectl get pod,svc,deployment,rc -n kube-system NAME READY STATUS RESTARTS AGE pod/coredns-6f6b679f8f-6gdhm 1/1 Running 0 7m5s pod/etcd-minikube 1/1 Running 0 7m11s pod/kube-apiserver-minikube 1/1 Running 0 7m11s pod/kube-controller-manager-minikube 1/1 Running 0 7m11s pod/kube-proxy-f4vnw 1/1 Running 0 7m5s pod/kube-scheduler-minikube 1/1 Running 0 7m11s pod/storage-provisioner 1/1 Running 1 (6m47s ago) 7m9s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kube-dns ClusterIP 10.96.0.10 53/UDP,53/TCP,9153/TCP 7m10s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/coredns 1/1 1 1 7m10s ``` ## 五、Kubernetes部署SpringCloud微服务应用集群 ### 1. 演示项目 springCloudK8sMall 应用介绍 如下图所示,springCloudK8sMall 是前后端分离的 B/S 应用。前端是一个基于 Vue 3 和 Element Plus 的商城演示项目,展示了一个微服务架构的商城系统,包括用户管理、商品管理、订单管理等功能。后端是一个基于Spring Cloud的微服务商城应用,以nacos为注册中心,包含用户微服务、商品微服务、订单微服务、所有后端微服务通过网关微服务向外暴露接口。 ![项目截图](./images/k8s-project.png "项目截图") ### 2. 镜像管理 #### 1) 打包镜像 我们知道,k8s是管理容器应用的编排器,所以第一步就是要打包镜像,即应用容器化。 **前提说明**:从2024年7月起阿里云镜像加速器调整了 [规则](https://help.aliyun.com/zh/acr/product-overview/product-change-acr-mirror-accelerator-function-adjustment-announcement) ,只能在阿里云服务器使用阿里云镜像加速器。我使用的方式是购买了一台基础版的云服务器,用于打包镜像,打包后推动到免费的 [阿里云容器镜像中心](https://free.aliyun.com/?spm=5176.166170.J_5253785160.4.79d951644oSFdZ&productCode=acr) ,再从本地虚拟机拉取镜像,运行容器。 下面,以前端工程为例,在工程根目录编写如下 Dockerfile 文件。 ```Dockerfile # Dockerfile # 使用 Node.js 17 作为基础镜像 FROM node:17 as build-stage # 设置工作目录 WORKDIR /app # 复制 package.json 和 package-lock.json (如果存在) COPY package*.json ./ # 安装项目依赖 RUN npm install # 复制项目文件和文件夹到工作目录 COPY . . # 构建应用 RUN npm run build # 生产阶段 FROM nginx:stable-alpine as production-stage # 从构建阶段复制构建好的文件到 nginx COPY --from=build-stage /app/dist /usr/share/nginx/html # 暴露 80 端口 EXPOSE 80 # 启动 nginx CMD ["nginx", "-g", "daemon off;"] ``` 执行 docker build 命令完成镜像打包 ```shell docker build -t mall-frontend . ``` 执行 docker images 命令可以查看镜像信息 ```shell [root@aliyun mall]# docker images | grep mall-frontend mall-frontend latest de465df980c9 2 weeks ago 29.7MB ``` 现在我们可以直接在本地运行 Docker 容器,验证镜像是否可以正常执行 ```shell # 运行容器 docker run -d -p 18080:80 mall-frontend # 查看容器运行状态 [root@aliyun mall]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 66340f2a68f7 mall-frontend "/docker-entrypoint.…" 5 seconds ago Up 3 seconds 0.0.0.0:18080->80/tcp, :::18080->80/tcp awesome_swartz # 测试访问 curl http://localhost:18080 ``` #### 2) 使用阿里云镜像中心管理镜像 ##### 1、免费申请试用阿里云镜像服务 登录 [阿里云镜像服务](https://free.aliyun.com/?spm=5176.166170.J_5253785160.4.15c4516423cLpr&productCode=acr) 申请免费试用,进入 [命名空间](https://cr.console.aliyun.com/cn-hangzhou/instance/namespaces) 创建一个自己的命名空间就可以开始使用了。 ##### 2、在打包镜像的服务器和运行k8s的服务器中登录镜像服务 ```shell # 登录阿里云Docker Registry,用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。 docker login --username= registry.cn-hangzhou.aliyuncs.com ``` ##### 3、在打包镜像的服务器中将镜像推送到镜像中心 ```shell # 标记镜像(注意将推送地址更换为你自己的命名空间(namespace)) docker tag mall-frontend:latest registry.cn-hangzhou.aliyuncs.com/namsapce01/mall-frontend:latest # 推送镜像 docker push registry.cn-hangzhou.aliyuncs.com/namsapce01/mall-frontend:latest ``` ##### 4、在运行k8s的服务器中拉取镜像 ```shell # 拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/namsapce01/mall-frontend:latest ``` ##### 5、从docker加载镜像到minikube 上述拉取镜像的动作只是将镜像拉取到了本地docker中,由于我们是使用minikube运行k8s集群,因此还需要将镜像加载到minikube中 ```shell # 加载镜像到minikube [root@minikube ~]# minikube image load registry.cn-hangzhou.aliyuncs.com/namsapce01/qsk-book:1.1 [root@minikube ~]# minikube image ls registry.cn-hangzhou.aliyuncs.com/namsapce01/qsk-book:1.1 ``` #### 3. 小结 我们以前端工程为例介绍了镜像打包和镜像管理的全过程,后端工程镜像打包和管理唯一的差异点就是Dockerfile文件不同,这里不再赘述,大家可以自行查看对于的Dockerfile文件。 ### 2. k8s部署前端 #### 1. 定义 Pod 如前所述,Pod 是K8s中应用执行的最小单位,Pod 的作用即是封装容器。 因此,要在k8s中部署应用,第一步就是要定义应用的Pod。如下所示,Pod 的定义文件由两部分组成,spec 之前定义了诸如 API 版本、资源类型、Pod 名称等基本信息,spec 定义了容器的信息。 ```yaml # mall-frontend-pod.yaml apiVersion: v1 # 定义K8s API的版本 kind: Pod # 定义创建资源的类型 metadata: name: mall-frontend-pod # POD的名称 spec: # 规格说明,定义容器信息 containers: - name: mall-frontend-pod image: registry.cn-hangzhou.aliyuncs.com/namsapce01/mall-frontend:latest # 镜像 这里的namespace01需要替换为自己的命名空间 imagePullPolicy: IfNotPresent # 镜像拉取策略:Always、Never、IfNotPresent ports: - containerPort: 80 ``` 定义好 Pod 对应的 yaml 文件之后,只需要执行 kubectl apply 命令,即可在 k8s 集群中运行对应的 Pod。Pod 的状态为 Running 即说明已经成功运行 Pod,不过此时的 Pod 只能在K8s集群内访问,并不能在集群外访问。 ```shell # 运行Pod [root@minikube deploy]# kubectl apply -f mall-frontend-pod.yaml pod/mall-frontend-pod created 查看POD状态 [root@minikube deploy]# kubectl get pods NAME READY STATUS RESTARTS AGE mall-frontend-pod 1/1 Running 0 10s ``` #### 2.使用 Deployment 管理一组 Pod 在上一节我们了解了如何定义并运行一个 Pod,但在实际运维中,我们并不会这样直接运行一个 Pod。因为 Pod 实际上是一个临时资源,你不应该期待单个 Pod 既可靠又耐用。 在实际应用中,k8s 是通过 Deployment 管理一组 Pod,通过 Deployment 定义一组 Pod 的**期望状态**,K8s 会自动帮忙实现并保持在这个期望状态。 所谓 Pod 的**期望状态**,即一个Pod 运行几个副本,如何更新等状态。 下面这个文件定义了前端项目的 Deployment 文件,从文件中可以看到两个关键信息: * replicas: 定义 Pod 的副本数,即有2个 mall-frontend 的 Pod 运行; * selector: 选择器,这是一个k8s中很关键的概念,这里指定这个 Deployment 需要管理的 Pod,这里即表示管理的是 app=mall-frontend 的 Pod。 ```yaml # mall-frontend-deployment.yaml apiVersion: apps/v1 # 定义使用的 Kubernetes API 版本 kind: Deployment # 定义要创建的资源类型 metadata: # 元数据 name: mall-frontend # Deployment 的名称 labels: app: mall-frontend # 为 Deployment 添加标签 spec: # Deployment规格说明 replicas: 2 # 定义期望运行的副本数 selector: # 定义如何选择要管理的 Pod matchLabels: app: mall-frontend template: # 定义 Pod 的模板 metadata: # Pod 的元数据 labels: # 为 Pod 添加标签 app: mall-frontend spec: # Pod 的规格 containers: # 定义容器 - name: mall-frontend image: registry.cn-hangzhou.aliyuncs.com/namsapce01/mall-frontend:latest # 镜像 imagePullPolicy: IfNotPresent # 镜像拉取策略:Always、Never、IfNotPresent ports: # 定义容器端口 - containerPort: 80 ``` 同样的,我们执行 kubectl apply 即运行对应的 Deployment ```shell # 创建Deployment [root@minikube deploy]# kubectl apply -f mall-frontend-deployment.yaml deployment.apps/mall-frontend created # 查看Dployment [root@minikube deploy]# kubectl get deploy -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR mall-frontend 2/2 2 2 13m mall-frontend registry.cn-hangzhou.aliyuncs.com/namsapce01/mall-frontend:latest app=mall-frontend ``` 从Deployment的状态可以看出,DEADY为2/2,即表示期望的POD数量为2,当前成功运行的数量也为2。这时继续查看 Pod 的状态可以发现,Deployment 自动生成了两个 Pod。 ```shell [root@minikube deploy]# kubectl get pod NAME READY STATUS RESTARTS AGE mall-frontend-6bb5768dbc-25jh8 1/1 Running 0 22m mall-frontend-6bb5768dbc-vmqvj 1/1 Running 0 22m ``` 为什么k8s特别强调了期望数量和实际数量呢?这就是k8s提供的强大的声明式的更新能力,我们只需要定义我们期望的状态,k8s会自动创建并保持在这个状态。 现在我们来看一下如果其中的一个 Pod 被删除或者意外宕机会发生什么? ```shell # 删除POD mall-frontend-6bb5768dbc-25jh8 [root@minikube deploy]# kubectl delete pod mall-frontend-6bb5768dbc-25jh8 pod "mall-frontend-6bb5768dbc-25jh8" deleted # 查看POD状态 [root@minikube deploy]# kubectl get pod NAME READY STATUS RESTARTS AGE mall-frontend-6bb5768dbc-vmqvj 1/1 Running 0 23m mall-frontend-6bb5768dbc-xf5jd 1/1 Running 0 4s ``` 从上面的过程可以看到,k8s 提供的 Deployment 自动新建了一个 Pod,仍然将 Pod 的数量保持在我们期望的数量2。 到这里,前端服务就已经部署好了,但是目前这个服务只能在集群内访问,集群外还无法访问到这个服务。 #### 3.使用Service暴露服务的入口 我们在前文中已经提过,Service主要解决两个问题: 1. 对集群外暴露访问入口; 2. 对集群内提供稳定的服务访问地址; 这里我们先来演示第一个能力,即对集群外暴露访问入口。 从mall-frontend-service.yaml我们看到两组关键信息: * selector: 定义这个service对于的POD * port: 定义如何映射端口 * targetPort: 对于POD中容器的端口 * port: Service 暴露的端口,我们可以在集群内通过Service IP + 这个端口访问POD的服务 * nodePort: 提供一个集群外端口,通过集群IP访问 ![service port 说明](./images/k8s-ports.png "service port 说明]") ```yaml # mall-frontend-service.yaml apiVersion: v1 kind: Service metadata: name: mall-frontend-service # Service 的名称 spec: # Service 规格说明 selector: # 定义如何选择要暴露的 Pod app: mall-frontend # 选择标签为 app: mall-frontend 的 Pod ports: # 定义单个端口映射 - protocol: TCP # 使用 TCP 协议 port: 80 # Service 暴露的端口 targetPort: 80 # Pod 中容器的端口 nodePort: 30080 # 提供一个集群外访问的端口,只能在30000-32767范围内 type: NodePort # 定义 Service 类型,通过每个节点上的 IP 和静态端口(NodePort)公开 Service。 为了让 Service 可通过节点端口访问,Kubernetes 会为 Service 配置集群 IP 地址, 相当于你请求了 type: ClusterIP 的 Service。 ``` 执行kubectl apply 命令创建Service ```shell [root@minikube deploy]# kubectl apply -f mall-frontend-service.yaml service/mall-frontend-service created ``` 查看Service状态 ```shell [root@minikube deploy]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mall-frontend-service NodePort 10.102.36.9 80:30080/TCP 77m ``` 现在我们就可以通过集群IP+service端口访问前端服务了 ```shell # 查看集群IP [root@minikube deploy]# minikube ip 192.168.49.2 # 在集群外访问前端服务 [root@minikube deploy]# curl 192.168.49.2:30080 mall
``` 到这里,前端服务就全部部署完成了,但是由于我们的k8s是运行VMware虚拟机中的,如果我们要在外部的windows机器上访问服务,还需要建立一个代理服务: ```shell # 在运行VMware的windows机器上执行以下命令 ssh -L {本地访问的端口}:{minikube的ip}:{service暴露的端口} {虚拟机(如CentOS、Debian、Ubuntu等)的用户名}@{虚拟机的ip} # 如执行,则可以在windows机器上通过浏览器访问127.0.0.1:9000访问对应的服务 ssh -L 9000:192.168.49.2:30080 root@192.168.8.128 ``` ### 2. k8s部署后端微服务集群 后端微服务集群的部署和前端差异不大,主要的区别就是 nacos 注册中心不应该使用 Deployment 管理负载,而应该使用 StatefulSet 管理负载。 Deployment 和 StatefulSet 都是用于管理应用负载的,主要差别是 Deployment 主要用于管理无状态服务,StatefulSet 用于管理有状态服务。 **有状态无状态**: * 无状态:不会对本地环境产生任何依赖。 * 有状态:会对本地环境(存储、网络等)产生依赖,会存储数据到本地内存、磁盘等,如redis,db; 由于我们使用的是 Nacos 本地 DB 缓存数据,所以应该使用 StatefulSet 部署。