Kevin
1119 words
6 minutes
kubernetes-statefulSet

1. StatefulSet 简介#

StatefulSet 是 Kubernetes 中用于 有状态应用(Stateful Applications)的控制器,与 Deployment 类似,但提供稳定的 Pod 标识、持久存储和有序部署等特性。常用于 数据库、分布式存储、ZooKeeper、Kafka 等应用。

StatefulSet 主要特点:

  1. 稳定的网络标识(Pod 名称唯一且有序)。
  2. 稳定且持久的存储(每个 Pod 绑定独立的 PV,不随 Pod 删除)。
  3. 有序部署、扩容、缩容、删除(保证 Pod 按序号启动/停止)。
  4. 支持拓扑感知(不同 Pod 可部署到不同节点)。

2. StatefulSet 关键组件#

组件作用
StatefulSet控制有状态应用的部署与管理
Headless Service提供稳定的 Pod 解析,格式 pod-name.service-name.namespace.svc.cluster.local
PersistentVolumeClaim (PVC)绑定持久存储,确保 Pod 重新调度后仍然可用

3. StatefulSet 拓扑结构#

StatefulSet 主要通过 Headless Service 结合 DNS 解析,确保每个 Pod 都有稳定的 FQDN:

+--------------------+
| Service: my-svc   |
| ClusterIP: None   |  <---  通过 DNS 解析 Pod
+--------------------+
          |
 ------------------------
 |        |        |
Pod-0   Pod-1   Pod-2
  • Pod 名称固定,例如 web-0, web-1, web-2
  • 解析方式:web-0.my-svc.default.svc.cluster.local
  • 允许应用使用 直接 Pod-to-Pod 连接,适用于数据库主从复制等场景。

4. StatefulSet 存储管理#

在 StatefulSet 中,每个 Pod 绑定一个 独立的 PersistentVolume (PV),即使 Pod 重新调度,也会保持相同的存储数据。

+----------------------+     +----------------------+
| Pod-0 (web-0)       | --> | PVC-0 -> PV-0       |
+----------------------+     +----------------------+
| Pod-1 (web-1)       | --> | PVC-1 -> PV-1       |
+----------------------+     +----------------------+

📌 重要特性:

  1. PVC 绑定不变:Pod-0 永远绑定 PVC-0,不会与 Pod-1 共享。
  2. 适用于数据库、分布式存储,保证数据持久化,不会因 Pod 重新调度丢失。

5. StatefulSet 部署示例#

(1)创建 Headless Service#

apiVersion: v1
kind: Service
metadata:
  name: my-svc
spec:
  clusterIP: None   # Headless Service
  selector:
    app: my-app
  ports:
    - port: 80

(2)创建 StatefulSet#

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "my-svc"
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: web-storage
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: web-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

📌 关键点:

  • serviceName: "my-svc" 绑定 Headless Service。
  • replicas: 3 创建 web-0, web-1, web-2
  • volumeClaimTemplates 自动为每个 Pod 申请 独立 PVC

6. StatefulSet 关键特性#

关键点说明
Pod 有序命名Pod 名称格式 statefulset-name-index,如 web-0, web-1
Pod 有序启动 & 终止web-0 -> web-1 -> web-2 顺序创建,按相反顺序删除
Pod 拓扑感知可通过 nodeAffinitypodAntiAffinity 指定调度策略
持久存储 PVC 绑定不变web-0 始终绑定 PVC-0,不会随意更换

7. StatefulSet 拓扑调度#

(1)节点亲和性(Node Affinity) 指定 Pod 只能运行在 region=us-east-1 的节点:

    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: topology.kubernetes.io/region
              operator: In
              values:
              - us-east-1

(2)Pod 反亲和性(Pod Anti-Affinity) 确保 Pod 不运行在相同节点,提高可用性:

    affinity:
      podAntiAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - my-app
            topologyKey: "kubernetes.io/hostname"

8. StatefulSet 操作#

(1)查看 StatefulSet#

kubectl get statefulset
kubectl describe statefulset web

(2)查看 Pod & 存储#

kubectl get pods -o wide
kubectl get pvc
kubectl get pv

(3)访问 Pod#

kubectl exec -it web-0 -- /bin/sh

(4)扩容 StatefulSet#

kubectl scale statefulset web --replicas=5

(5)删除 StatefulSet#

kubectl delete statefulset web --cascade=orphan  # 保留 PVC

9. StatefulSet VS Deployment#

特性StatefulSetDeployment
Pod 名称固定✅ 是(web-0, web-1)❌ 否(随机生成)
有序部署 & 终止✅ 是❌ 否
持久存储 PVC 绑定✅ 是(PVC 绑定 Pod)❌ 否(Pod 共享 PVC)
Headless Service✅ 是❌ 否
适用于数据库、分布式存储无状态 Web 应用

练习, MySQL StatefulSet的部署:

  1. Headless Service:
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
  - name: mysql
    port: 3306
(base) PS C:\Users\Kevin Leen\OneDrive - San Jose-Evergreen Community College District\Desktop\k8s> k get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   172.20.0.1   <none>        443/TCP    67m
mysql        ClusterIP   None         <none>        3306/TCP   10s

(base) PS C:\Users\Kevin Leen\OneDrive - San Jose-Evergreen Community College District\Desktop\k8s> k get ep
NAME         ENDPOINTS                       AGE
kubernetes   10.0.2.177:443,10.0.3.135:443   69m
mysql        <none>                          2m20s
  1. PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: gp2 # 明确指定使用 gp2 StorageClass
  resources:
    requests:
      storage: 10Gi

EKS中的storageclass :

kubectl get storageclass
NAME            PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
gp2 (default)   kubernetes.io/aws-ebs   Delete          WaitForFirstConsumer   false                  61m
(base) PS C:\Users\Kevin Leen\OneDrive - San Jose-Evergreen Community College District\Desktop\k8s> k get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   172.20.0.1   <none>        443/TCP    68m
mysql        ClusterIP   None         <none>        3306/TCP   96s
  1. StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: "mysql"
  replicas: 1 
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
	initContainers:
	- name: data-cleanup
	  image: busybox:1.28
	  command: ["sh", "-c", "rm -rf /var/lib/mysql/*"] #提前清理数据避免报错
	  volumeMounts:
		- name: mysql-persistent-storage
		  mountPath: /var/lib/mysql
      containers:
      - name: mysql
        image: mysql:5.7 
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "your_root_password" 
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-persistent-storage
        persistentVolumeClaim:
          claimName: mysql-pvc
(base) PS C:\Users\Kevin Leen\OneDrive - San Jose-Evergreen Community College District\Desktop\k8s> k exec -it mysql-0 -c mysql -- sh
sh-4.2#             
sh-4.2# mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
kubernetes-statefulSet
https://fuwari.vercel.app/posts/kubernetes-statefulset/kubernetes-statefulset/
Author
Kevin
Published at
2025-03-08