16.3.5 StatefulSet与有状态应用
StatefulSet用于管理有状态应用,提供稳定的网络标识、持久化存储与有序部署/扩缩容,适合数据库、消息队列、分布式存储等需要固定身份与数据一致性的场景。
原理草图#
核心特性#
- 稳定网络标识:Pod名称固定为
<sts-name>-<ordinal>,重建后名称保持一致。 - 稳定存储:通过
volumeClaimTemplates为每个Pod创建独立PVC,绑定稳定PV。 - 有序部署与扩缩容:默认按序号升序创建、降序删除,可通过
podManagementPolicy切换并行。 - 有序滚动更新:
updateStrategy支持RollingUpdate与OnDelete,按序号逐个更新。
关键资源与字段#
serviceName:通常指向Headless Service,为每个Pod提供独立DNS。replicas:副本数,影响Pod数量与PVC数量。selector/template:标签选择与Pod模板。volumeClaimTemplates:为每个Pod自动创建PVC,命名为<claim-name>-<sts-name>-<ordinal>。
安装与部署示例(Nginx有状态演示)#
目标:创建Headless Service + StatefulSet,并验证稳定Pod名、稳定PVC与DNS。
1) 创建Headless Service#
# /opt/k8s/sts/headless-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: web-hl
namespace: default
spec:
clusterIP: None
selector:
app: web-sts
ports:
- name: http
port: 80
targetPort: 80
2) 创建StatefulSet#
# /opt/k8s/sts/web-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: web-hl
replicas: 2
selector:
matchLabels:
app: web-sts
podManagementPolicy: OrderedReady
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
app: web-sts
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Gi
3) 应用资源并验证#
# 应用
kubectl apply -f /opt/k8s/sts/headless-svc.yaml
kubectl apply -f /opt/k8s/sts/web-sts.yaml
# 观察Pod创建顺序与名称
kubectl get pod -l app=web-sts -o wide
# 观察PVC/PV绑定
kubectl get pvc -l app=web-sts
kubectl get pv | grep data-web
# 观察DNS(在集群内执行)
kubectl run -it --rm dns-test --image=busybox:1.36 --restart=Never -- sh
nslookup web-0.web-hl.default.svc.cluster.local
nslookup web-1.web-hl.default.svc.cluster.local
4) 验证持久化(写入文件后重建Pod)#
# 往web-0写入文件
kubectl exec web-0 -- sh -c 'echo "hello-sts" > /usr/share/nginx/html/index.html'
kubectl delete pod web-0
# 等待重建后验证
kubectl exec web-0 -- sh -c 'cat /usr/share/nginx/html/index.html'
# 预期输出:hello-sts
运维关注点与命令解释#
- 存储回收策略:PV回收策略影响删除Pod后的数据保留
bash # 查看StorageClass默认回收策略 kubectl get sc -o wide # 查看PV回收策略字段 kubectl get pv -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.persistentVolumeReclaimPolicy}{"\n"}{end}' - 扩缩容风险:缩容会删除高序号Pod及其PVC
bash # 扩容 kubectl scale sts/web --replicas=3 # 缩容(会删除web-2及其PVC) kubectl scale sts/web --replicas=1 - 更新策略选择:关键业务可选
OnDelete手动控制升级节奏
bash # 修改更新策略为OnDelete kubectl patch sts/web -p '{"spec":{"updateStrategy":{"type":"OnDelete"}}}' # 手动删除Pod触发更新 kubectl delete pod web-0 - 探针与启动顺序:有状态应用常依赖启动顺序与探针配置
bash # 查看Pod是否Ready以及探针事件 kubectl describe pod web-0 | sed -n '/Events/,$p'
常见问题与排错流程#
1) PVC无法绑定#
kubectl describe pvc data-web-0
kubectl get sc
kubectl get pv
排查要点:StorageClass不存在、请求容量大于PV、访问模式不匹配。
2) DNS解析失败#
kubectl get svc web-hl
kubectl get endpoints web-hl
kubectl get pod -l app=web-sts --show-labels
排查要点:Headless Service未生效、Service selector与Pod标签不匹配、CoreDNS异常。
3) 更新卡住或Pod不Ready#
kubectl rollout status sts/web
kubectl describe pod web-0
kubectl logs web-0 --tail=100
排查要点:探针失败、容器启动慢、依赖服务不可达。
练习#
- 将
podManagementPolicy改为Parallel,观察Pod创建顺序差异。 - 将
updateStrategy改为OnDelete,并手动删除web-1观察滚动更新行为。 - 模拟PVC绑定失败:将
volumeClaimTemplates中的storage改为一个极大值(如1000Gi),观察PVC事件并恢复。 - 使用
kubectl exec web-0 -- hostname验证稳定主机名,并在重建后再次验证。