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