1. 概述
Kubernetes(简称 K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用。
在本篇文章中,我们将深入探讨 Kubernetes 中两种常用的部署资源:
- Deployment
- StatefulSet
在开始之前,我们先了解下什么是有状态应用与无状态应用。
2. 有状态 vs 无状态应用
区分两者的关键在于是否需要持久化数据存储:
✅ 无状态应用不保存状态数据,每次请求都是独立的,状态通常保存在外部服务中(如数据库)。例如 Web 服务、API 服务。
❌ 有状态应用则需要持久化存储来保存状态信息,即使 Pod 重启或被调度到其他节点,数据也不能丢失。例如 MySQL、MongoDB、ZooKeeper、Kafka 等数据库或分布式系统。
⚠️ Kubernetes 最初设计是为无状态服务优化的,但通过 StatefulSet 的引入,也很好地支持了有状态应用的部署与管理。
3. Deployment
3.1 基本概念
Deployment 是 Kubernetes 中用于管理无状态 Pod 的控制器。它通过 ReplicaSet 来确保指定数量的 Pod 副本始终处于运行状态。
Deployment 的主要特性包括:
- 支持滚动更新(Rolling Update)
- 支持版本回滚
- Pod 是“可替换的”,即没有唯一标识
- Pod 名称是随机生成的
Deployment 适用于部署无状态服务,但也可以通过挂载 PVC(Persistent Volume Claim)实现“伪有状态”功能。
3.2 Deployment 的组件结构
一个完整的 Deployment 部署通常包含以下三个组件:
- Deployment 模板
- PersistentVolumeClaim(PVC)
- Service(通常是 ClusterIP 或 NodePort)
示例 YAML:Deployment 模板
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: hello-world:nanoserver-1809
volumeMounts:
- name: counter
mountPath: /app/
volumes:
- name: counter
persistentVolumeClaim:
claimName: counter
示例 YAML:PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: counter
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 50Mi
storageClassName: default
示例 YAML:Service 模板
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
ports:
- name: http
port: 80
nodePort: 30080
selector:
app: web-app
type: NodePort
3.3 部署与操作
使用 kubectl
命令部署服务和 Deployment:
kubectl apply -f service.yaml
kubectl apply -f deployment.yaml
查看 Deployment 状态:
kubectl describe deployment web-app-deployment
Deployment 内部会创建 ReplicaSet,ReplicaSet 再创建 Pod。更新 Deployment 时会创建新的 ReplicaSet,逐步替换旧 Pod。如果更新失败,旧 ReplicaSet 仍保留,支持手动回滚。
4. StatefulSet
4.1 基本概念
StatefulSet 是 Kubernetes 中用于管理有状态 Pod 的控制器。它与 Deployment 的最大区别在于:
✅ 每个 Pod 都有稳定的唯一标识(包括网络标识和存储标识)
❌ Pod 是“不可替换的”,Pod 名称是有序的(如 web-0, web-1, web-2)
StatefulSet 的主要特性包括:
- Pod 名称具有顺序性
- 每个 Pod 有独立的 PVC
- 支持滚动更新(但不支持回滚)
- 删除或缩容不会自动删除关联的 PVC
4.2 Headless Service
StatefulSet 必须配合 Headless Service 使用。Headless Service 没有 ClusterIP,直接返回 Pod IP,用于实现 Pod 间的 DNS 解析。
示例 YAML:Headless Service
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
4.3 StatefulSet 的组件结构
StatefulSet 部署通常包含以下三个组件:
- StatefulSet 模板
- PersistentVolumeClaim(PVC)
- Headless Service
示例 YAML:StatefulSet 模板
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: myclaim
示例 YAML:PersistentVolumeClaim
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
4.4 部署与操作
使用 kubectl
创建 StatefulSet:
kubectl create -f statefulset.yaml
查看 Pod:
kubectl get pods
输出示例:
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 1m
web-1 1/1 Running 0 46s
web-2 1/1 Running 0 18s
StatefulSet 不会创建 ReplicaSet,因此不支持版本回滚。更新时采用滚动更新策略,一次更新一个 Pod。更新失败时,仅当前 Pod 被影响,其余 Pod 仍运行旧版本。
缩容或删除 StatefulSet 时,关联的 PVC 不会被自动删除,以保证数据安全。
4.5 典型使用场景
StatefulSet 适用于以下场景:
- 需要唯一稳定标识的应用(如数据库、分布式系统)
- 数据需要持久化存储
- Pod 之间需要互相通信(如集群节点发现)
常见应用包括:
- MySQL 集群
- MongoDB
- Redis
- Kafka
- ZooKeeper
- Solr 集群
5. Deployment 与 StatefulSet 对比
特性 | Deployment | StatefulSet |
---|---|---|
适用场景 | 无状态应用 | 有状态应用 |
Pod 是否可替换 | ✅ 可替换 | ❌ 不可替换 |
Pod 名称 | 随机生成 | 有序名称(如 web-0) |
网络标识 | 依赖 Service | 依赖 Headless Service |
存储 | 共享 PVC | 每个 Pod 有独立 PVC |
回滚支持 | ✅ 支持 | ❌ 不支持 |
更新策略 | RollingUpdate | RollingUpdate |
缩容行为 | 自动删除 Pod | 不自动删除 PVC |
典型用途 | Web 服务、API 服务等 | 数据库、消息队列、分布式系统等 |
6. 总结
在 Kubernetes 中,Deployment 和 StatefulSet 是两种核心的控制器资源,分别适用于不同类型的业务场景。
- ✅ Deployment 适用于部署无状态服务,具备良好的滚动更新和回滚能力。
- ✅ StatefulSet 适用于部署有状态服务,为每个 Pod 提供稳定的网络标识和独立的持久化存储。
选择合适的控制器资源,是实现高可用、易维护、可扩展的 Kubernetes 应用部署的关键一步。