**StatefulSet** 是 Kubernetes 中用于管理 **有状态应用(Stateful Application)** 的控制器,专为需要稳定网络标识、持久化存储和有序部署/扩缩容的场景设计。与 `Deployment` 或 `DaemonSet` 不同,StatefulSet 确保每个 Pod 具有唯一且固定的标识,即使重新调度也能保持一致性。
---
### **核心特性**
1. **稳定的网络标识**
- 每个 Pod 拥有唯一的名称(如 `web-0`, `web-1`)和 DNS 记录(`<pod-name>.<service-name>.<namespace>.svc.cluster.local`)。
- 即使 Pod 被重新调度,名称和网络标识不变。
2. **持久化存储**
- 通过 `volumeClaimTemplates` 为每个 Pod 动态创建独立的持久卷(PersistentVolume, PV),数据与 Pod 生命周期解耦。
- 存储随 Pod 的调度自动绑定,适合需要保留数据的应用(如数据库)。
3. **有序部署与扩缩容**
- **顺序创建**:按索引递增顺序部署 Pod(如先 `web-0`,再 `web-1`)。
- **逆序删除**:缩容时按索引递减顺序终止 Pod(如先删 `web-1`,再删 `web-0`)。
- **有序滚动更新**:更新时按反向顺序(从最大索引到最小索引)替换 Pod。
4. **与 Headless Service 强绑定**
- 需关联一个 **Headless Service**(无头服务,`clusterIP: None`),用于控制 Pod 的网络标识和发现机制。
---
### **与 Deployment 的区别**
| **特性** | **Deployment** | **StatefulSet** |
|------------------------|--------------------------------|-------------------------------------|
| **适用场景** | 无状态应用(如 Web 服务) | 有状态应用(如 MySQL、Redis) |
| **Pod 标识** | 随机名称,无固定标识 | 唯一名称(如 `web-0`, `web-1`) |
| **存储** | 临时存储(Volume 可共享) | 独立持久化存储(Volume 与 Pod 绑定)|
| **扩缩容顺序** | 并行创建/删除 | 顺序创建,逆序删除 |
| **网络标识** | 通过 Service 负载均衡 | 稳定的 DNS 记录(直接访问单个 Pod) |
---
### **典型使用场景**
1. **数据库集群**
- 如 MySQL、PostgreSQL、MongoDB 等,需确保主从节点有序启动和数据持久化。
2. **分布式存储系统**
- 如 Elasticsearch、Cassandra,依赖稳定的网络标识和持久化存储。
3. **消息队列**
- 如 Kafka、RabbitMQ,每个节点需独立存储消息数据。
4. **有状态中间件**
- 如 Redis 哨兵、ZooKeeper 集群。
---
### **工作机制**
#### **1. Pod 标识与 DNS**
- 每个 Pod 名称格式为 `<statefulset-name>-<ordinal-index>`(如 `redis-0`, `redis-1`)。
- 通过 Headless Service 暴露的 DNS 记录可直接访问特定 Pod:
```bash
redis-0.redis.default.svc.cluster.local # 访问第一个 Pod
redis-1.redis.default.svc.cluster.local # 访问第二个 Pod
```
#### **2. 持久化存储**
- 使用 `volumeClaimTemplates` 定义存储模板,每个 Pod 自动创建独立的 PVC(PersistentVolumeClaim):
```yaml
volumeClaimTemplates:
- metadata:
name: data # 卷名称
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
```
- 存储卷生命周期与 Pod 解耦,删除 Pod 时保留数据,适合重建后恢复。
#### **3. 有序调度**
- **扩容时**:按索引顺序创建新 Pod(先 `web-0`,再 `web-1`),确保前一个 Pod 进入 `Running` 状态后再创建下一个。
- **缩容时**:按逆序删除 Pod,避免数据丢失风险(如优先删除从节点而非主节点)。
---
### **YAML 示例**
```yaml
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
clusterIP: None # Headless Service
selector:
app: redis
ports:
- port: 6379
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: "redis" # 必须关联 Headless Service
replicas: 3
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates: # 存储模板
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
```
---
### **关键配置**
1. **Headless Service**
- 必须定义,用于 Pod 的 DNS 解析和网络标识。
2. **volumeClaimTemplates**
- 定义存储模板,确保每个 Pod 拥有独立存储。
3. **更新策略**
- 通过 `spec.updateStrategy.type` 指定:
- `RollingUpdate`:滚动更新(默认)。
- `OnDelete`:手动删除 Pod 后触发更新。
4. **Pod 管理策略**
- `spec.podManagementPolicy`:
- `OrderedReady`:默认,顺序创建 Pod。
- `Parallel`:并行创建(牺牲有序性,提高速度)。
---
### **注意事项**
1. **资源管理**
- 为每个 Pod 预留足够的 CPU/内存资源,避免因资源竞争导致调度失败。
2. **存储配置**
- 确保 StorageClass 可用,避免 PVC 处于 Pending 状态。
3. **删除操作**
- 删除 StatefulSet 时,默认不会自动删除关联的 PVC,需手动清理:
```bash
kubectl delete statefulset <name> --cascade=orphan # 保留 Pod 和 PVC
kubectl delete pvc -l app=<label> # 手动删除 PVC
```
4. **监控与备份**
- 持久化数据需定期备份(如通过 Velero),避免数据丢失。
---
### **总结**
StatefulSet 是 Kubernetes 管理有状态应用的核心工具,通过稳定的网络标识、持久化存储和有序调度,为数据库、消息队列等场景提供可靠支持。理解其与 Deployment 的区别,合理设计存储和更新策略,是构建高可用有状态服务的关键。