DaemonSet
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:v2.5.2
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 需要 apiVersion
、kind
和 metadata
欄位。有關使用組態檔的一般資訊,請參閱執行無狀態應用程式和使用 kubectl 的物件管理。
DaemonSet 物件的名稱必須是有效的DNS 子網域名稱。
DaemonSet 也需要.spec
區段。
Pod 範本
.spec.template
是 .spec
中的必要欄位之一。
.spec.template
是一個pod 範本。它與 Pod 具有完全相同的結構描述,但它是巢狀的,並且沒有 apiVersion
或 kind
。
除了 Pod 的必要欄位之外,DaemonSet 中的 Pod 範本還必須指定適當的標籤(請參閱pod 選取器)。
DaemonSet 中的 Pod 範本必須具有 RestartPolicy
,其值等於 Always
,或未指定,預設值為 Always
。
Pod 選取器
.spec.selector
欄位是一個 pod 選取器。它的運作方式與 Job 的 .spec.selector
相同。
您必須指定一個 pod 選取器,使其符合 .spec.template
的標籤。此外,一旦建立 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 Pods 如何排程
DaemonSet 可用於確保所有符合條件的節點都執行 Pod 的副本。DaemonSet 控制器會為每個符合條件的節點建立一個 Pod,並新增 Pod 的 spec.affinity.nodeAffinity
欄位以符合目標主機。建立 Pod 後,預設排程器通常會接管,然後透過設定 .spec.nodeName
欄位將 Pod 繫結至目標主機。如果新的 Pod 無法容納在節點上,預設排程器可能會根據新 Pod 的優先順序,搶佔(驅逐)一些現有的 Pod。
注意
如果 DaemonSet pod 必須在每個節點上執行,通常建議將 DaemonSet 的.spec.template.spec.priorityClassName
設定為具有較高優先順序的 PriorityClass,以確保發生驅逐。使用者可以透過設定 DaemonSet 的 .spec.template.spec.schedulerName
欄位,為 DaemonSet 的 Pod 指定不同的排程器。
DaemonSet 控制器在評估符合條件的節點時,會將 .spec.template.spec.affinity.nodeAffinity
欄位(如果已指定)中指定的原始節點親和性納入考量,但在建立的 Pod 上,會將其替換為符合符合條件節點名稱的節點親和性。
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-name
污點和容忍度
DaemonSet 控制器會自動將一組容忍度新增至 DaemonSet Pod
容忍度鍵 | 效果 | 詳細資訊 |
---|---|---|
node.kubernetes.io/not-ready | NoExecute | DaemonSet Pod 可以排程到不健康或尚未準備好接受 Pod 的節點上。在這些節點上執行的任何 DaemonSet Pod 都不會被驅逐。 |
node.kubernetes.io/unreachable | NoExecute | DaemonSet Pod 可以排程到節點控制器無法連線的節點上。在這些節點上執行的任何 DaemonSet Pod 都不會被驅逐。 |
node.kubernetes.io/disk-pressure | NoSchedule | DaemonSet Pod 可以排程到具有磁碟壓力問題的節點上。 |
node.kubernetes.io/memory-pressure | NoSchedule | DaemonSet Pod 可以排程到具有記憶體壓力問題的節點上。 |
node.kubernetes.io/pid-pressure | NoSchedule | DaemonSet Pod 可以排程到具有程序壓力問題的節點上。 |
node.kubernetes.io/unschedulable | NoSchedule | DaemonSet Pod 可以排程到無法排程的節點上。 |
node.kubernetes.io/network-unavailable | NoSchedule | 僅針對要求主機網路的 DaemonSet Pod 新增,亦即具有 spec.hostNetwork: true 的 Pod。這類 DaemonSet Pod 可以排程到網路無法使用的節點上。 |
您也可以將自己的容忍度新增至 DaemonSet 的 Pod,方法是在 DaemonSet 的 Pod 範本中定義這些容忍度。
由於 DaemonSet 控制器會自動設定 node.kubernetes.io/unschedulable:NoSchedule
容忍度,因此 Kubernetes 可以在標記為無法排程的節點上執行 DaemonSet Pod。
如果您使用 DaemonSet 來提供重要的節點層級功能,例如叢集網路,Kubernetes 在節點準備就緒之前將 DaemonSet Pod 放置在節點上會很有幫助。例如,如果沒有該特殊容忍度,您可能會陷入僵局,節點未標記為就緒,因為網路外掛程式未在該處執行,同時網路外掛程式未在該節點上執行,因為節點尚未就緒。
與 Daemon Pod 通訊
與 DaemonSet 中的 Pod 通訊的一些可能模式如下
- 推送:DaemonSet 中的 Pod 設定為將更新傳送至另一個服務,例如統計資料庫。它們沒有用戶端。
- NodeIP 和已知連接埠:DaemonSet 中的 Pod 可以使用
hostPort
,以便可以透過節點 IP 連線到 Pod。用戶端以某種方式知道節點 IP 列表,並依慣例知道連接埠。 - DNS:使用相同的 pod 選取器建立無頭服務,然後使用
endpoints
資源探索 DaemonSet,或從 DNS 擷取多個 A 記錄。 - 服務:使用相同的 Pod 選取器建立服務,並使用該服務連線到隨機節點上的 daemon。(無法連線到特定節點。)
更新 DaemonSet
如果節點標籤變更,DaemonSet 會立即將 Pod 新增至新符合的節點,並從新不符合的節點中刪除 Pod。
您可以修改 DaemonSet 建立的 Pod。但是,Pod 不允許更新所有欄位。此外,下次建立節點(即使名稱相同)時,DaemonSet 控制器仍會使用原始範本。
您可以刪除 DaemonSet。如果您在使用 kubectl
時指定 --cascade=orphan
,則 Pod 會留在節點上。如果您隨後使用相同的選取器建立新的 DaemonSet,則新的 DaemonSet 會採用現有的 Pod。如果需要替換任何 Pod,DaemonSet 會根據其 updateStrategy
替換它們。
您可以對 DaemonSet 執行rolling update。
DaemonSet 的替代方案
Init 腳本
當然可以透過直接在節點上啟動 daemon 程序來執行它們(例如,使用 init
、upstartd
或 systemd
)。這完全沒問題。但是,透過 DaemonSet 執行這些程序有幾個優點
- 能夠以與應用程式相同的方式監控和管理 daemon 的記錄。
- daemon 和應用程式使用相同的組態語言和工具(例如 Pod 範本、
kubectl
)。 - 在具有資源限制的容器中執行 daemon 可以提高 daemon 與應用程式容器之間的隔離性。但是,這也可以透過在容器中執行 daemon 但不在 Pod 中來完成。
裸 Pod
可以直接建立 Pod,並指定要在其上執行的特定節點。但是,DaemonSet 會替換因任何原因(例如節點故障或破壞性節點維護,如核心升級)而刪除或終止的 Pod。因此,您應該使用 DaemonSet 而不是建立個別的 Pod。
靜態 Pod
可以透過將檔案寫入 Kubelet 監看的特定目錄來建立 Pod。這些稱為靜態 Pod。與 DaemonSet 不同,靜態 Pod 無法使用 kubectl 或其他 Kubernetes API 用戶端進行管理。靜態 Pod 不依賴 apiserver,因此在叢集啟動案例中很有用。此外,靜態 Pod 未來可能會被棄用。
部署
DaemonSet 類似於 Deployment,因為它們都會建立 Pod,而這些 Pod 具有預期不會終止的程序(例如,網頁伺服器、儲存伺服器)。
對於無狀態服務(如前端),擴增和縮減副本數量以及推出更新比精確控制 Pod 在哪個主機上執行更重要,請使用 Deployment。如果 DaemonSet 提供節點層級功能,讓其他 Pod 可以在該特定節點上正確執行,則當 Pod 的副本始終在所有或特定主機上執行很重要時,請使用 DaemonSet。
例如,網路外掛程式通常包含一個作為 DaemonSet 執行的元件。DaemonSet 元件可確保執行它的節點具有可運作的叢集網路。
下一步
- 瞭解關於 Pod 的資訊。
- 瞭解如何使用 DaemonSet
- 對 DaemonSet 執行 rolling update
- 對 DaemonSet 執行 rollback(例如,如果 rollout 未如預期般運作)。
- 瞭解 Kubernetes 如何將 Pod 指派給節點。
- 瞭解關於 裝置外掛程式和 附加元件的資訊,它們通常以 DaemonSet 形式執行。
DaemonSet
是 Kubernetes REST API 中的頂層資源。請閱讀 DaemonSet 物件定義,以瞭解 daemon set 的 API。