K8S-Statefulset控制器

在 Kubernetes 的世界里,服务通常分为有状态和无状态两种类型。对于无状态服务,我们可以轻松地使用 Deployment 或 RC 来管理,但当面对需要稳定网络标识和持久化存储的有状态服务时,StatefulSet 就成为了最佳选择。本文将深入解析 StatefulSet 控制器的核心概念、工作原理及实际应用。

一、StatefulSet 核心概念解析

有状态服务 vs 无状态服务

Kubernetes 中存在两种服务类型,它们的管理方式有着本质区别:

  • 无状态服务:由 RC、Deployment、DaemonSet 等控制器管理,其 Pod 的 IP、名称、启停顺序都是随机的,个体对整体无影响,所有 Pod 共享相同的数据卷(如 Tomcat 集群)

  • 有状态服务:由 StatefulSet 管理,其 Pod 名称固定不变,每个 Pod 拥有独立的持久化存储目录,适用于需要稳定标识和状态的服务(如 MySQL 主从、Redis 集群等)

StatefulSet 的三大组成部分

  1. Headless Service:用于定义 Pod 的网络标识,生成可解析的 DNS 记录
  2. volumeClaimTemplates:存储卷申请模板,自动创建 PVC,为每个 Pod 提供独立存储
  3. StatefulSet 控制器:核心管理组件,负责 Pod 的创建、更新和维护

Headless Service 详解

Headless Service 是 StatefulSet 的关键组件,它与普通 Service 的最大区别是不分配 ClusterIP。通过解析其 DNS 可以直接返回所有关联 Pod 的 DNS 和 IP 地址(这是 StatefulSet 部署的 Pod 独有的特性)。

为什么需要 Headless Service?

  • StatefulSet 要求 Pod 名称必须有序且固定,重建后名称保持不变
  • Pod IP 是变化的,需要用固定的 Pod 名称作为唯一标识符
  • 提供稳定的网络标识,确保服务发现的可靠性

Headless Service 会为自身分配固定域名:

plaintext

复制代码
<service name>.<namespace name>.svc.cluster.local

而每个 Pod 则会获得如下格式的 DNS 名称:

plaintext

复制代码
<pod name>.<service name>.<namespace name>.svc.cluster.local

二、StatefulSet 资源清单编写指南

StatefulSet 的资源清单包含几个关键部分,我们可以通过kubectl explain命令查看详细定义:

bash

运行

复制代码
# 查看StatefulSet的顶级字段
kubectl explain statefulset

# 查看spec字段详情
kubectl explain statefulset.spec

# 查看Pod模板字段
kubectl explain statefulset.spec.template

StatefulSet 清单的核心字段说明:

  • spec.replicas:指定副本数量
  • spec.selector:标签选择器,必须匹配 Pod 模板中的标签
  • spec.serviceName:关联的 Headless Service 名称(必填)
  • spec.template:Pod 模板定义
  • spec.volumeClaimTemplates:存储卷申请模板

注意:StatefulSet 中有两个 spec 字段,外层 spec 用于定义 StatefulSet 属性,内层 spec(spec.template.spec)用于定义 Pod 容器属性

三、StatefulSet 实战:部署 Web 站点

下面通过一个实例演示如何使用 StatefulSet 部署 Web 服务:

1. 编写资源清单文件

创建statefulset.yaml文件,包含 Headless Service 和 StatefulSet 定义:

yaml

复制代码
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
     app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: "None"  # 定义为Headless Service
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx-svc"  # 关联Headless Service
  replicas: 2  # 两个副本
  template:
    metadata:
     labels:
       app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: web

2. 部署并验证

bash

运行

复制代码
# 应用配置
kubectl apply -f statefulset.yaml

# 查看StatefulSet
kubectl get statefulset

# 查看创建的Pod(名称是有序的)
kubectl get pods -l app=nginx

# 查看Headless Service
kubectl get svc -l app=nginx

执行结果会显示两个有序命名的 Pod:web-0web-1,以及一个类型为 ClusterIP 且 CLUSTER-IP 为 None 的 Headless Service。

3. 验证 DNS 解析

创建一个测试 Pod 验证 DNS 解析功能:

yaml

复制代码
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
spec:
  containers:
  - name: busybox
    image: busybox:1.28
    command: ["sh","-c","sleep 3600"]

部署后进入容器测试:

bash

运行

复制代码
# 进入测试Pod
kubectl exec -it pod-second -- /bin/sh

# 解析单个Pod的DNS
nslookup web-0.nginx-svc.default.svc.cluster.local

# 解析Headless Service(会返回所有Pod的IP)
nslookup nginx-svc.default.svc.cluster.local

四、StatefulSet 管理操作

动态扩容

有两种方式可以实现 StatefulSet 的扩容:

  1. 修改配置文件中的replicas值后应用:

bash

运行

复制代码
kubectl apply -f statefulset.yaml
  1. 直接编辑 StatefulSet 配置:

bash

运行

复制代码
kubectl edit sts web
# 修改spec.replicas的值

扩容时,StatefulSet 会按照序号递增的顺序创建新 Pod(如 web-2、web-3 等)。

动态缩容

缩容操作与扩容类似,只需减小replicas的值。需要注意的是,StatefulSet 会按照序号递减的顺序删除 Pod(先删除序号最大的)。

bash

运行

复制代码
# 修改配置文件后应用
kubectl apply -f statefulset.yaml

版本更新

更新 StatefulSet 管理的 Pod 镜像:

bash

运行

复制代码
# 编辑StatefulSet配置
kubectl edit sts web
# 修改spec.template.spec.containers.image的值

更新时,StatefulSet 会按照序号从高到低的顺序逐个更新 Pod,确保服务的连续性。

五、经典面试题:Service 与 Headless Service 的区别

特性 普通 Service Headless Service
ClusterIP 分配唯一的 ClusterIP 无 ClusterIP
DNS 解析 返回 Service 的 ClusterIP 返回所有关联 Pod 的 IP 列表
适用场景 无状态服务、负载均衡 有状态服务、需要明确知道每个 Pod
Pod 标识 随机名称 固定有序名称

通过nslookup命令可以直观看到区别:

  • 普通 Service 解析返回 ClusterIP
  • Headless Service 解析返回所有 Pod 的 IP 地址
相关推荐
新手小白*1 天前
K8S DaemonSet 控制器
k8s
虚伪的空想家3 天前
云镜像,虚拟机镜像怎么转换成容器镜像
服务器·docker·容器·k8s·镜像·云镜像·虚机
ohoy3 天前
ubuntu k8s1.32集群安装
k8s
武子康3 天前
AI研究-134 Java 2025:会衰退吗?LTS 路线、云原生与工程化落地趋势研究
java·开发语言·人工智能·python·ai·云原生·k8s
iru12 天前
kubectl cp详解,k8s集群与本地环境文件拷贝
运维·容器·k8s
竹君子14 天前
研发管理知识库(15)K8s和Istio关系
k8s
像风一样自由202017 天前
告别“在我电脑上能跑”:Docker入门与核心概念解析
docker·容器·k8s
Garfield200521 天前
Kubeflow 运行容器时 ENTRYPOINT 被覆盖导致环境变量未生效问题分析与解决
k8s·dockerfile·kubeflow·entrypoint
南方以南_23 天前
CKA07--Argo CD
运维·kubernetes·k8s