Menu

真正的有状态服务架构,考验的是团队对可靠性、自动化与数据安全的极致追求。

本文总结了在 Kubernetes 中部署有状态应用的最佳实践,涵盖 StatefulSet 与 Operator 的选择、存储与网络设计、滚动升级、备份恢复等关键环节,并通过架构图和流程图直观展示核心流程,帮助技术团队实现高可用、易运维的有状态服务。

何时使用 StatefulSet,何时使用 Operator

在 Kubernetes 中部署有状态应用时,需根据实际需求选择合适的方案。以下内容介绍两种主流方式的适用场景及优势。

核心概念与关键要点

在实际部署过程中,需关注以下核心概念与关键技术要点,以保障有状态应用的稳定性和可维护性。

```mermaid “StatefulSet Architecture Overview” %% mermaid 架构图:StatefulSet 与相关组件(示例) graph LR subgraph K8s svc[Headless Service] sts[StatefulSet] pvc1[PVC pod-0] pvc2[PVC pod-1] pvc3[PVC pod-2] sc[“StorageClass
(WaitForFirstConsumer)”] pdb[PDB] probe[startup/readiness/liveness probes] affinity[Affinity / TopologySpread] operator[Optional Operator] monitoring[Prometheus / Exporter] end

svc –> sts sts –> pvc1 sts –> pvc2 sts –> pvc3 pvc1 –> sc pvc2 –> sc pvc3 –> sc sts –> probe sts –> affinity sts –> pdb operator —|可选| sts sts — monitoring operator — monitoring


![StatefulSet Architecture Overview](/devops/using-statefulset/1d4549d05adba4d1377c46bd0bb4ccf2.svg)
{width=1940 height=826}

## 推荐的部署流程(高层)

有状态应用的标准部署流程如下,建议团队严格遵循以提升系统可靠性和可维护性。

1. 选择方案:评估是否使用 Operator;若使用 Operator,优先部署并使用其 CR(自定义资源)。
2. 设计 StorageClass:确保支持 WaitForFirstConsumer、拓扑约束、快照与扩容能力。
3. 设计 Service:Headless Service 提供 DNS;单独配置面向外部的访问方式(Ingress/Gateway/LoadBalancer)。
4. 编写 StatefulSet:
   - 指定 podManagementPolicy、updateStrategy、volumeClaimTemplates。
   - 添加 startupProbe、readinessProbe、livenessProbe,以及 preStop 钩子。
   - 配置资源 requests/limits、affinity、topologySpreadConstraints、PDB。
5. 测试:启动、扩缩容、滚动升级、故障恢复、备份恢复演练。
6. 监控与告警:Exporter、Prometheus、AlertManager、日志聚合。
7. 持续演练:升级演练、灾难恢复(DR)流程验证。

```mermaid "Deployment Workflow"
%% mermaid 流程图:部署流程(高层)
flowchart TD
  A[评估:StatefulSet vs Operator] --> B[设计 StorageClass 与 拓扑]
  B --> C[设计 Headless Service 与 对外访问]
  C --> D[编写 StatefulSet / Operator CR]
  D --> E[测试:部署 / 扩缩容 / 升级]
  E --> F[生产监控与备份演练]
  F --> G[持续演练与改进]

Deployment Workflow {width=1920 height=7038}

精简示例:Headless Service + StatefulSet(最佳实践要素)

以下为通用模板示例,生产环境建议结合 Operator 或根据实际应用补充初始化脚本与优雅停机逻辑。

# 注意:仅为示例,生产请根据实际镜像与 StorageClass 调整
apiVersion: v1
kind: Service
metadata:
  name: example-svc
  labels:
    app: example
spec:
  clusterIP: None           # Headless Service 提供稳定 DNS
  selector:
    app: example
  ports:
  - port: 9092
    name: app-port
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: example
spec:
  serviceName: example-svc
  replicas: 3
  podManagementPolicy: "OrderedReady"  # 严格顺序启动与删除(需要强一致性的应用)
  selector:
    matchLabels:
      app: example
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 0   # 可通过变更 partition 实现分阶段滚动更新
  template:
    metadata:
      labels:
        app: example
    spec:
      terminationGracePeriodSeconds: 120
      # 优先将副本分散到不同节点/zone
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: example
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  app: example
              topologyKey: kubernetes.io/hostname
      containers:
        - name: app
          image: your-registry/example:stable-2025-01
          imagePullPolicy: IfNotPresent
          resources:
            requests:
              cpu: "500m"
              memory: "1Gi"
            limits:
              cpu: "1"
              memory: "2Gi"
          ports:
            - containerPort: 9092
              name: app
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          lifecycle:
            preStop:
              exec:
                command: ["/bin/sh", "-c", "your-graceful-shutdown.sh || sleep 30"]
          # 长启动应用使用 startupProbe,避免 readiness 在启动前就失败
          startupProbe:
            exec:
              command: ["/bin/sh", "-c", "check-startup.sh"]
            failureThreshold: 60
            periodSeconds: 10
          readinessProbe:
            exec:
              command: ["/bin/sh", "-c", "check-ready.sh"]
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            exec:
              command: ["/bin/sh", "-c", "check-live.sh"]
            initialDelaySeconds: 60
            periodSeconds: 30
          volumeMounts:
            - name: data
              mountPath: /var/lib/example
      # 可选 initContainer:用于基于 hostname 生成配置
      initContainers:
        - name: init-config
          image: busybox
          command:
            - /bin/sh
            - -c
            - |
              HOST=$(hostname -s)
              # 从主机名解析 ordinal 并生成配置(示例)
              if echo "$HOST" | grep -q '\-'; then
                ORD=${HOST##*-}
                echo "ordinal=$ORD" > /tmp/ordinal
              fi
          volumeMounts:
            - name: data
              mountPath: /tmp
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        storageClassName: fast-ssd   # 使用支持 WaitForFirstConsumer 的 StorageClass
        resources:
          requests:
            storage: 50Gi

mermaid "StatefulSet Rolling Update Sequence" %% mermaid 序列图:滚动更新 / 启动顺序 示例(StatefulSet OrderedReady) sequenceDiagram participant Controller as K8s Controller participant Pod0 as pod-0 participant Pod1 as pod-1 participant Pod2 as pod-2 Controller->>Pod0: 创建并等待 ready Controller->>Pod1: 创建并等待 ready (OrderedReady) Controller->>Pod2: 创建并等待 ready Note over Pod0,Pod2: 升级时可通过 partition 控制从最高 ordinal 开始逐个更新

StatefulSet Rolling Update Sequence {width=1920 height=760}

生产建议清单(要点速查)

在实际生产环境中,建议参考以下清单,确保有状态应用的高可用与可维护性。

与历史实践的差异

近年来,Kubernetes 有状态应用的运维模式发生了显著变化,主要体现在以下方面:

总结

StatefulSet 作为 Kubernetes 提供稳定网络标识与 per‑Pod 存储的基础设施工具,依然适用于部分场景。但在大多数生产环境中,建议结合成熟的 Operator 使用,以获得更强的可用性、可观测性与自动化运维能力。设计时需从存储拓扑、探针与优雅停机、更新策略、备份恢复与演练等多个维度综合考虑,才能在真实生产环境中安全运行有状态服务。


Menu