有状态副本集

理解 StatefulSets

请参阅 Kubernetes 官方文档:StatefulSets

StatefulSet 是 Kubernetes 中用于管理有状态应用的工作负载 API 对象,具有以下能力:

  • 稳定的网络标识:DNS 主机名 <statefulset-name>-<ordinal>.<service-name>.ns.svc.cluster.local
  • 稳定的持久化存储:通过 volumeClaimTemplates 实现。
  • 有序部署/扩缩容:按顺序创建/删除 Pod:Pod-0 → Pod-1 → Pod-N。
  • 有序滚动更新:按倒序更新 Pod:Pod-N → Pod-0。

在分布式系统中,可以将多个 StatefulSet 作为独立组件部署,以提供专用的有状态服务(例如 Kafka brokersMongoDB shards)。

创建 StatefulSets

通过 CLI 创建 StatefulSet

前提条件

  • 确保已配置 kubectl,并且已连接到集群。

YAML 文件示例

# example-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: 'nginx' # this headless Service is responsible for the network identity of the Pods
  replicas: 3 # defines the desired number of Pod replicas (default: 1)
  minReadySeconds: 10 # by default is 0
  template: # defines the Pod template for the StatefulSet
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
        - name: nginx
          image: registry.k8s.io/nginx-slim:0.24
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
  volumeClaimTemplates: # defines PersistentVolumeClaim (PVC) templates. Each Pod gets a unique PersistentVolume (PV) dynamically provisioned based on these templates.
    - metadata:
        name: www
      spec:
        accessModes: ['ReadWriteOnce']
        storageClassName: 'my-storage-class'
        resources:
          requests:
            storage: 1Gi
---
# example-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
    - port: 80
      name: web
  clusterIP: None
  selector:
    app: nginx

通过 YAML 创建 StatefulSet

# Step 1: To create the StatefulSet defined in *example-statefulset.yaml*, execute the following command
kubectl apply -f example-statefulset.yaml

# Step 2: To verify the creation and status of your StatefulSet and its associated Pods and PVCs:
kubectl get statefulset web # View StatefulSet
kubectl get pods -l app=nginx # Check Pods managed by this StatefulSet
kubectl get pvc -l app=nginx # Check PVCs created by volumeClaimTemplates

通过 Web 控制台创建 StatefulSet

前提条件

获取镜像地址。镜像来源可以是平台管理员通过工具链集成到平台中的镜像仓库,也可以是第三方平台的镜像仓库。

  • 对于前者,管理员通常会将镜像仓库分配给你的项目,你可以使用其中的镜像。如果找不到所需的镜像仓库,请联系管理员进行分配。

  • 如果是第三方平台的镜像仓库,请确保当前集群可以直接从该仓库拉取镜像。

  • 如果镜像仓库需要认证,则需要配置相应的 image pull secret。更多信息,请参阅 为 ServiceAccount 添加 ImagePullSecrets

  • 通过 OCI Connector 选择镜像时,还需要为 Connector 代理选择一个 image pull Secret,或者确认工作负载的 ServiceAccount 已经引用了该 Secret。请参阅 在 OCI Connector 中使用 ImagePullSecret

通过新版 Web 控制台创建 StatefulSet

新版 Web 控制台可以从不同视图暴露 StatefulSet 的创建入口。请根据你是在项目范围内操作,还是在具体集群中操作来选择入口。

  • 应用视图:从当前项目开始。打开 Workloads > StatefulSets,选择目标 ClusterNamespace,然后选择会创建 StatefulSet 的工作负载模型或创建流程。
  • 集群视图:从具体集群开始。先打开目标集群,进入目标 namespace,然后导航到 Workloads > StatefulSets,点击 Create StatefulSet

操作步骤 - 配置基本信息

  1. Container Platform 左侧边栏中,导航到 Workloads > StatefulSets

  2. 点击 Create StatefulSet

  3. 选择输入 一个镜像,然后点击 Confirm

INFO

注意:当使用 Web 控制台中集成的镜像仓库中的镜像时,可以通过 Already Integrated 进行筛选。Integration Project Name,例如镜像(registry-projectname),其中包含了 Web 控制台中的项目名 projectname,以及镜像仓库中的项目名 containers。

Basic Info 部分中,为 StatefulSet 工作负载配置声明式参数:

参数说明
Replicas定义 StatefulSet 中期望的 Pod 副本数量(默认值:1)。可根据工作负载需求和预期请求量进行调整。
Update Strategy控制 StatefulSet 滚动更新期间的分阶段更新。RollingUpdate 策略是默认值,也是推荐值。
Partition 值:Pod 更新的序号阈值。
  • 序号 ≥ partition 的 Pod 会立即更新。
  • 序号 < partition 的 Pod 保留之前的 spec。
示例
  • Replicas=5(Pods:web-0 ~ web-4)
  • Partition=3(仅更新 web-3 和 web-4)
