什么是Kubernetes DaemonSet,如何使用?
DaemonSet是Kubernetes API對象的一種類型,它可以在集群中的所有節點上復制相同的Pod。
本文將深入介紹DaemonSet是什么,它的工作原理以及何時應該使用它們。我們還將提供一個簡單的教程,展示如何在您自己的集群中部署一個DaemonSet。
什么是 Kubernetes DaemonSet?
圖片
DaemonSet是 Kubernetes API 對象,允許在每個Node節點上將 Pod 作為守護進程運行。當加入集群的新節點會自動運行屬于 DaemonSet 的 Pod,同樣,當下線一個節點時,這個節點運行的DaemonSet 的 Pod也會被回收。DaemonSet 通常用于長期運行的后臺服務,例如節點監控和日志收集代理等。
默認情況下,DaemonSet會在每個節點始終運行一個P od 實例。當然我們可以選擇自定義 DaemonSet 的配置,可以讓它只在指定的節點上調度 Pod。
由于 DaemonSet設計目標是可靠地在每個節點上運行一個Pod,因此它們具有默認的"tolerations"(容忍度),這使得它們可以在通常會阻止調度新Pod的情況下繼續調度。例如,即使目標節點面臨資源約束或不接受新的Pod,DaemonSet的Pod仍然會被調度。
Pod、ReplicaSets、Deployments、StatefulSets 和 DaemonSets 之間有什么區別?
Pod 是 Kubernetes 中的基本單元:它們表示在集群中運行的一個或多個容器的集合。
ReplicaSets 建立在這一基礎之上,它提供了一種結構,可保證在給定時間內運行指定數量的 Pod 副本。Deployments實現了對 ReplicaSets 的聲明式管理,是大多數無狀態應用程序在 Kubernetes 中的部署方式,而 StatefulSets 則簡化了需要持久數據存儲的有狀態工作負載的使用。
DaemonSets 與其他工作負載類型不同,因為它們有獨特的調度行為。Pod、ReplicaSets 和 Deployments 會自動調度到可用的Node節點,直到運行了所需數量的副本。除非設置親和性規則,否則我們無法知道哪個節點上運行了我們的Pod。而 DaemonSets 可確保每個節點都運行 Pod。
DaemonSet 應用場景?
運行節點監控代理
比如我們使用Prometheus 監控node節點資源,一般會部署一個node_exporter,來收集每個節點資源信息,這種就比較適合,DaemonSet 無需任何特殊配置即可實現以上需求。
收集節點日志
同樣,收集節點級日志(如 Kubelet 和內核日志、運行的 pod的日志)也可以使用DaemonSet,比如監控系統 Loki,會在每個部署一個promtail進行日志收集,如下圖
圖片
圖片
備份節點數據
備份是 DaemonSet 的另一個應用場景。使用 DaemonSet 可確保所有節點數據都進行備份,而無需在節點發生變化時擴展或重新配置備份服務。如果某些節點不需要備份,我們可以自定義 DaemonSet,以便只覆蓋標記節點。
DaemonSet 示例
前面我們介紹了 DaemonSets 背后的原理,下面我們來運行的簡單示例。
由于 DaemonSets 會在多個節點上部署Pod,因此我們需要有一個多節點 Kubernetes 集群。下面是我的一個集群,同學們可以自行搭建
圖片
如何創建 DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:latest
該模板是一個常規的 Kubernetes Pod 規范,它定義了 DaemonSet 將運行的容器,下面我們執行 apply 進行部署
kubectl apply -f fluentd.yaml
圖片
等 DaemonSet 的 Pod 啟動,然后查詢出 Pod 以及它們部署到的節點
kubectl get pods -l name=fluentd -o wide
圖片
可以看到 Kubernetes 已自動將 Fluentd Pod 調度到集群中的三個節點上。
kubectl get daemonsets命令會顯示 DaemonSet 對象的狀態,比如集群中當前節點數量的所需運行 Pod 數量,以及當前是否已就緒、可用。
圖片
如何更新 DaemonSet
DaemonSet 的更新方式與其他 Kubernetes 對象相同。我們可以使用和命令,或者通過編輯 YAML 文件然后重復該命令來進行聲明性更新,具體命令如下
kubectl update
kubectl patch
kubectl apply
如何刪除 DaemonSet
標準 Kubernetes 刪除也適用于 DaemonSet。可以使用以下命令停止并刪除 DaemonSet 創建的所有 Pod,然后刪除 DaemonSet 對象本身:kubectl delete
圖片
或者,我們可以僅刪除 DaemonSet 對象,同時保持其 Pod 繼續運行。在在發出刪除命令時指定:--cascade=orphan即可
圖片
可以看到pod還在現有節點上運行。如果我們創建另一個同名的 DaemonSet,那么它將自動關聯上面的 Pod。
圖片
指定節點運行DaemonSet類型的 Pod
我們可以使用關聯性規則配置 DaemonSet,讓它在集群的特定節點上運行 Pod。這些約束會使用
spec.template.spec.nodeSelector或者spec.template.spec.affinity進行配置
下面是 Fluentd DaemonSet 清單的修改版本:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
nodeSelector:
log-collection-enabled: "true"
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:latest
以上表示只在節點的標簽為log-collection-enabled: "true"運行,下面我們選擇一個標簽進行標記然后在運行
kubectl label node xxx.58 log-collection-enabled=true
然后更新 DaemonSet 清單:
kubectl apply -f fluentd2.yaml
圖片
可以看到節點選擇器已經生效。DaemonSet 的當前和可用 Pod 計數顯示為 1,因為只有一個節點被標記了對應的標簽
圖片
如何擴展 DaemonSet
在Kubernetes中,DaemonSet的作用是在每個節點上運行一個Pod,以確保集群中的每個節點都有對應的Pod實例。要將DaemonSet縮小到0,即停止在所有節點上運行相關的Pod實例,可以通過將DaemonSet的nodeSelector設置為不匹配任何節點的值來實現。
我們可以使用kubectl patch命令來修改DaemonSet的配置,將nodeSelector設置為一個不匹配任何節點的占位值。比如,以下命令將DaemonSet的nodeSelector設置為dummy-nodeselector: abc:
kubectl patch daemonset fluentd -p '{"spec": {"template": {"spec": {"nodeSelector": {"dummy-nodeselector": "abc"}}}}}'
這將導致DaemonSet不再在任何節點上調度新的Pod實例,從而實現了縮小到0的效果。
DaemonSet 最佳實踐
以下是使用DaemonSet的最佳實踐,這些實踐將幫助您最大化性能和可靠性。
僅當Pod的擴縮容與節點數量關聯時使用DaemonSet
DaemonSet的設計目的是在節點上擴展Pod節點。當需要獨立于集群的節點數量來部署Pod時,我們應使用常規工作負載對象,如ReplicaSet和Deployment。
確保所有DaemonSet Pod具有正確的重啟策略
DaemonSet中的Pod的重啟策略必須設置為Always,如果選擇指定該值,Pod將隨節點一起重新啟動。
不要手動管理DaemonSet Pod
作為DaemonSet的一部分創建的Pod不應該被手動編輯或刪除。在DaemonSet之外進行更改可能導致Pod被孤立。
使用回滾快速恢復DaemonSet的更改
使用 DaemonSets 作為集群的后臺服務的一個優點是,如果出現問題,我們可以輕松回滾到早期版本。啟動回滾比手動恢復進行新的部署更快、更可靠。