CKAD-exercises高级主题:StatefulSets与DaemonSets实战详解
在Kubernetes(K8s)集群管理中,有状态应用和节点级服务的部署一直是运维人员面临的棘手问题。传统的Deployment资源虽然能高效管理无状态应用,却无法满足数据库集群、分布式存储等有状态服务对稳定网络标识和持久化存储的需求。同时,日志收集、监控代理等节点级服务需要在每个节点上稳定运行,这又超出了普通控制器的能力范围。本文将通过CKAD-exercises项目中的实战案例,详细解析StatefulSet与DaemonSet两种控制器如何解决这些痛点,帮助你掌握企业级K8s应用部署的核心技能。
有状态应用的挑战与解决方案
有状态应用(如MySQL集群、ZooKeeper等)与无状态应用的核心差异体现在三个方面:稳定的网络标识、持久化存储和有序部署/扩展。在g.state.md中提到的PersistentVolume(持久卷)和PersistentVolumeClaim(持久卷声明)为数据持久化提供了基础,但传统Deployment通过随机生成Pod名称和IP地址,无法满足有状态应用的集群发现需求。
StatefulSet核心能力解析
StatefulSet通过以下机制解决有状态应用的部署难题:
-
固定网络标识:每个Pod拥有稳定的DNS名称(格式为
$(statefulset名称)-$(序号).$(服务名称).$(命名空间).svc.cluster.local),如web-0.nginx.default.svc.cluster.local -
有序操作:部署时从0到N-1依次创建Pod,删除时则相反;扩展/缩容遵循严格的序号递增/递减顺序
-
持久存储关联:自动为每个Pod创建与序号绑定的PersistentVolumeClaim,确保数据与实例生命周期解耦
# StatefulSet基本结构示例(源自[g.state.md](https://link.gitcode.com/i/2b887c85a14f766a1359ae9214e737f0)中存储实战案例扩展)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx" # 必须与Headless Service名称匹配
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.19.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates: # 动态生成PVC的模板
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "normal" # 对应[g.state.md](https://link.gitcode.com/i/2b887c85a14f766a1359ae9214e737f0)中定义的storageClass
resources:
requests:
storage: 1Gi
Headless Service与StatefulSet的协同工作
StatefulSet必须配合Headless Service使用,后者负责为Pod提供DNS记录但不分配集群IP。在g.state.md的第256-258行提到,当使用hostPath存储时,跨节点Pod无法共享数据,而StatefulSet结合Headless Service可实现跨节点的稳定通信:
# Headless Service定义(对应StatefulSet网络标识需求)
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None # 关键配置:不分配集群IP
selector:
app: nginx
StatefulSet实战:分布式应用部署
部署ZooKeeper集群
以ZooKeeper分布式协调服务为例,通过StatefulSet实现高可用部署。参照g.state.md中PersistentVolume的创建方法,先准备3个10Gi的PV:
# 创建PV(源自[g.state.md](https://link.gitcode.com/i/2b887c85a14f766a1359ae9214e737f0)第94-128题的PV/PVC创建流程)
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: zk-pv-0
spec:
capacity: { storage: 10Gi }
accessModes: [ "ReadWriteOnce" ]
storageClassName: "normal"
hostPath: { path: "/data/zk/0" }
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: zk-pv-1
spec:
capacity: { storage: 10Gi }
accessModes: [ "ReadWriteOnce" ]
storageClassName: "normal"
hostPath: { path: "/data/zk/1" }
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: zk-pv-2
spec:
capacity: { storage: 10Gi }
accessModes: [ "ReadWriteOnce" ]
storageClassName: "normal"
hostPath: { path: "/data/zk/2" }
EOF
然后部署StatefulSet控制器,注意如何通过环境变量注入序号信息,实现ZooKeeper集群的自动发现:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: zk
spec:
serviceName: zk-hs
replicas: 3
selector:
matchLabels:
app: zk
template:
metadata:
labels:
app: zk
spec:
containers:
- name: zk
image: k8s.gcr.io/zookeeper:3.5.10
ports:
- containerPort: 2181
name: client
- containerPort: 2888
name: peer
- containerPort: 3888
name: leader-election
env:
- name: ZOO_MY_ID
valueFrom:
fieldRef:
fieldPath: metadata.name # 获取Pod名称中的序号(如zk-0中的0)
- name: ZOO_SERVERS
value: "server.0=zk-0.zk-hs.default.svc.cluster.local:2888:3888;server.1=zk-1.zk-hs.default.svc.cluster.local:2888:3888;server.2=zk-2.zk-hs.default.svc.cluster.local:2888:3888"
volumeMounts:
- name: data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "normal"
resources:
requests:
storage: 10Gi
StatefulSet操作实战技巧
- 查看有序部署状态:
kubectl rollout status statefulset/zk # 类似Deployment的rollout状态查看
- 手动维护Pod:
kubectl delete pod zk-1 # StatefulSet会自动重建相同标识的Pod
- 扩缩容操作:
kubectl scale statefulset zk --replicas=5 # 按序号递增创建新Pod
DaemonSet:节点级服务的部署利器
DaemonSet应用场景与特性
DaemonSet确保所有(或指定)节点运行相同的Pod副本,非常适合以下场景:
- 日志收集(如Fluentd、Logstash)
- 监控代理(如Prometheus Node Exporter)
- 网络插件(如Calico、Flannel)
与StatefulSet的核心差异在于:
- 无固定序号,Pod名称随机生成
- 自动在新加入节点部署Pod
- 支持节点亲和性选择特定节点
实战:部署节点监控代理
以下示例基于CKAD-exercises中的Pod调度案例,部署Prometheus Node Exporter到所有节点:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
spec:
selector:
matchLabels:
name: node-exporter
template:
metadata:
labels:
name: node-exporter
spec:
hostNetwork: true # 使用主机网络获取真实节点指标
tolerations: # 容忍控制平面污点,确保在master节点部署
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers:
- name: node-exporter
image: prom/node-exporter:v1.3.1
ports:
- containerPort: 9100
name: metrics
volumeMounts:
- name: proc
mountPath: /host/proc
readOnly: true
- name: sys
mountPath: /host/sys
readOnly: true
volumes:
- name: proc
hostPath:
path: /proc
- name: sys
hostPath:
path: /sys
DaemonSet高级配置
- 限制部署节点:通过节点亲和性选择特定节点
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disk
operator: In
values:
- ssd
- 资源限制与请求:避免DaemonSet占用过多节点资源
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
StatefulSet与DaemonSet的运维与排障
常见问题解决方案
- StatefulSet存储故障: 当出现g.state.md第256-258行描述的跨节点文件不可见问题时,检查:
kubectl get pods -o wide # 确认Pod是否调度到不同节点
kubectl describe pv # 检查PV的accessModes是否支持多节点访问
- DaemonSet未调度到节点:
kubectl describe pod <daemonset-pod-name> # 检查节点污点和Pod容忍度匹配情况
kubectl get nodes --show-labels # 确认节点标签是否满足亲和性要求
升级策略对比
| 控制器类型 | 升级策略 | 适用场景 |
|---|---|---|
| StatefulSet | 有序滚动更新(默认),支持分区更新 | 数据库集群等需按顺序升级的服务 |
| DaemonSet | 滚动更新(默认),支持最大不可用配置 | 节点代理等无状态节点服务 |
StatefulSet分区更新示例:
kubectl patch statefulset zk -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":2}}}}'
总结与最佳实践
StatefulSet和DaemonSet作为Deployment的重要补充,分别解决了有状态应用和节点级服务的部署难题。在实际应用中,建议:
-
存储选择:为StatefulSet使用云厂商提供的持久化存储(如AWS EBS、GCP PD)而非hostPath,避免g.state.md中提到的跨节点数据不可见问题
-
服务发现:始终为StatefulSet创建专用的Headless Service,并使用DNS名称而非IP地址进行服务发现
-
资源规划:为DaemonSet设置合理的资源限制,避免影响节点上其他应用
-
监控告警:通过Prometheus监控StatefulSet的就绪状态和DaemonSet的节点覆盖率
通过CKAD-exercises项目中的这些高级主题练习,你可以深入理解Kubernetes控制器的设计哲学,掌握企业级应用部署的核心技能。无论是数据库集群的稳定运行,还是全节点监控的无缝覆盖,StatefulSet与DaemonSet都将成为你K8s运维工具箱中的利器。
本文所有实战案例均基于CKAD-exercises项目设计,完整练习可参考c.pod_design.md中的Pod管理章节和g.state.md的存储实战部分。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



