有状态副本集

理解 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 brokers、MongoDB 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,选择目标 Cluster 和 Namespace,然后选择会创建 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-0、web-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 使用的 StorageClass 的 reclaimPolicy 为 Delete,那么当 PVCs 被删除时,PV 和底层存储也会自动删除。

通过 Web 控制台管理 StatefulSet

查看 StatefulSet

  1. 在 Container Platform 中,导航到 Workloads > StatefulSets。
  2. 找到你要查看的 StatefulSet。
  3. 点击 statefulSet 名称以查看 Details、Topology、Logs、Events、Monitoring 等信息。

更新 StatefulSet

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

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

删除 StatefulSet

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

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