K8s中 statefulset 和deployment的区别

在 Kubernetes 中,StatefulSet 和 Deployment 是两种管理 Pod 的控制器,它们的主要区别在于 状态管理 和 Pod 的标识。以下是详细对比:


1. 功能定位

Deployment

  • 用途 :用于 无状态应用 的部署,例如 Web 服务、API 服务等。
  • 特点 :
    • 每个 Pod 是完全独立的,没有严格的顺序或唯一性要求。
    • 适用于场景:服务是无状态的,多个副本的实例可以随时替换、扩缩。

StatefulSet

  • 用途 :用于 有状态应用 的部署,例如数据库、分布式缓存、分布式文件系统等。
  • 特点 :
    • 提供对 Pod 顺序启动、停止 的控制。
    • 为每个 Pod 分配一个固定的标识(Stable Identity)。
    • 适用于场景:应用需要持久化数据或对实例的顺序、标识有严格要求。

2. Pod 标识和命名

Deployment

  • 每个 Pod 都是无状态的,没有固定的名称或标识。
  • 如果 Pod 被删除,一个新 Pod 会创建,且新 Pod 的名称不同。
  • 示例:nginx-abcdef123(随机生成的后缀)。

StatefulSet

  • 每个 Pod 都有固定的名称和编号(Stable Identity)。
  • 即使 Pod 被删除,重新创建后仍然保持相同的名称。
  • 示例:nginx-0, nginx-1, nginx-2。

3. 存储卷管理

Deployment

  • 默认使用临时存储(ephemeral storage),Pod 重启后数据会丢失。
  • 如果需要持久化存储,需要手动配置 PersistentVolume(PV)和 PersistentVolumeClaim(PVC)。

StatefulSet

  • 每个 Pod 都会拥有自己的持久化存储(Persistent Volume),并且存储卷与 Pod 的标识绑定。
  • 如果 Pod 被删除或重建,其关联的存储卷不会被删除,数据可以恢复。

4. Pod 的启动顺序

Deployment

  • Pod 的启动顺序无关紧要,Kubernetes 会尽快启动所有 Pod,彼此之间没有依赖关系。

StatefulSet

  • Pod 的启动是 有序 的:
    • 顺序启动:Pod-0 -> Pod-1 -> Pod-2...
    • 顺序删除:Pod-N -> Pod-(N-1) -> ...
    • 对于某些应用程序(如主从数据库),这种顺序启动/停止特性是必需的。

5. 更新机制

Deployment

  • 支持 滚动更新,即逐步替换旧 Pod,直到所有 Pod 更新完成。
  • 更新速度可以通过 maxSurge 和 maxUnavailable 参数控制。

StatefulSet

  • 同样支持滚动更新,但默认是 逐个更新(按照 Pod 的编号顺序)。
  • 需要确保新的 Pod 启动后,旧的 Pod 才会更新。

6. 应用场景

特性 Deployment StatefulSet
使用场景 无状态服务 有状态服务
数据持久化 不提供默认支持(需手动配置) 每个 Pod 绑定专属存储卷
启动顺序 无关 严格的顺序(0 -> N)
Pod 的标识 动态生成的名称 固定名称(<name>-<编号>)
横向扩展 支持 支持
典型应用场景 Web 服务、API 服务 数据库、Kafka、Redis 集群

7. 示例对比

Deployment 示例

用于无状态 Web 服务:

复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
  • 部署后会创建 3 个副本 Pod,例如:nginx-xyz12, nginx-abc34, nginx-uvw56。

StatefulSet 示例

用于有状态服务(如 Redis):

复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis
spec:
  serviceName: "redis"
  replicas: 3
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - name: redis
        image: redis:6.2
        ports:
        - containerPort: 6379
  volumeClaimTemplates:
  - metadata:
      name: redis-data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi
  • 部署后会创建 Pod:
    • redis-0, redis-1, redis-2
    • 每个 Pod 绑定自己的存储卷 redis-data-redis-0, redis-data-redis-1。

8. 选择哪种控制器?

使用 Deployment 的场景

  • 无状态服务,例如:
    • Web 应用
    • API 网关
    • 任务处理服务

使用 StatefulSet 的场景

  • 有状态服务,例如:
    • 数据库(MySQL、PostgreSQL、MongoDB 等)
    • 分布式存储(Cassandra、HDFS 等)
    • 缓存服务(Redis、ZooKeeper、Kafka 等)

总结

  • Deployment 是通用的控制器,适合大多数无状态应用场景。
  • StatefulSet 则为有状态服务提供独特的支持,例如持久化存储和固定标识。
  • 根据应用是否需要持久化存储、顺序启动/停止、固定 Pod 标识来选择适合的控制器。
相关推荐
知已难寻7 小时前
第 2 篇 · 云的地基:服务器、存储、网络三大基础设施
运维·服务器·网络·云原生·云计算·负载均衡·1024程序员节
阿里云云原生11 小时前
车企数据隐私保护必修课:如何用 SLS mask 守住日志中的敏感信息
云原生
阿里云云原生11 小时前
切换模型会损失缓存,智能路由还省钱吗?
云原生
闲云野鹤在人间11 小时前
Kubernetes Service 与 kube-proxy 详解
云原生·容器·kubernetes
我不会起名字32212 小时前
节点 NotReady:kubelet 与容器运行时的 4 步排查
云原生·kubernetes·kubelet·排查
说实话起个名字真难啊13 小时前
实战docker部署dify及注意点
运维·docker·容器
闲云自留地13 小时前
K8s Service 全解:服务发现、四种类型、会话保持、金丝雀发布一篇通
容器·kubernetes·服务发现
分布式存储与RustFS14 小时前
GPU 在空转等数据?PyTorch 训练集进 RustFS 的三种接法
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
choumin15 小时前
C++ 标准容器为什么不能存引用
c++·容器·引用类型
时间售卖铺17 小时前
MySQL 备份
运维·数据库·mysql·云原生