跳转至

K8s StatefulSet 与 DaemonSet

一句话概述:StatefulSet 管理有状态应用(如数据库),保证 Pod 有固定标识和持久存储;DaemonSet 确保每个节点上都运行一个 Pod(如日志收集、监控代理)。

核心知识点

概念白话解释
StatefulSet有状态集 = 每个 Pod 有固定名字(pod-0, pod-1)和独立存储
DaemonSet守护集 = 每个节点自动运行一个 Pod 副本
Headless Service无头服务 = StatefulSet 必须配合使用,提供 Pod 的 DNS
PVC持久卷声明 = 向 K8s 申请一块存储空间
PV持久卷 = 实际的存储资源
Ordinal Index序号 = StatefulSet 中 Pod 的编号(0, 1, 2...)
Stable Network ID稳定网络标识 = Pod 重启后名字和 DNS 不变

基本使用

1. StatefulSet(有状态应用)

# 先创建 Headless Service(StatefulSet 必须)
apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
spec:
  clusterIP: None  # Headless = 不分配 ClusterIP
  selector:
    app: mysql
  ports:
    - port: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-headless  # 关联的 Headless Service
  replicas: 3  # 3个副本:mysql-0, mysql-1, mysql-2
  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: password
          volumeMounts:
            - name: data
              mountPath: /var/lib/mysql  # 数据目录

  volumeClaimTemplates:  # 每个 Pod 自动创建独立的 PVC
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]  # 单节点读写
        resources:
          requests:
            storage: 10Gi  # 每个 Pod 10GB 存储
kubectl apply -f mysql-statefulset.yaml  # 创建

# Pod 按顺序创建:mysql-0 → mysql-1 → mysql-2
kubectl get pods -l app=mysql  # 查看 Pod

# 每个 Pod 有固定的 DNS 名:
# mysql-0.mysql-headless.default.svc.cluster.local
# mysql-1.mysql-headless.default.svc.cluster.local

# 每个 Pod 有独立的 PVC:
kubectl get pvc  # data-mysql-0, data-mysql-1, data-mysql-2

2. DaemonSet(节点守护进程)

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: log-collector
spec:
  selector:
    matchLabels:
      app: log-collector
  template:
    metadata:
      labels:
        app: log-collector
    spec:
      containers:
        - name: fluentd
          image: fluentd:latest
          volumeMounts:
            - name: varlog
              mountPath: /var/log  # 挂载节点的日志目录
              readOnly: true
          resources:
            limits:
              cpu: "200m"
              memory: "256Mi"
      volumes:
        - name: varlog
          hostPath:
            path: /var/log  # 主机的 /var/log 目录
      tolerations:  # 容忍污点,让 DaemonSet 能在所有节点运行
        - effect: NoSchedule
          operator: Exists
kubectl apply -f daemonset.yaml
kubectl get daemonset  # 查看 DaemonSet
kubectl get pods -l app=log-collector -o wide  # 每个节点一个 Pod

3. DaemonSet 常见场景

# 监控代理(每个节点运行 Prometheus Node Exporter)
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
spec:
  selector:
    matchLabels:
      app: node-exporter
  template:
    metadata:
      labels:
        app: node-exporter
    spec:
      hostNetwork: true  # 使用主机网络
      containers:
        - name: node-exporter
          image: prom/node-exporter:latest
          ports:
            - containerPort: 9100
              hostPort: 9100  # 直接绑定到节点端口

高级用法

StatefulSet 更新策略

spec:
  updateStrategy:
    type: RollingUpdate  # 滚动更新
    rollingUpdate:
      partition: 1  # 只更新序号 >= 1 的 Pod(金丝雀发布)
      # mysql-0 保持旧版本,mysql-1、mysql-2 更新

DaemonSet 只在特定节点运行

spec:
  template:
    spec:
      nodeSelector:
        disk: ssd  # 只在有 disk=ssd 标签的节点运行

常见报错

报错信息原因解决方法
Pod stuck in Pending没有可用 PV 或存储类检查 StorageClass 和 PV
FailedMountPVC 挂载失败检查 PVC 状态和存储后端
OrderedReady timeoutPod 启动太慢检查 readinessProbe 或增加超时
DaemonSet Pod 未调度节点有污点添加 tolerations

速查表

# === StatefulSet ===
kubectl get statefulsets        # 列出
kubectl describe sts <name>    # 详情
kubectl scale sts <name> --replicas=5  # 扩缩容
kubectl rollout status sts <name>      # 更新状态
kubectl delete sts <name> --cascade=orphan  # 删除 STS 不删 Pod

# === DaemonSet ===
kubectl get daemonsets          # 列出
kubectl describe ds <name>     # 详情
kubectl rollout status ds <name>  # 更新状态

# === StatefulSet vs Deployment ===
# Deployment: Pod 名随机(web-abc123),无状态
# StatefulSet: Pod 名固定(db-0, db-1),有状态
# Deployment: Pod 可以任意调度
# StatefulSet: Pod 按顺序启动/停止
# Deployment: 共享存储或无存储
# StatefulSet: 每个 Pod 独立存储(volumeClaimTemplates)

# === DaemonSet 适用场景 ===
# 日志收集(Fluentd、Filebeat)
# 监控代理(Node Exporter、Datadog Agent)
# 网络插件(Calico、Cilium)
# 存储插件(CSI 驱动)

参考:K8s StatefulSet | K8s DaemonSet | 更新于 2026 年