在 Kubernetes (K8s) 中,StatefulSet 是一种用于管理有状态应用的工作负载 API 对象。与 Deployment 管理无状态应用不同,StatefulSet 为每个 Pod 副本提供了持久性标识符(如名称和网络标识),并且可以保证部署和扩展顺序、以及网络标识和存储的稳定性。
核心特性
- 稳定、唯一的网络标识符:StatefulSet 中的每个 Pod 都有一个固定的、按顺序的名称(如
<statefulset-name>-0
),即使它们被重新调度到其他节点。 - 稳定的存储:StatefulSet 可以将持久化存储卷 (Persistent Volume) 与 Pod 的标识符关联起来,即使 Pod 被重新调度,它们的存储卷也不会丢失。
- 有序的部署、扩展和删除:StatefulSet 保证了 Pod 的部署、扩展和删除是按照严格的顺序进行的,通常是从 0 到 N-1,对于某些应用,这种顺序非常重要。
- 有序的滚动更新:StatefulSet 允许你对其管理的 Pod 进行顺序更新,确保不会同时中断多个副本。
使用场景
StatefulSet 适用于需要一个或多个以下特性的应用:
- 稳定且唯一的网络标识。
- 稳定的持久存储。
- 有序的、优雅的部署和扩展。
- 有序的、自动的滚动更新。
常见的用例包括:
- 分布式数据库,如 MongoDB、Cassandra 和 Elasticsearch。
- 任何需要持久化存储的服务。
- 有状态的应用,其中每个实例都需要保持其身份和数据。
示例
以下是一个简单的 StatefulSet 示例,它创建了一个由 3 个 Nginx 服务器 Pod 组成的 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
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "my-storage-class"
resources:
requests:
storage: 1Gi
在这个示例中:
serviceName
指定了 Pods 被控制的 Service 的名称。- StatefulSet 创建了三个 Pod 副本,每个副本都有一个固定的名称(
web-0
、web-1
和web-2
)。 volumeClaimTemplates
为每个 Pod 副本创建了一个持久化存储卷。这意味着即使 Pod 被重新调度到其他节点,数据也会被保留。
注意事项
- 使用 StatefulSet 时,需要一个头部 Service 来控制网络域。这个 Service 负责为每个 Pod 副本提供一个稳定的 DNS 名称。
- StatefulSet 的滚动更新可能比 Deployment 慢,因为它按顺序更新每个副本。
- 管理有状态应用更加复杂,需要仔细管理数据的备份和恢复策略。
StatefulSet 提供了 Kubernetes 环境中部署和管理有状态应用所需的稳定性和灵活性。