目录
[1. Nacos 单节点(使用轩辕加速镜像)](#1. Nacos 单节点(使用轩辕加速镜像))
[5. user-service 微服务](#5. user-service 微服务)
[6. order-service 微服务](#6. order-service 微服务)

简介K8s
Kubernetes(简称 K8s)是一个容器编排平台,它负责把你用 Docker 打包的应用(容器)放到多台机器上运行、自动重启、伸缩、负载均衡和发现服务。换句话说:把"单机 docker run"提升成"分布式可用、可扩缩、可管理"的平台。
-
Pod:K8s 最小调度单位,通常一个 Pod 里跑一个容器(或紧密耦合的多个容器)。
-
Deployment:管理一组副本 Pod 的控制器(负责滚动更新、回滚)。
-
StatefulSet:有状态服务(比如数据库、有持久名)的部署方式。
-
Service:把一组 Pod 暴露成稳定的网络入口(ClusterIP / NodePort / LoadBalancer)。
-
ConfigMap / Secret:配置与密钥注入(避免把配置写死在镜像里)。
-
PersistentVolume(PV) / PersistentVolumeClaim(PVC):持久化存储(容器重建数据不丢)。
-
Ingress:HTTP/HTTPS 入口路由,可绑定域名与 TLS。
-
Namespace:逻辑隔离(不同环境或团队用不同 namespace)。
-
Node:运行 Pod 的物理/虚拟机(工作节点)。
-
kube-apiserver / kube-scheduler / kube-controller-manager / etcd:控制平面组件(通常由集群管理员维护)。
k8s集群架构
Kubernetes 安装都是 集群模式,部署完 Kubernetes, 即拥有了一个完整的集群。
Kubernetes Cluster = N 主节点 + N 工作节点 ( N >= 1)
- 控制平面组件:管理集群的整体状态(不重要,部署应用不需要和这些组件打交道,了解即可):
- kube-apiserver: 公开 Kubernetes HTTP API 的核心组件服务器;
- etcd: 具备一致性和高可用性的键值存储,用于所有 API 服务器的数据存储;
- kube-scheduler: 查找尚未绑定到节点的 Pod,并将每个 Pod 分配给合适的节点;
- kube-controller-manager: 运行控制器来实现 Kubernetes API 行为。
- cloud-controller-manager: 与底层云驱动集成
- Node 组件 :在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行时环境:
- kubelet: 确保 Pod 及其容器正常运行;
- kube-proxy: 维护节点上的网络规则以实现 Service 的功能;
- 容器运行时(Container runtime);
我们所有的应用和中间件都是运行在 node 组件的容器运行时中,通过 kube-proxy 向集群内外提供网络访问。使用命令查看节点(在主节点运行):
kubectl get nodes
k8s 主要有容器、Pod、Deployment、Service等四个核心概念,学过docker就会明白,它主要是起到了资源隔离,而资源隔离主要只指**进程隔离、文件隔离、网络隔离。**一个容器进程本质上是一个运行在沙盒中的隔离进程,由 Linux 系统本身负责隔离,Docker 只是提供了一系列工具,帮助我们设置好隔离环境后,启动这个进程。容器就是运行你 Java 服务的最底层实例,来自 Docker 镜像,例如:
image: user-service:1.0
所有的应用和中间件都是运行在容器运行时中的,那么我们应如何管理容器运行时呢?这个时候就可以通过 pod,在上面提到过,pod 是 K8s 最小调度单位,通常一个 Pod 里跑一个或多个容器,能够共享网络(同一IP),共享存储(volumes):
Pod → Container (user-service.jar)
可以使用命令去查看所有的 pod:
kubectl get pods -A
查看详细 pod:
kubectl describe pod pod-name
集群中的每个 Pod 都会获得自己的、独一无二的集群范围 IP 地址。Pod 网络(也称为集群网络)处理 Pod 之间的通信。它确保所有 Pod 可以与所有其他 Pod 进行通信, 无论它们是在同一个节点还是在不同的节点上。但是 **Pod 不可靠,会随时被重启、删除、迁移,**所以不能用 Pod 做高可用,必须使用 Deployment 来管理 Pod。
Deployment 才是真正部署微服务的地方,一个 Deployment 为 Pod 提供声明式的更新能力,也就是 服务更新和扩缩容的能力。所谓的声明式,就是说用户可以通过 Deployment 声明 Pod 的期望状态,Deployment 会自动帮你把 Pod 保持在期望状态。而期望状态,一般是指你需要这个 Pod 有几个副本,如何更新,如何定义 Pod 的健康状态的信息。
kubectl get deploy -A
kubectl describe deploy deploy-name
而由于 Pod IP 会变化(Pod 会重启),所以不能直接访问 Pod,这个时候就要使用 Service,它是 Pod 的 稳定访问入口。
- Service API 允许我们为由一个或多个后端 Pod 实现的服务提供一个稳定(长效)的 IP 地址或主机名, 其中组成服务的各个 Pod 可以随时变化。
Service主要是为了解决两个问题:
- 对集群外暴露访问入口;
- 对集群内提供稳定的服务访问地址;
Service 主要有 4 种:
| 类型 | 作用 |
|---|---|
| ClusterIP | 微服务内部访问(最常用) |
| NodePort | 暴露到宿主机端口 |
| LoadBalancer | 云厂商自动分配公网 IP |
| Headless (clusterIP: None) | 给 StatefulSet 用的,例如 MySQL 集群 |
可以使用命令查看 Service:
kubectl get svc -A
kubectl describe svc svc-name
搭建一个k8s集群
这里我们创建了三台虚拟机(主机名分别为:node1,node2,node3),其中 node1 是主节点,而 node2、node3 是工作节点。
三台机器都需装上 Docker、Kubelet、Kubectl、Kubeadm,一般主节点与工作节点需要安装如下:

安装教程可以参考如下:Kubenetes
我们可以使用 minikube,它是一个本地Kubernetes,提供和 k8s 一样的交互命令,安装更加简单并且占用的资源也更少。k8s部署SpringCloud微服务集群k8s部署SpringCloud微服务集群 ,简要介绍 kubernetes( - 掘金
打包并上传镜像
首先去编写 Dockerfile(不会的朋友可以点击下面链接学习在Linux系统上使用DockerFile以及Dockercompose部署项目_linux,docker部署java项目-CSDN博客)
bash
# 1. 使用基础镜像
FROM eclipse-temurin:17-jdk
# 2. 设置工作目录
WORKDIR /app
# 3. 将 jar 包复制进容器
COPY target/user-service.jar app.jar
# 4. 暴露端口(可选,给文档用)
EXPOSE 8081
# 5. 启动命令
ENTRYPOINT ["java","-jar","/app/app.jar"]
随后执行 docker build 完成镜像打包:
bash
docker build -t user-service:1.0
然后执行下面命令查看镜像信息:
bash
docker images | grep user-service:1.0
接下来需要我们去上传这个镜像,一般会使用阿里镜像服务:容器镜像服务 ACR 控制台
登录 阿里云镜像服务 申请免费试用,进入 命名空间 创建一个自己的命名空间就可以开始使用了。
我们在打包镜像的服务器和运行k8s的服务器中登录镜像服务,随后执行下面命令:【换成自己的用户名】
bash
# 登录阿里云Docker Registry,用于登录的用户名为阿里云账号全名,密码为开通服务时设置的密码。
docker login --username=<username> registry.cn-hangzhou.aliyuncs.com
随后在打包镜像的服务器中将镜像推送到镜像中心:【换成自己的命名空间】
bash
# 标记镜像(注意将推送地址更换为你自己的命名空间(namespace))
docker tag mall-frontend:latest registry.cn-hangzhou.aliyuncs.com/namsapce01/user-service:1.0
# 推送镜像
docker push registry.cn-hangzhou.aliyuncs.com/namsapce01/user-service:1.0
最后我们就可以尝试使用命令去拉取我们的镜像了:
bash
# 拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/namsapce01/user-service:1.0
k8s中编写使用yaml文件
YAML 是 Kubernetes 的"配置文件格式",主要用于告诉 K8s:我要创建什么资源?如何运行?运行多少?暴露哪些端口?使用哪个镜像?等关键信息。
比如:
-
部署一个 Java 微服务? → 写 Deployment.yaml
-
创建一个访问入口? → 写 Service.yaml
-
创建域名入口? → 写 Ingress.yaml
-
创建 MySQL 集群? → 写 StatefulSet.yaml
-
设置环境变量? → 写 ConfigMap.yaml
-
设置密码? → 写 Secret.yaml
而使用它非常简单,我们只需要编写一个 yaml 文件,随后去使用下面命令去运行即可:【例如我构建了一个名为 user-service.yaml 文件】
bash
kubectl apply -f user-service.yaml
那么下面我们就要讲解如何去编写 YAML 文件 ->
K8s 的 YAML 基本结构总共 4 部分,不管你部署啥都是这结构:
bash
apiVersion:
kind:
metadata:
spec:
| 字段 | 含义 |
|---|---|
| apiVersion | 资源所属的 API 版本 |
| kind | 资源类型,例如 Deployment、Service |
| metadata | 名称、标签等 |
| spec | 核心配置(最重要) |
比如下面的 YAML 文件:
bash
apiVersion: apps/v1 # 使用 Deployment 所在的 API 版本
kind: Deployment # 声明资源类型为 Deployment(部署)
metadata:
name: user-service # Deployment 名称,在运行 kubectl get deploy 时会看到它,Pod 会自动继承这个名称的前缀
spec:
replicas: 2 # 副本数量,表示运行 2 个 Pod(负载均衡)【如果挂了 1 个 → 自动拉起新 Pod;如果你手动删 1 个 → 2 秒后自动补上】
selector: # Deployment 如何找到需要管理的 Pod
matchLabels:
# Deployment 只会管理那些 app=user-service 的 Pod,后面 template 里的 label 必须一致,否则 Pod 不会被管理
app: user-service # 通过 Pod 标签 app=user-service 进行匹配 【Deployment 用这个 label 找它管理的 Pod】
# K8s 会根据 template 的内容来创建 Pod
template: # Pod 模板(Deployment 会根据这里创建 Pod)
metadata:
labels:
# label 是 K8s 中资源关联的唯一方式
app: user-service # 给 Pod 设置标签,必须与 selector 匹配
# Pod 的运行配置
spec:
containers: # Pod 中运行的容器列表
- name: user-service # 容器名称
image: user-service:1.0 # 使用的镜像,来自本地或镜像仓库
ports:
- containerPort: 8081 # 容器对外暴露的端口(应用内部端口)
env: # 注入环境变量
- name: MYSQL_HOST
value: mysql # MYSQL 主机名(ClusterIP 服务名)
- name: NACOS_ADDR
value: nacos:8848 # Nacos 地址(服务名 + 端口)
---
# 下面是为 user-service Pod 提供访问方式的 Service
apiVersion: v1 # Service 属于 core/v1
kind: Service # 声明资源类型为 Service(服务)
metadata:
name: user-service # Service 名称,应与 Deployment 名相同(常见约定)
spec:
type: ClusterIP # 默认类型:仅集群内部访问
selector:
app: user-service # 选择带标签 app=user-service 的 Pod
ports:
- port: 8081 # Service 对外暴露的端口(集群内部访问)
targetPort: 8081 # Pod 内部容器端口(containerPort),通常一致
当我们去运行这份 YAML 文件,K8s 自动创建:
| 资源 | 作用 |
|---|---|
| Deployment | 启动 user-service |
| Pod | 运行 user-service.jar |
| Service | 提供集群内部访问入口 |
另外我们还需要去知道常用 YAML 的种类:
| 类型 | 作用 | 微服务中用来干啥? |
|---|---|---|
| Deployment | 启动微服务(多副本) | 运行 Java 服务 |
| Service | 暴露端口、让服务互相访问 | user-service 调 order-service |
| Ingress | 域名访问入口 | 给前端提供网关入口 |
| ConfigMap | 配置文件(不放镜像里) | 代替 application.yml |
| Secret | 敏感数据 | MySQL 密码、JWT 密钥 |
| StatefulSet | 有状态应用 | MySQL、Redis、Nacos |
| PV / PVC | 持久化存储 | MySQL 数据目录 |
详细教学可以看:Kubernetes
部署实战
首先我们先介绍项目架构:
| 服务名 | 类型 | 说明 |
|---|---|---|
| gateway-service | SpringCloud Gateway | 微服务入口 |
| user-service | 微服务 | 用户模块 |
| order-service | 微服务 | 订单模块 |
| mysql | 数据库 | 使用 PVC 持久化 |
| redis | 缓存 | 缓存/分布式锁 |
| nacos | 注册中心 + 配置中心 | |
| rabbitmq | MQ | 消息队列 |
1. Nacos 单节点(使用轩辕加速镜像)
对于微服务开发环境,一般1节点足够。
bash
apiVersion: v1
kind: Service
metadata:
name: nacos
spec:
ports:
- port: 8848
targetPort: 8848
selector:
app: nacos
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nacos
spec:
replicas: 1
selector:
matchLabels:
app: nacos
template:
metadata:
labels:
app: nacos
spec:
containers:
- name: nacos
image: dockerproxy.cn/nacos/nacos-server:v2.2.3
env:
- name: MODE
value: standalone
ports:
- containerPort: 8848
2.MySQL(支持持久化)
K8s 部署 MySQL 时,如果你希望:
- MySQL 第一次启动时自动运行 SQL 文件(建库、建表、插入初始数据)
那么只需要使用 Init Container + ConfigMap(或 PVC 文件)。
将 SQL 文件挂载到 /docker-entrypoint-initdb.d
原理:
只要 SQL 文件在该目录下,并且数据目录是空的,MySQL 第一次启动时会自动执行它。
Docker Compose 用的是 volume,让 SQL 落到这个目录,Kubernetes 同理,也可以做到。
首先创建 ConfigMap 存放 SQL:
bash
apiVersion: v1
kind: ConfigMap
metadata:
name: demo-mysql-init
data:
init.sql: |
CREATE DATABASE IF NOT EXISTS demo;
USE demo;
CREATE TABLE user (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
password VARCHAR(100)
);
**好处:**SQL 改项目自动更新,不需要打包镜像。
随后将 MySQL Deployment 引用这个 SQL
重点:把 ConfigMap 挂载到 /docker-entrypoint-initdb.d
bash
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-mysql
spec:
replicas: 1
selector:
matchLabels:
app: demo-mysql
template:
metadata:
labels:
app: demo-mysql
spec:
containers:
- name: mysql
image: xxx.xuanyuan.run/library/mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: "root"
- name: MYSQL_DATABASE
value: "demo"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: mysql-init
mountPath: /docker-entrypoint-initdb.d # ⭐ 初始化 SQL 自动执行
volumes:
- name: mysql-data
emptyDir: {} # 或者用 PVC,如果你要持久化
- name: mysql-init
configMap:
name: demo-mysql-init
3.Redis
bash
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
ports:
- port: 6379
selector:
app: redis
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: dockerproxy.cn/library/redis:6.2
ports:
- containerPort: 6379
4.RabbitMQ:
bash
apiVersion: v1
kind: Service
metadata:
name: rabbitmq
spec:
ports:
- port: 5672
- port: 15672
name: http
selector:
app: rabbitmq
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rabbitmq
spec:
selector:
matchLabels:
app: rabbitmq
template:
metadata:
labels:
app: rabbitmq
spec:
containers:
- name: rabbitmq
image: dockerproxy.cn/library/rabbitmq:3.12-management
ports:
- containerPort: 5672
- containerPort: 15672
5. user-service 微服务
bash
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
ports:
- port: 8081
selector:
app: user-service
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 2
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: dockerproxy.cn/library/openjdk:17
args:
- "java"
- "-jar"
- "/app/user-service.jar"
env:
- name: NACOS_ADDR
value: nacos:8848
- name: MYSQL_HOST
value: mysql
- name: REDIS_HOST
value: redis
ports:
- containerPort: 8081
6. order-service 微服务
bash
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
ports:
- port: 8082
selector:
app: order-service
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 2
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: dockerproxy.cn/library/openjdk:17
args:
- "java"
- "-jar"
- "/app/order-service.jar"
env:
- name: NACOS_ADDR
value: nacos:8848
- name: MQ_HOST
value: rabbitmq
ports:
- containerPort: 8082
7. SpringCloud Gateway
bash
apiVersion: v1
kind: Service
metadata:
name: gateway-service
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30080
selector:
app: gateway-service
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway-service
spec:
replicas: 1
selector:
matchLabels:
app: gateway-service
template:
metadata:
labels:
app: gateway-service
spec:
containers:
- name: gateway-service
image: dockerproxy.cn/library/openjdk:17
args:
- "java"
- "-jar"
- "/app/gateway.jar"
env:
- name: NACOS_ADDR
value: nacos:8848
ports:
- containerPort: 8080
随后统一执行命令:
bash
kubectl apply -f nacos.yaml
kubectl apply -f mysql.yaml
kubectl apply -f redis.yaml
kubectl apply -f rabbitmq.yaml.
kubectl apply -f user-service.yaml
kubectl apply -f order-service.yaml
kubectl apply -f gateway.yaml