有状态副本集

了解有状态副本集

参考官方 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)。

创建有状态副本集

使用 CLI 创建有状态副本集

前提条件

  • 确保你已配置 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 创建有状态副本集

# 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 控制台创建有状态副本集

前提条件

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

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

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

  • 如果镜像仓库需要认证,你需要配置相应的 image pull Secret。更多信息,请参见 将 ImagePullSecrets 添加到 ServiceAccount。

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

使用新的 web 控制台创建有状态副本集

新的 web 控制台可以从不同视图暴露 StatefulSet 的创建入口。请根据你是从项目范围还是从具体集群进行操作,选择相应入口。

  • Applications view:从当前项目开始。打开 Workloads > StatefulSets,选择目标 Cluster 和 Namespace,然后选择会生成 StatefulSet 的工作负载模型或创建流程。
  • Clusters view:从具体集群开始。先打开目标集群,进入目标命名空间,然后导航到 Workloads > StatefulSets,点击 Create StatefulSet。

操作步骤 - 配置基本信息

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

  2. 点击 Create StatefulSet。

  3. Select 或 Input 一个镜像,然后点击 Confirm。

INFO

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

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

参数描述
Replicas定义 StatefulSet 中所需的 Pod 副本数量(默认值:1)。请根据工作负载需求和预期请求量进行调整。
Update Strategy控制 StatefulSet 滚动更新期间的分阶段更新。RollingUpdate 策略为默认值,且推荐使用。
Partition 值:用于 Pod 更新的序号阈值。
  • 索引 ≥ partition 的 Pod 会立即更新。
  • 索引 < partition 的 Pod 将保留之前的规格。
示例:
  • Replicas=5(Pods: web-0 ~ web-4)
  • Partition=3(仅更新 web-3 和 web-4)
Volume Claim TemplatesvolumeClaimTemplates 是 StatefulSet 的关键特性,它支持为每个 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 - Configure Pod

操作步骤 - 配置容器

Containers 部分,请参阅 Deployment - Configure Containers

操作步骤 - 创建

点击 Create。

何时在 Applications 视图中使用有状态副本集

当工作负载依赖于每个副本的标识、稳定命名、有序生命周期行为,或者需要与特定副本保持关联的持久存储时,应使用有状态副本集。

通常在以下场景中,有状态副本集更适合:

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

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

有状态工作负载审查要点

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

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

健康检查

管理有状态副本集

使用 CLI 管理有状态副本集

查看有状态副本集

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

  • 检查 StatefulSet 是否已创建。

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

    kubectl describe statefulsets

扩缩有状态副本集

  • 修改现有 StatefulSet 的副本数量:

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

    kubectl scale statefulset web --replicas=5

更新有状态副本集(Rolling Update)

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

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

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

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

    kubectl rollout status statefulset/<statefulset-name>

删除有状态副本集

要删除 StatefulSet 及其关联的 Pod:

kubectl delete statefulset <statefulset-name>

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

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

另外,如果你的 volumeClaimTemplates 使用的 StorageClass 的 reclaimPolicy 为 Delete,则在 PVC 被删除时,PVs 及其底层存储也会自动删除。

使用 web 控制台管理有状态副本集

查看有状态副本集

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

更新有状态副本集

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

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

删除有状态副本集

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

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