DaemonSet

DaemonSet 定義了提供節點本地功能的 Pod。這些 Pod 可能是叢集執行的基礎,例如網路輔助工具,或作為附加元件的一部分。

_DaemonSet_ 確保所有(或部分)節點執行 Pod 的副本。當節點新增到叢集時,Pod 會新增到這些節點上。當節點從叢集中移除時,這些 Pod 會被垃圾回收。刪除 DaemonSet 會清理其建立的 Pod。

DaemonSet 的一些典型用途是:

  • 在每個節點上執行叢集儲存守護程序
  • 在每個節點上執行日誌收集守護程序
  • 在每個節點上執行節點監控守護程序

在簡單情況下,每種型別的守護程序會使用一個 DaemonSet,覆蓋所有節點。更復雜的設定可能會為單一型別的守護程序使用多個 DaemonSet,但針對不同的硬體型別使用不同的標誌和/或不同的記憶體和 CPU 請求。

編寫 DaemonSet 規範

建立 DaemonSet

你可以在 YAML 檔案中描述一個 DaemonSet。例如,下面的 daemonset.yaml 檔案描述了一個執行 fluentd-elasticsearch Docker 映象的 DaemonSet。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # these tolerations are to have the daemonset runnable on control plane nodes
      # remove them if your control plane nodes should not run pods
      - 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:v5.0.1
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
      # it may be desirable to set a high priority class to ensure that a DaemonSet Pod
      # preempts running Pods
      # priorityClassName: important
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log

根據 YAML 檔案建立 DaemonSet

kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml

必填欄位

與所有其他 Kubernetes 配置一樣,DaemonSet 需要 apiVersionkindmetadata 欄位。有關配置檔案的通用資訊,請參閱執行無狀態應用使用 kubectl 進行物件管理

DaemonSet 物件的名稱必須是有效的DNS 子域名

DaemonSet 還需要一個 .spec 部分。

Pod 模板

.spec.template.spec 中必填欄位之一。

.spec.template 是一個Pod 模板。它的 schema 與 Pod 完全相同,只是它是巢狀的,並且沒有 apiVersionkind

除了 Pod 的必填欄位外,DaemonSet 中的 Pod 模板必須指定適當的標籤(請參閱Pod 選擇器)。

DaemonSet 中的 Pod 模板必須將 RestartPolicy 設定為 Always,或者未指定(預設為 Always)。

Pod 選擇器

.spec.selector 欄位是一個 Pod 選擇器。它的工作方式與 Job.spec.selector 相同。

你必須指定一個與 .spec.template 的標籤匹配的 Pod 選擇器。此外,一旦建立了 DaemonSet,其 .spec.selector 就不能被修改。修改 Pod 選擇器可能會導致 Pod 被意外地孤立,這被發現對使用者來說是令人困惑的。

.spec.selector 是一個包含兩個欄位的物件:

  • matchLabels - 工作方式與 ReplicationController.spec.selector 相同。
  • matchExpressions - 允許透過指定鍵、值列表以及關聯鍵和值的運算子來構建更復雜的選擇器。

當兩者都指定時,結果是進行 AND 運算。

.spec.selector 必須與 .spec.template.metadata.labels 匹配。這兩個不匹配的配置將被 API 拒絕。

在選定節點上執行 Pod

如果你指定 .spec.template.spec.nodeSelector,則 DaemonSet 控制器將在匹配該節點選擇器的節點上建立 Pod。同樣,如果你指定 .spec.template.spec.affinity,則 DaemonSet 控制器將在匹配該節點親和性的節點上建立 Pod。如果你兩者都不指定,則 DaemonSet 控制器將在所有節點上建立 Pod。

Daemon Pod 的排程方式

DaemonSet 可用於確保所有符合條件的節點都執行 Pod 的副本。DaemonSet 控制器為每個符合條件的節點建立一個 Pod,並新增 Pod 的 spec.affinity.nodeAffinity 欄位以匹配目標主機。Pod 建立後,預設排程器通常會接管,然後透過設定 .spec.nodeName 欄位將 Pod 繫結到目標主機。如果新 Pod 無法適應節點,預設排程器可能會根據新 Pod 的優先順序搶佔(驅逐)一些現有 Pod。

使用者可以透過設定 DaemonSet 的 .spec.template.spec.schedulerName 欄位,為 DaemonSet 的 Pods 指定不同的排程器。

DaemonSet 控制器在評估符合條件的節點時會考慮 .spec.template.spec.affinity.nodeAffinity 欄位中指定的原始節點親和性(如果已指定),但在建立的 Pod 上,它會被替換為與符合條件的節點名稱匹配的節點親和性。

nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchFields:
      - key: metadata.name
        operator: In
        values:
        - target-host-name

汙點和容忍度

DaemonSet 控制器會自動為 DaemonSet Pods 新增一組容忍度

