StatefulSet详解:构建有状态应用的利器

科技   2024-11-13 07:31   广东  

StatefulSet 是 Kubernetes 专门设计用于管理 有状态应用 的控制器。它在处理 网络标识、持久存储、Pod 启动顺序 等方面有独特的优势,非常适合管理数据库、分布式存储等需要持久性和有序性的应用。

StatefulSet基本的工作流程如下

以下将从 工作原理、核心配置、更新策略、应用场景、注意事项 等多个方面进行详细分析。

1. StatefulSet 工作原理

StatefulSet 的设计目标是提供有状态应用的核心特性:

唯一性:确保每个 Pod 在集群中都有唯一标识。

持久性:即使 Pod 被删除或重建,存储数据依然保留。

有序性:控制 Pod 的创建、更新、删除顺序。

1.1 组件关系

StatefulSet 通常与以下组件协同工作:

组件描述
StatefulSet定义和管理有状态应用,负责控制 Pod 和卷的生命周期。
Pod由 StatefulSet 创建,具有唯一标识(如 web-0, web-1)
Headless Service提供稳定的网络标识,用于为每个 Pod 提供独立的 DNS 名称。
PersistentVolumeClaim (PVC)每个 Pod 绑定一个独立的 PVC,用于存储持久化数据。

1.2 有序操作

StatefulSet 在以下场景下保证 Pod 操作的有序性:

创建顺序:按序号(ordinal)依次创建 Pod(从 web-0 到 web-N)。

更新顺序:从高序号到低序号逐步更新 Pod。

删除顺序:从高序号 Pod 开始删除。

恢复顺序:当某个 Pod 失败时,先恢复低序号 Pod。

2. StatefulSet 配置详解

下面举例一个简单例子,这里用的是Nginx


apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "web"  # 引用 Headless Service
  replicas: 3         # 创建 3 个副本
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
        volumeMounts:
        - name: data
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:   # PVC需要提前配置好
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi

定义一个无头服务:

apiVersion: v1
kind: Service
metadata:
  name: web
spec:  
  clusterIP: None  
  selector:    
    app: nginx  
  ports:  
  - port: 80

关键字段解析

serviceName

该字段是为了关联一个 Headless Service。Headless Service 的 clusterIP 为 None,它为每个 Pod 提供唯一的 DNS 名称。例如,web-0 的 DNS 名称为:

web-0.web.default.svc.cluster.local

replicas

定义 StatefulSet 运行的 Pod 副本数量。

volumeClaimTemplates

定义 PVC 模板,用于动态生成持久存储卷。每个 Pod 都会获得独立的 PVC,例如 data-web-0, data-web-1, data-web-2。这些 PVC 可以关联到不同的 PersistentVolume(PV),确保每个 Pod 的数据独立。

podManagementPolicy

控制 Pod 的创建和删除方式:

OrderedReady(默认):Pod 按序号顺序启动,只有前一个 Pod 处于 Ready 状态时,才启动下一个。

Parallel:Pod 可以并行启动或删除。配置为:

podManagementPolicy: Parallel

3. StatefulSet 操作流程

3.1 创建 StatefulSet

使用StatefulSet 配置文件创建:

kubectl apply -f statefulset.yaml

3.2 查看 StatefulSet 和 Pod 状态

查看时要注意名称空间

kubectl get statefulsets
kubectl get pods 

3.3 查看Statefulset详细信息

kubectl describe sts <statefulset-name>
kubectl describe sts web

3.4 直接修改statefulset

kubectl edit sts <statefulset-name>
kubectl edit sts web

谨慎操作:修改完立即生效

3.5 扩容与缩容

扩容:

kubectl scale statefulset web --replicas=5

新增 web-3 和 web-4 两个 Pod。

缩容:

kubectl scale statefulset web --replicas=2

删除web-4, web-3 和 web-2,且其对应的 PVC 会被保留。

3.4 删除 StatefulSet

保留 PVC:

kubectl delete statefulset web --cascade=orphan

不保留PVC:

kubectl delete pvc -l app=nginx

4. StatefulSet 更新机制

4.1 RollingUpdate 策略

RollingUpdate 是默认的更新策略,更新时按以下步骤进行:

从高序号 Pod 开始更新。只有当高序号 Pod 更新成功并进入 Ready 状态时,才会更新下一个 Pod。

updateStrategy:
  type: RollingUpdate

4.2 OnDelete 策略

OnDelete 策略不自动更新 Pod。只有在手动删除 Pod 时,新的 Pod 才会被重新创建,并使用新的模板。

updateStrategy:
  type: OnDelete

5. StatefulSet 使用场景

StatefulSet 适用于需要 持久化存储、稳定网络标识 和 有序操作 的应用。以下是几个典型场景:

5.1 数据库

如 MySQL、PostgreSQL、MongoDB:

需要每个数据库实例有唯一标识。数据存储需要持久化,即使 Pod 被重新调度或删除,数据也不能丢失。

5.2 分布式存储

如 Cassandra、Elasticsearch、HDFS:

每个存储节点有独立的存储卷。集群内节点需要通过稳定的 DNS 名称进行通信。

5.3 消息队列

如 Kafka、RabbitMQ:

每个 Broker 需要持久化存储日志或消息。Broker 节点需要稳定标识以加入集群。

5.4 缓存系统

如 Redis、Memcached:

配置主从模式,主节点和从节点需要有固定标识以确保同步关系。

6. StatefulSet 与其他控制器比较

7. StatefulSet 常见问题和注意事项

7.1 Pod 启动时间过长

StatefulSet 在创建 Pod 时,会等待前一个 Pod 进入 Ready 状态。因此,如果某个 Pod 启动时间较长,会阻塞后续 Pod 的创建。

解决方法:

检查容器的启动探针 (readinessProbe) 是否配置合理。如果无须严格的启动顺序,可以将 podManagementPolicy 设置为 Parallel。

7.2 删除 StatefulSet 时数据未保留

默认情况下,删除 StatefulSet 也会删除其 Pod 和相关资源。

如果希望保留 PVC,需使用 --cascade=orphan 参数。

7.3 滚动更新失败

如果某个 Pod 在更新过程中无法进入 Ready 状态,将阻塞后续 Pod 的更新。

解决方法:

调整更新策略为 OnDelete,手动控制更新。优化 Pod 的配置和探针设置。StatefulSet 是 Kubernetes 中管理有状态应用的核心工具。通过它,可以为有序性和持久性要求高的系统提供强大的支持。希望这份超详解能够帮助你深入理解并灵活使用 StatefulSet!


往期精彩文章



运维李哥不背锅
专注于各种运维技术、,分享Linux基础知识,服务器,数据库,云原生和网络安全等相关技术,各种进阶知识等着你,助你成为技术达人!
 最新文章