在 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-0web-1web-2)。
  • volumeClaimTemplates 为每个 Pod 副本创建了一个持久化存储卷。这意味着即使 Pod 被重新调度到其他节点,数据也会被保留。

注意事项

  • 使用 StatefulSet 时,需要一个头部 Service 来控制网络域。这个 Service 负责为每个 Pod 副本提供一个稳定的 DNS 名称。
  • StatefulSet 的滚动更新可能比 Deployment 慢,因为它按顺序更新每个副本。
  • 管理有状态应用更加复杂,需要仔细管理数据的备份和恢复策略。

StatefulSet 提供了 Kubernetes 环境中部署和管理有状态应用所需的稳定性和灵活性。

04-04 11:19