CKAD-exercises高级主题:StatefulSets与DaemonSets实战详解

CKAD-exercises高级主题:StatefulSets与DaemonSets实战详解

【免费下载链接】CKAD-exercises A set of exercises to prepare for Certified Kubernetes Application Developer exam by Cloud Native Computing Foundation 【免费下载链接】CKAD-exercises 项目地址: https://gitcode.com/gh_mirrors/ck/CKAD-exercises

在Kubernetes(K8s)集群管理中,有状态应用和节点级服务的部署一直是运维人员面临的棘手问题。传统的Deployment资源虽然能高效管理无状态应用,却无法满足数据库集群、分布式存储等有状态服务对稳定网络标识和持久化存储的需求。同时,日志收集、监控代理等节点级服务需要在每个节点上稳定运行,这又超出了普通控制器的能力范围。本文将通过CKAD-exercises项目中的实战案例,详细解析StatefulSet与DaemonSet两种控制器如何解决这些痛点,帮助你掌握企业级K8s应用部署的核心技能。

有状态应用的挑战与解决方案

有状态应用(如MySQL集群、ZooKeeper等)与无状态应用的核心差异体现在三个方面:稳定的网络标识持久化存储有序部署/扩展。在g.state.md中提到的PersistentVolume(持久卷)和PersistentVolumeClaim(持久卷声明)为数据持久化提供了基础,但传统Deployment通过随机生成Pod名称和IP地址,无法满足有状态应用的集群发现需求。

StatefulSet核心能力解析

StatefulSet通过以下机制解决有状态应用的部署难题:

  1. 固定网络标识:每个Pod拥有稳定的DNS名称(格式为$(statefulset名称)-$(序号).$(服务名称).$(命名空间).svc.cluster.local),如web-0.nginx.default.svc.cluster.local

  2. 有序操作:部署时从0到N-1依次创建Pod,删除时则相反;扩展/缩容遵循严格的序号递增/递减顺序

  3. 持久存储关联:自动为每个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操作实战技巧

  1. 查看有序部署状态
kubectl rollout status statefulset/zk  # 类似Deployment的rollout状态查看
  1. 手动维护Pod
kubectl delete pod zk-1  # StatefulSet会自动重建相同标识的Pod
  1. 扩缩容操作
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高级配置

  1. 限制部署节点:通过节点亲和性选择特定节点
spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: disk
                operator: In
                values:
                - ssd
  1. 资源限制与请求:避免DaemonSet占用过多节点资源
resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 250m
    memory: 256Mi

StatefulSet与DaemonSet的运维与排障

常见问题解决方案

  1. StatefulSet存储故障: 当出现g.state.md第256-258行描述的跨节点文件不可见问题时,检查:
kubectl get pods -o wide  # 确认Pod是否调度到不同节点
kubectl describe pv  # 检查PV的accessModes是否支持多节点访问
  1. 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的重要补充,分别解决了有状态应用和节点级服务的部署难题。在实际应用中,建议:

  1. 存储选择:为StatefulSet使用云厂商提供的持久化存储(如AWS EBS、GCP PD)而非hostPath,避免g.state.md中提到的跨节点数据不可见问题

  2. 服务发现:始终为StatefulSet创建专用的Headless Service,并使用DNS名称而非IP地址进行服务发现

  3. 资源规划:为DaemonSet设置合理的资源限制,避免影响节点上其他应用

  4. 监控告警:通过Prometheus监控StatefulSet的就绪状态和DaemonSet的节点覆盖率

通过CKAD-exercises项目中的这些高级主题练习,你可以深入理解Kubernetes控制器的设计哲学,掌握企业级应用部署的核心技能。无论是数据库集群的稳定运行,还是全节点监控的无缝覆盖,StatefulSet与DaemonSet都将成为你K8s运维工具箱中的利器。

本文所有实战案例均基于CKAD-exercises项目设计,完整练习可参考c.pod_design.md中的Pod管理章节和g.state.md的存储实战部分。

【免费下载链接】CKAD-exercises A set of exercises to prepare for Certified Kubernetes Application Developer exam by Cloud Native Computing Foundation 【免费下载链接】CKAD-exercises 项目地址: https://gitcode.com/gh_mirrors/ck/CKAD-exercises

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值