Kubernetes DaemonSet - 確保每個節點都運行副本

DaemonSet 確保叢集中的 全部 (或部分) 節點上,都運行一個 Pod 的副本。 當有新節點加入叢集時,DaemonSet 會自動在上面新增一個 Pod;當節點被移除時,該 Pod 也會被回收。

使用場景

DaemonSet 通常用於執行 系統級別 的背景任務:

  1. 日誌收集 (Logging): 在每個節點上運行 log agent,如 fluentdfilebeat,收集該節點上所有容器的 log。
  2. 監控 (Monitoring): 在每個節點上運行監控 agent,如 Prometheus Node Exporter,監控節點的資源使用量 (CPU/RAM/Disk)。
  3. 儲存 (Storage): 運行叢集儲存 daemon,如 glusterdceph

定義 DaemonSet

建立 fluentd-ds.yaml

# fluentd-ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system # 通常 Log Agent 會部署在系統命名空間
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch # 用來選擇要管理的 Pod,必須與 template.metadata.labels 匹配
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1 # 更新過程中,最多允許幾個 Pod 無法服務 (即一次更新幾個節點)
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch # Pod 的標籤
    spec:
      tolerations: # 容忍度設定,讓 Pod 可以排程到 Master/Control Plane 節點
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule
        - key: node-role.kubernetes.io/master
          operator: Exists
          effect: NoSchedule
      containers:
        - name: fluentd-elasticsearch
          image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
          resources: # 設定資源限制,避免佔用過多節點資源
            limits:
              memory: 200Mi
            requests:
              cpu: 100m
              memory: 200Mi

注意:DaemonSet 不需要指定 replicas,因為它的副本數取決於符合條件的節點數量。

指定節點運行

並非所有 DaemonSet 都要跑在所有節點上。你可以透過 nodeSelectoraffinity 來限制。

使用 NodeSelector

假設你只想在標有 type=gpu 的節點上運行監控 GPU 的程式:

spec:
  template:
    spec:
      nodeSelector:
        type: gpu

Tolerations (汙點與容忍)

K8s 的 Master 節點通常會有 Taints (汙點) 防止一般 Pod 調度上去。但 DaemonSet (如網路插件 CNI、Log Agent) 通常需要跑在 Master 上以收集 Master 的監控數據。 這時可以在 DaemonSet 中設定 tolerations 來容忍 Master 的汙點。

spec:
  template:
    spec:
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          operator: Exists
          effect: NoSchedule
        - key: node-role.kubernetes.io/master
          operator: Exists
          effect: NoSchedule

操作 DaemonSet

查看狀態

kubectl get ds -n kube-system

輸出範例:

  • DESIRED: 應運行的 Pod 數量(通常等於節點數)。
  • CURRENT: 目前運行的 Pod 數量。
  • READY: 就緒的 Pod 數量。
  • UP-TO-DATE: 已更新到最新版本的 Pod 數量。

滾動更新與回滾

當修改了 Image Tag 或 ConfigMap,DaemonSet 預設會自動進行 滾動更新 (RollingUpdate)

你可以監控更新進度:

kubectl rollout status ds/fluentd-elasticsearch -n kube-system

若更新失敗,可以回滾:

kubectl rollout undo ds/fluentd-elasticsearch -n kube-system

OnDelete 策略

對於某些核心服務(如 CNI 網路插件),你可能不希望自動重啟所有節點的網路。這時可使用 OnDelete 策略:

spec:
  updateStrategy:
    type: OnDelete

這種模式下,更新 YAML 不會 觸發 Pod 重建。你必須 手動刪除 某個節點上的 Pod,Set Controller 才會在該節點建立新版本的 Pod。這讓管理者能完全控制更新時機。

總結

  • Deployment: 部署無狀態應用,關心的是副本總數。
  • StatefulSet: 部署有狀態應用,關心的是唯一標識與順序。
  • DaemonSet: 部署系統級 Agent,關心的是每個節點都要有一份。