文章目录
本章节系统性梳理一下 无状态应用(Stateless App) 和 有状态应用(Stateful App) 的概念及其在 K8s 上的典型部署方式。
一、概念区别
1. 无状态应用(Stateless App)
-
定义:应用实例之间没有依赖关系,任意一个实例都能独立处理请求。
-
特点:
不保存会话信息,用户数据存储在外部系统(如 DB、缓存);
扩缩容容易,随时可以新增/删除 Pod;
常见场景:Web 应用、API 服务、Nginx、前端服务。
-
示例:
Nginx Web Server
SpringBoot 微服务
2. 有状态应用(Stateful App)
-
定义:应用实例之间存在依赖关系,需要保持持久化存储和固定的网络标识。
-
特点:
Pod 有顺序性和固定命名(例如 mysql-0, mysql-1);
需要持久化存储(PVC + PV)来保证数据不会因 Pod 重启而丢失;
常见场景:数据库、中间件、消息队列。
-
示例:
MySQL、Postgres
Redis(持久化模式)
Kafka、Zookeeper
二、K8s 部署方式
1. 无状态应用部署(Deployment)
无状态应用一般使用 Deployment 管理,Pod 数量灵活扩缩容。
📌 示例:部署一个 Nginx 服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3 # 三个副本
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: ClusterIP
selector:
app: nginx
ports:
- port: 80
targetPort: 80
2. 有状态应用部署(StatefulSet)
有状态应用一般使用 StatefulSet 来保证 Pod 的唯一标识和顺序性,同时结合 PVC 做存储。
📌 示例:部署一个 MySQL 集群(单副本简化版)
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
name: mysql
clusterIP: None # Headless Service,保证 StatefulSet Pod 可直连
selector:
app: mysql
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql"
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "root123"
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-persistent-storage
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 5Gi
三、无状态 vs 有状态应用的可视化对比图
四、流量、存储、Pod 生命周期的差异
1. 流量(Traffic)
名称 | 内容 |
---|---|
无状态应用 | 流量进入时可以随机分发到任意 Pod(通过 Service 轮询 / 随机 / 哈希)。Pod 不保存会话信息,用户请求在不同 Pod 之间切换也不会出问题。典型:Nginx、前端服务、API 网关。 |
有状态应用 | 流量可能需要固定路由到特定 Pod(粘性会话、StatefulSet 的固定 DNS)。例如 Redis 集群、数据库主从,需要保证某个请求始终命中对应节点。常通过 Headless Service + StatefulSet 实现。 |
2. 存储(Storage)
名称 | 内容 |
---|---|
无状态应用 | 通常使用临时存储(emptyDir),Pod 重启数据就会丢失。不依赖持久化卷。 |
有状态应用 | 强依赖持久化存储(PersistentVolume + PVC)。Pod 即便销毁,数据仍保存在卷中,重新调度时挂载回来。典型:MySQL、PostgreSQL、Redis、Kafka。 |
3. Pod 生命周期(Lifecycle)
名称 | 内容 |
---|---|
无状态应用 | Pod 可以随意扩缩容、重建、迁移,不影响整体服务。停止 / 删除一个 Pod 不会影响数据一致性。更适合水平扩展(scale out)。 |
有状态应用 | Pod 需要稳定标识(StatefulSet 分配固定的 Pod 名称:pod-0、pod-1…)。重启、扩容、缩容顺序敏感(先启动主,再启动从)。生命周期和存储、流量绑定在一起,更复杂。 |
五、总结对比表
特性 | 无状态应用 (Stateless) | 有状态应用 (Stateful) |
---|---|---|
部署方式 | Deployment | StatefulSet |
Pod 命名 | 无固定顺序 | 有序且固定(如 mysql-0) |
存储 | 不需要持久化存储 | 必须持久化存储(PVC) |
扩缩容 | 快速扩容/缩容 | 扩缩容有顺序限制 |
典型应用 | Nginx、Web API | MySQL、Redis、Kafka |
“人的一生会经历很多痛苦,但回头想想,都是传奇”。