首先,需要确认StatefulSet和Deployment的主要区别。Deployment管理的Pod是无状态的,每个Pod都是相同的,可以互相替换,名称也是随机的。而StatefulSet的Pod名称是有序且稳定的,,这样每个Pod都有固定的标识,便于有状态应用处理网络和存储。

特性StatefulSetDeployment
网络标识稳定(固定名称/DNS)随机名称,无固定 DNS
存储独立 PVC,持久化临时存储(通常)
部署顺序按序号顺序创建/删除并行创建/删除
适用场景有状态应用(数据库、中间件)无状态应用(Web 服务等)

StatefulSet如何管理存储呢?每个Pod需要有自己的持久卷(PV),这样即使Pod被重新调度,数据也不会丢失。StatefulSet使用volumeClaimTemplates来为每个Pod生成PersistentVolumeClaim(PVC),这样每个Pod都有自己的存储。例如,当创建mysql-0时,会自动生成一个pvc-mysql-0的声明,绑定到对应的PV。这样保证了数据的持久化和独立性。

StatefulSet 实例:部署 MySQL 集群

1. 创建 Headless Service
# mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  clusterIP: None  # Headless Service 标识
  selector:
    app: mysql
  ports:
    - port: 3306
      name: mysql

说明

  • clusterIP: None 表示这是一个 Headless Service,直接暴露 Pod 的 DNS 记录。

  • Headless Service 通过 ​禁用 ClusterIP​ 和 ​直接暴露 Pod IP,为有状态应用提供了稳定的网络标识和精确的端点访问能力。它是 StatefulSet 实现数据持久化、有序扩缩容等特性的关键基础组件。

2. 创建 StatefulSet
# mysql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-service  # 关联 Headless Service
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:5.7
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "rootpassword"   #设置 MySQL 的 root 密码,生产环境中建议用Secret。
          ports:
            - containerPort: 3306
              name: mysql
          volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql 
  volumeClaimTemplates:
    - metadata:
        name: mysql-data
      spec:
        accessModes: [ "ReadWriteOnce" ]  #该 PV 只能被单节点读写
        resources:
          requests:
            storage: 1Gi

关键配置解析

  • volumeClaimTemplates: 每个 Pod 自动创建名为 mysql-data 的 PVC,存储类为默认的 standard(可按需替换)。

  • 存储挂载: PVC 挂载到 MySQL 的数据目录 /var/lib/mysql,确保数据持久化。


部署与验证

  1. 应用配置

    kubectl apply -f mysql-service.yaml
    kubectl apply -f mysql-statefulset.yaml
  2. 查看资源状态

    kubectl get statefulset/mysql      # 查看 StatefulSet 状态
    kubectl get pods -l app=mysql      # 观察 Pod 按顺序创建
    kubectl get pvc -l app=mysql      # 查看自动创建的 PVC
  3. 验证 DNS 稳定性

    # 进入第一个 Pod 执行 nslookup
    kubectl exec -it mysql-0 /bin/sh
    apt-get update && apt-get install -y dnsutils
    nslookup mysql-service
  4. 数据持久化测试

    • 在 mysql-0 中创建测试数据库。
    • 删除 Pod mysql-0,Kubernetes 会自动重建。
    • 验证数据是否仍然存在。

高级配置

  1. 唯一性配置​(如 MySQL server-id):

    env:
      - name: SERVER_ID
        value: "$(echo ${HOSTNAME} | sed 's/mysql-//')"  # 提取 Pod 序号
      - name: MYSQL_ROOT_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysql-secret
            key: password
  2. 使用 InitContainer 初始化数据

    spec:
      initContainers:
        - name: init-mysql
          image: mysql:5.7
          command: ["bash", "-c", "..." ]  # 自定义初始化脚本
  3. 配置 livenessProbe 和 readinessProbe

    livenessProbe:   #存活探针
      tcpSocket:    #尝试与容器的 3306 端口建立 TCP 连接
        port: 3306
      initialDelaySeconds: 30  # 容器启动后等待 30 秒再开始探测
    readinessProbe:  #就绪探针
      exec: 
        command: ["mysql", "-uroot", "-prootpassword", "-e", "SELECT 1"]

总结

StatefulSet 是 Kubernetes 中用于管理有状态应用的核心控制器,提供稳定的网络标识、持久化存储和有序部署,适用于数据库、分布式中间件等需要固定状态和存储的场景。



 

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