DaemonSet Pod 的容忍度
容忍度鍵效果詳情
node.kubernetes.io/not-readyNoExecuteDaemonSet Pod 可以排程到不健康或未準備好接受 Pod 的節點上。執行在此類節點上的任何 DaemonSet Pod 都不會被驅逐。
node.kubernetes.io/unreachableNoExecuteDaemonSet Pod 可以排程到節點控制器無法訪問的節點上。執行在此類節點上的任何 DaemonSet Pod 都不會被驅逐。
node.kubernetes.io/disk-pressureNoScheduleDaemonSet Pod 可以排程到存在磁碟壓力問題的節點上。
node.kubernetes.io/memory-pressureNoScheduleDaemonSet Pod 可以排程到存在記憶體壓力問題的節點上。
node.kubernetes.io/pid-pressureNoScheduleDaemonSet Pod 可以排程到存在程序壓力問題的節點上。
node.kubernetes.io/unschedulableNoScheduleDaemonSet Pod 可以排程到不可排程的節點上。
node.kubernetes.io/network-unavailableNoSchedule僅為請求主機網路的 DaemonSet Pod 新增,即具有 spec.hostNetwork: true 的 Pod。此類 DaemonSet Pod 可以排程到網路不可用的節點上。

你也可以透過在 DaemonSet 的 Pod 模板中定義這些容忍度,為 DaemonSet 的 Pods 新增自己的容忍度。

由於 DaemonSet 控制器會自動設定 node.kubernetes.io/unschedulable:NoSchedule 容忍度,Kubernetes 可以在標記為_不可排程_的節點上執行 DaemonSet Pod。

如果你使用 DaemonSet 來提供重要的節點級功能,例如叢集網路,那麼 Kubernetes 在節點準備好之前將 DaemonSet Pod 放置到節點上是很有幫助的。例如,如果沒有這個特殊的容忍度,你可能會陷入死鎖情況:節點未標記為就緒,因為網路外掛未在該節點上執行;同時網路外掛未在該節點上執行,因為節點尚未就緒。

與守護程序 Pod 通訊

與 DaemonSet 中的 Pod 通訊的一些可能模式是:

  • 推送:DaemonSet 中的 Pod 被配置為向其他服務(例如統計資料庫)傳送更新。它們沒有客戶端。
  • 節點 IP 和已知埠:DaemonSet 中的 Pod 可以使用 hostPort,這樣可以透過節點 IP 訪問 Pod。客戶端以某種方式知道節點 IP 列表,並根據約定知道埠。
  • DNS:使用相同的 Pod 選擇器建立一個無頭服務,然後使用 endpoints 資源發現 DaemonSet 或從 DNS 中檢索多個 A 記錄。
  • Service:使用相同的 Pod 選擇器建立一個服務,並使用該服務來訪問隨機節點上的守護程序。使用服務內部流量策略將其限制到同一節點上的 Pod。

更新 DaemonSet

如果節點標籤發生更改,DaemonSet 將立即向新匹配的節點新增 Pod,並從新不匹配的節點刪除 Pod。

你可以修改 DaemonSet 建立的 Pod。但是,Pod 不允許更新所有欄位。此外,DaemonSet 控制器下次建立節點(即使名稱相同)時,將使用原始模板。

你可以刪除一個 DaemonSet。如果你使用 kubectl 並指定 --cascade=orphan,則 Pod 將保留在節點上。如果你隨後建立一個具有相同選擇器的新 DaemonSet,則新 DaemonSet 會接管現有 Pod。如果任何 Pod 需要替換,DaemonSet 會根據其 updateStrategy 替換它們。

你可以對 DaemonSet執行滾動更新

DaemonSet 的替代方案

初始化指令碼

直接在節點上啟動守護程序(例如,使用 initupstartdsystemd)當然是可行的。這完全沒有問題。然而,透過 DaemonSet 執行此類程序有幾個優點:

  • 能夠以與應用程式相同的方式監視和管理守護程序的日誌。
  • 守護程序和應用程式使用相同的配置語言和工具(例如 Pod 模板、kubectl)。
  • 在具有資源限制的容器中執行守護程序可以增加守護程序與應用程式容器之間的隔離。然而,這也可以透過在容器中執行守護程序但不將其放入 Pod 中來實現。

裸 Pod

可以直接建立指定在特定節點上執行的 Pod。然而,DaemonSet 會替換因任何原因刪除或終止的 Pod,例如節點故障或破壞性節點維護(如核心升級)的情況。因此,你應該使用 DaemonSet 而不是建立單獨的 Pod。

靜態 Pod

可以透過將檔案寫入 Kubelet 監視的特定目錄來建立 Pod。這些被稱為靜態 Pod。與 DaemonSet 不同,靜態 Pod 不能透過 kubectl 或其他 Kubernetes API 客戶端進行管理。靜態 Pod 不依賴於 apiserver,這使得它們在叢集引導情況下非常有用。此外,靜態 Pod 在將來可能會被棄用。

部署

DaemonSet 與 Deployments 相似,因為它們都建立 Pod,並且這些 Pod 中的程序預期不會終止(例如,Web 伺服器、儲存伺服器)。

對於無狀態服務(例如前端),當擴充套件副本數量和滾動更新比精確控制 Pod 執行在哪個主機上更重要時,請使用 Deployment。當 Pod 的副本始終執行在所有或某些主機上很重要時,如果 DaemonSet 提供節點級功能,使其他 Pod 能夠在該特定節點上正確執行,請使用 DaemonSet。

例如,網路外掛通常包含一個作為 DaemonSet 執行的元件。該 DaemonSet 元件確保其執行的節點具有正常工作的叢集網路。

下一步

上次修改於 2025 年 8 月 10 日太平洋標準時間晚上 10:50:在 Daemon Pod 通訊中提及服務內部流量策略 (6c39c2bbbb)