Volume Claim TemplatesvolumeClaimTemplates 是 StatefulSets 的一项关键特性,可为每个 Pod 提供动态持久化存储。StatefulSet 中的每个 Pod 副本都会基于预定义模板自动获得专用的 PersistentVolumeClaim(PVC)。
  • 1. 动态创建 PVC:为每个 Pod 自动创建唯一的 PVC,命名模式为:<statefulset-name>-<claim-template-name>-<pod-ordinal>示例web-www-web-0web-www-web-1
  • 2. 访问模式:支持所有 Kubernetes 访问模式。
    • ReadWriteOnce(RWO - 单节点读写)
    • ReadOnlyMany(ROX - 多节点只读)
    • ReadWriteMany(RWX - 多节点读写)。
  • 3. Storage Class:通过 storageClassName 指定存储后端。若未指定,则使用集群的默认 StorageClass。支持多种云上/本地存储类型(例如 SSD、HDD)。
  • 4. 容量:通过 resources.requests.storage 配置存储容量。示例:1Gi。如果 StorageClass 启用了动态卷扩展,则支持动态扩容。

操作步骤 - 配置 Pod

Pod 部分请参阅 Deployment - 配置 Pod

操作步骤 - 配置容器

Containers 部分请参阅 Deployment - 配置 Containers

操作步骤 - 创建

点击 Create

何时在 Applications 视图中使用 StatefulSet

当工作负载依赖于每个副本的身份、稳定命名、有序生命周期行为,或依赖应与特定副本关联的持久化存储时,请使用 StatefulSet。

通常在以下情况下,StatefulSet 是更合适的选择:

  • 每个副本都应保留稳定的序号身份
  • 工作负载依赖稳定的网络命名或相关的 headless Service
  • 每个副本都需要自己的 persistent volume claim
  • 应用依赖启动、关闭或更新顺序

如果工作负载可以被视为可互换的无状态副本,请改为查看 Deployments

Stateful 工作负载检查点

在创建或更新 StatefulSet 之前,请仔细检查以下内容:

  • 所选项目、集群和 namespace 是否是预期的运行范围
  • 每个副本是否都需要稳定身份
  • 每个副本是否都需要持久化存储
  • 工作负载是否依赖有序的启动、关闭或扩缩容行为
  • 引用的存储设置在目标环境中是否可用
  • 配置变更是否可能影响数据连续性或副本替换行为
  • 工作负载是否还依赖相关 Service 提供稳定的网络标识

健康检查

管理 StatefulSets

通过 CLI 管理 StatefulSet

查看 StatefulSet

你可以查看 StatefulSet 以获取应用信息。

  • 检查 StatefulSet 是否已创建。

    kubectl get statefulsets
  • 获取 StatefulSet 的详细信息。

    kubectl describe statefulsets

扩缩 StatefulSet

  • 要更改现有 StatefulSet 的副本数量:

    kubectl scale statefulset <statefulset-name> --replicas=<new-replica-count>
  • 示例:

    kubectl scale statefulset web --replicas=5

更新 StatefulSet(滚动更新)

当你修改 StatefulSet 的 Pod 模板时(例如更改容器镜像),Kubernetes 会默认执行滚动更新(如果 updateStrategy 设置为 RollingUpdate,而这也是默认值)。

在更改镜像或 OCI Connector 之前,请确认每个新的 Pod 版本都可以直接或通过其 ServiceAccount 获取有效的 Connector 代理 image pull Secret。在有序更新期间,请检查每个 Pod 的 Connector 注解、重写后的代理镜像、状态和 Events。如果某个序号 Pod 进入 ImagePullBackOff,请停止发布流程,并在继续之前检查 Secret、ServiceAccount 和令牌有效性。

  • 首先,编辑 YAML 文件(例如 example-statefulset.yaml)并应用所需更改:

    kubectl apply -f example-statefulset.yaml
  • 然后,你可以监控滚动更新的进度:

    kubectl rollout status statefulset/<statefulset-name>

删除 StatefulSet

要删除 StatefulSet 及其关联的 Pod:

kubectl delete statefulset <statefulset-name>

默认情况下,删除 StatefulSet 不会删除其关联的 PersistentVolumeClaims(PVCs)或 PersistentVolumes(PVs),以防止数据丢失。若要同时删除 PVCs,必须显式执行:

kubectl delete pvc -l app=<label-selector-for-your-statefulset> # Example: kubectl delete pvc -l app=nginx

另外,如果你的 volumeClaimTemplates 使用的 StorageClassreclaimPolicyDelete,那么当 PVCs 被删除时,PV 和底层存储也会自动删除。

通过 Web 控制台管理 StatefulSet

查看 StatefulSet

  1. Container Platform 中,导航到 Workloads > StatefulSets
  2. 找到你要查看的 StatefulSet。
  3. 点击 statefulSet 名称以查看 DetailsTopologyLogsEventsMonitoring 等信息。

更新 StatefulSet

  1. Container Platform 中,导航到 Workloads > StatefulSets
  2. 找到你要更新的 StatefulSet。
  3. Actions 下拉菜单中选择 Update,进入 Edit StatefulSet 页面,你可以更新 ReplicasimageupdateStrategy 等参数。

在更改镜像或 OCI Connector 时,也要检查 Connector 代理 image pull Secret、工作负载 ServiceAccount 和令牌有效性。观察有序 Pod 替换过程,并验证每个新 Pod 的实际镜像重写情况和 Events。

删除 StatefulSet

  1. Container Platform 中,导航到 Workloads > StatefulSets
  2. 找到你要删除的 StatefulSet。
  3. Actions 下拉菜单中,点击操作列中的 Delete 按钮并确认。

StatefulSet 的删除和扩缩容可能会带来与无状态工作负载不同的存储影响。在删除或缩容之前,请确认被移除的副本不再持有所需数据或集群成员关系。