1119 words
6 minutes
kubernetes-statefulSet
1. StatefulSet 简介
StatefulSet 是 Kubernetes 中用于 有状态应用(Stateful Applications)的控制器,与 Deployment 类似,但提供稳定的 Pod 标识、持久存储和有序部署等特性。常用于 数据库、分布式存储、ZooKeeper、Kafka 等应用。
StatefulSet 主要特点:
- 稳定的网络标识(Pod 名称唯一且有序)。
- 稳定且持久的存储(每个 Pod 绑定独立的 PV,不随 Pod 删除)。
- 有序部署、扩容、缩容、删除(保证 Pod 按序号启动/停止)。
- 支持拓扑感知(不同 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 |
+----------------------+ +----------------------+
📌 重要特性:
- PVC 绑定不变:Pod-0 永远绑定
PVC-0
,不会与 Pod-1 共享。 - 适用于数据库、分布式存储,保证数据持久化,不会因 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 拓扑感知 | 可通过 nodeAffinity 或 podAntiAffinity 指定调度策略 |
持久存储 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
特性 | StatefulSet | Deployment |
---|---|---|
Pod 名称固定 | ✅ 是(web-0, web-1) | ❌ 否(随机生成) |
有序部署 & 终止 | ✅ 是 | ❌ 否 |
持久存储 PVC 绑定 | ✅ 是(PVC 绑定 Pod) | ❌ 否(Pod 共享 PVC) |
Headless Service | ✅ 是 | ❌ 否 |
适用于 | 数据库、分布式存储 | 无状态 Web 应用 |
练习, MySQL StatefulSet的部署:
- 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
- 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
- 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/