ReplicaSet和ReplicationController都用於在k8s叢集上運行部屬特定數量的pod,但是當你希望pod在叢集中的某個節點上運作(而且每個節點只需要剛好一個pod),使用RS或RC就會出問題。 這些情況包含執行系統等級操作的基礎結構關聯的pod。例如:希望在每個節點上運行收集log和資源監控。另一個典型的例子是k8s自己的kube-proxy程序,它需要運行在所有節點上才能使服務運作。
在k8s以外的環境,這種類型的程序通常在節點開機時透過系統初始化腳本或者systemd daemon來啟動。 在k8s節點上,仍然可以使用systemd執行系統程序,但這樣無法利用所有的k8s特性。
要在所有節點上運行一個pod,只需要建立一個DaemonSet物件,這很像一個ReplicaSet或ReplicationController,除了由DaemonSet建立的pod,已經有一個指定的目標節點並且跳過k8s調度程序,它們不是隨機分布在節點上的。
DaemonSet沒有期望副本數量的概念,因為它的工作是確保一個pod匹配它的選擇器並且每個節點上運行。 如果節點下線,DaemonSet不會在其他節點重新建立pod,但是,當一個新節點加入到叢集時,DaemonSet會立刻部屬一個新的pod到新節點。 同樣如果有人無意中刪除了一個pod,讓某個節點沒有DaemonSet的pod,那麼它也會立刻幫節點重新建立一個新的,跟ReplicaSet一樣,DaemonSet會從配置的pod樣板來建立pod。
DaemonSet將pod部屬到叢集中的所有節點上,除非特別指定這些DaemonSet pod只會在部分節點上運行。這個透過pod樣板中的nodeSelector屬性設定的。
注意:後面會學到將節點設定為不可調度(unschedulable),防止pod被部屬到該節點上。但DaemonSet甚至會將pod部屬到這些節點上,因為無法調度的屬性只會被Scheduler使用,而DaemonSet管理的pod則完全繞過Scheduler。這是當然的,因為DaemonSet通常是運行系統服務pod,即使在不可調度的節點上,系統服務通常也需要運行。
假設要在叢集中包含SSD硬碟的所有節點上,運行一個ssd-monitor的Daemon程序,你將會建立一個DaemonSet,它在標記具有SSD的節點上運行,同時叢集管理員也已經在所有此類節點上增加了disk=ssd的標籤,因此你將使用節點選擇器來建立DaemonSet,該選擇器只選擇具有該標籤的節點。如下圖:
圖4.9 使用含有節點選擇器的DaemonSet在特定節點上部屬pod
建立 ssd-monitor-daemonset.yaml (該pod模擬類似ssd-monitor監控程序,該程序每5秒會列印"SSD OK”標準輸出) 此DaemonSet 使用 luksa/ssd-monitor的image,並且部屬在有disk=ssd標籤的節點上
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ssd-monitor
spec:
selector:
matchLabels:
app: ssd-monitor
template:
metadata:
labels:
app: ssd-monitor
spec:
nodeSelector: # 使用了nodeSelector
disk: ssd # 節點必須匹配 disk=ssd
containers:
- name: main
image: luksa/ssd-monitor
[root@cp200 ch4]# kubectl create -f ssd-monitor-daemonset.yaml
daemonset.apps/ssd-monitor created
[root@cp200 ch4]# kubectl get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
ssd-monitor 0 0 0 0 0 disk=ssd 65s
[root@cp200 ch4]# kubectl get po
No resources found in default namespace.
會發現沒有任何pod啟動,是因為我們有用 nodeSelect 選擇 disk=ssd的節點,目前沒有節點符合,所以沒有可以執行,且Daemonset顯示都是0