Kubernetes StatefulSet 有状态应用
Kubernetes StatefulSet 有状态应用
什么是 StatefulSet
StatefulSet 是 Kubernetes 中用于管理有状态应用的控制器。与 Deployment 不同,StatefulSet 为每个 Pod 提供稳定的网络标识和持久存储,适用于数据库、消息队列等需要持久状态的应用。
StatefulSet 的特点
- 稳定的网络标识:Pod 名称为
<statefulset-name>-<ordinal-index> - 稳定的持久存储:每个 Pod 有独立的 PVC
- 有序部署和扩展:Pod 按顺序创建和删除
- 有序更新:按顺序更新 Pod
创建 StatefulSet
YAML 文件
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: root-password
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: standard
resources:
requests:
storage: 10Gi
Headless Service
StatefulSet 需要配套的 Headless Service:
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: None
selector:
app: mysql
ports:
- port: 3306
创建 Secret
kubectl create secret generic mysql-secret \
--from-literal=root-password=S3cr3tP@ss
部署
kubectl apply -f headless-service.yaml
kubectl apply -f statefulset.yaml
# 查看状态
kubectl get pods -l app=mysql
kubectl get statefulset mysql
访问 Pod
# 访问特定 Pod
mysql-0.mysql.default.svc.cluster.local
mysql-1.mysql.default.svc.cluster.local
mysql-2.mysql.default.svc.cluster.local
# 测试 DNS 解析
kubectl run test --image=busybox --rm -it -- nslookup mysql
扩展和收缩
# 扩展到 5 个副本
kubectl scale statefulset mysql --replicas=5
# 收缩到 2 个副本
kubectl scale statefulset mysql --replicas=2
# 查看 PVC
kubectl get pvc
更新策略
Rolling Update(默认)
spec:
updateStrategy:
type: RollingUpdate
rollingUpdate:
partition: 0
OnDelete
spec:
updateStrategy:
type: OnDelete
更新镜像
# 更新 StatefulSet
kubectl set image statefulset mysql mysql=mysql:8.0.28
# 分区更新(只更新 ordinal >= partition 的 Pod)
kubectl patch statefulset mysql -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":1}}}}'
常用操作
# 查看 StatefulSet 状态
kubectl describe statefulset mysql
# 暂停和恢复
kubectl rollout pause statefulset mysql
kubectl rollout resume statefulset mysql
# 回滚
kubectl rollout undo statefulset mysql
kubectl rollout history statefulset mysql
# 删除 StatefulSet(保留 PVC)
kubectl delete statefulset mysql --cascade=orphan
实践案例:部署 MySQL 集群
部署主从架构
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql-replica
spec:
serviceName: mysql-replica
replicas: 3
selector:
matchLabels:
app: mysql-replica
template:
metadata:
labels:
app: mysql-replica
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: mysql-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 20Gi
常见问题
Pod 无法启动
# 检查 PVC 状态
kubectl get pvc
# 检查 Pod 事件
kubectl describe pod mysql-0
Headless Service 配置
确保 StatefulSet 的 serviceName 与 Headless Service 的 name 匹配。
最佳实践
- 为 StatefulSet 配置 Headless Service
- 使用 volumeClaimTemplates 管理持久存储
- 合理设置 Pod 反亲和性,分散部署
- 定期备份持久存储数据
- 使用 Init Container 进行初始化
总结
StatefulSet 是部署有状态应用的核心组件,提供稳定的网络标识和持久存储。掌握 StatefulSet 的使用可以更好地管理数据库、消息队列等有状态应用。