1. 概述

Kubernetes(简称 K8s)是一个开源的容器编排系统,用于自动化部署、扩展和管理容器化应用。

在本篇文章中,我们将深入探讨 Kubernetes 中两种常用的部署资源:

  • Deployment
  • StatefulSet

在开始之前,我们先了解下什么是有状态应用无状态应用


2. 有状态 vs 无状态应用

区分两者的关键在于是否需要持久化数据存储

无状态应用不保存状态数据,每次请求都是独立的,状态通常保存在外部服务中(如数据库)。例如 Web 服务、API 服务。

有状态应用则需要持久化存储来保存状态信息,即使 Pod 重启或被调度到其他节点,数据也不能丢失。例如 MySQL、MongoDB、ZooKeeper、Kafka 等数据库或分布式系统。

⚠️ Kubernetes 最初设计是为无状态服务优化的,但通过 StatefulSet 的引入,也很好地支持了有状态应用的部署与管理。


3. Deployment

3.1 基本概念

Deployment 是 Kubernetes 中用于管理无状态 Pod 的控制器。它通过 ReplicaSet 来确保指定数量的 Pod 副本始终处于运行状态。

Deployment 的主要特性包括:

  • 支持滚动更新(Rolling Update)
  • 支持版本回滚
  • Pod 是“可替换的”,即没有唯一标识
  • Pod 名称是随机生成的

Deployment 适用于部署无状态服务,但也可以通过挂载 PVC(Persistent Volume Claim)实现“伪有状态”功能。

3.2 Deployment 的组件结构

一个完整的 Deployment 部署通常包含以下三个组件:

  1. Deployment 模板
  2. PersistentVolumeClaim(PVC)
  3. Service(通常是 ClusterIP 或 NodePort)

示例 YAML:Deployment 模板

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app-deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 1
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web-app
          image: hello-world:nanoserver-1809
          volumeMounts:
            - name: counter
              mountPath: /app/
      volumes:
        - name: counter
          persistentVolumeClaim:
            claimName: counter

示例 YAML:PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: counter
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 50Mi
  storageClassName: default

示例 YAML:Service 模板

apiVersion: v1
kind: Service
metadata:
  name: web-app-service
spec:
  ports:
    - name: http
      port: 80
      nodePort: 30080
  selector:
    app: web-app
  type: NodePort

3.3 部署与操作

使用 kubectl 命令部署服务和 Deployment:

kubectl apply -f service.yaml
kubectl apply -f deployment.yaml

查看 Deployment 状态:

kubectl describe deployment web-app-deployment

Deployment 内部会创建 ReplicaSet,ReplicaSet 再创建 Pod。更新 Deployment 时会创建新的 ReplicaSet,逐步替换旧 Pod。如果更新失败,旧 ReplicaSet 仍保留,支持手动回滚。


4. StatefulSet

4.1 基本概念

StatefulSet 是 Kubernetes 中用于管理有状态 Pod 的控制器。它与 Deployment 的最大区别在于:

✅ 每个 Pod 都有稳定的唯一标识(包括网络标识和存储标识)

❌ Pod 是“不可替换的”,Pod 名称是有序的(如 web-0, web-1, web-2)

StatefulSet 的主要特性包括:

  • Pod 名称具有顺序性
  • 每个 Pod 有独立的 PVC
  • 支持滚动更新(但不支持回滚)
  • 删除或缩容不会自动删除关联的 PVC

4.2 Headless Service

StatefulSet 必须配合 Headless Service 使用。Headless Service 没有 ClusterIP,直接返回 Pod IP,用于实现 Pod 间的 DNS 解析。

示例 YAML:Headless Service

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

4.3 StatefulSet 的组件结构

StatefulSet 部署通常包含以下三个组件:

  1. StatefulSet 模板
  2. PersistentVolumeClaim(PVC)
  3. Headless Service

示例 YAML:StatefulSet 模板

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80
              name: web
          volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
      volumes:
        - name: www
          persistentVolumeClaim:
            claimName: myclaim

示例 YAML:PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

4.4 部署与操作

使用 kubectl 创建 StatefulSet:

kubectl create -f statefulset.yaml

查看 Pod:

kubectl get pods

输出示例:

NAME      READY   STATUS    RESTARTS   AGE
web-0     1/1     Running   0          1m
web-1     1/1     Running   0          46s
web-2     1/1     Running   0          18s

StatefulSet 不会创建 ReplicaSet,因此不支持版本回滚。更新时采用滚动更新策略,一次更新一个 Pod。更新失败时,仅当前 Pod 被影响,其余 Pod 仍运行旧版本。

缩容或删除 StatefulSet 时,关联的 PVC 不会被自动删除,以保证数据安全。

4.5 典型使用场景

StatefulSet 适用于以下场景:

  • 需要唯一稳定标识的应用(如数据库、分布式系统)
  • 数据需要持久化存储
  • Pod 之间需要互相通信(如集群节点发现)

常见应用包括:

  • MySQL 集群
  • MongoDB
  • Redis
  • Kafka
  • ZooKeeper
  • Solr 集群

5. Deployment 与 StatefulSet 对比

特性 Deployment StatefulSet
适用场景 无状态应用 有状态应用
Pod 是否可替换 ✅ 可替换 ❌ 不可替换
Pod 名称 随机生成 有序名称(如 web-0)
网络标识 依赖 Service 依赖 Headless Service
存储 共享 PVC 每个 Pod 有独立 PVC
回滚支持 ✅ 支持 ❌ 不支持
更新策略 RollingUpdate RollingUpdate
缩容行为 自动删除 Pod 不自动删除 PVC
典型用途 Web 服务、API 服务等 数据库、消息队列、分布式系统等

6. 总结

在 Kubernetes 中,Deployment 和 StatefulSet 是两种核心的控制器资源,分别适用于不同类型的业务场景。

  • Deployment 适用于部署无状态服务,具备良好的滚动更新和回滚能力。
  • StatefulSet 适用于部署有状态服务,为每个 Pod 提供稳定的网络标识和独立的持久化存储。

选择合适的控制器资源,是实现高可用、易维护、可扩展的 Kubernetes 应用部署的关键一步。


原始标题:Kubernetes Deployment vs. StatefulSets