ReplicaSet和ReplicationController都用於在k8s叢集上運行部屬特定數量的pod,但是當你希望pod在叢集中的某個節點上運作(而且每個節點只需要剛好一個pod),使用RS或RC就會出問題。 這些情況包含執行系統等級操作的基礎結構關聯的pod。例如:希望在每個節點上運行收集log和資源監控。另一個典型的例子是k8s自己的kube-proxy程序,它需要運行在所有節點上才能使服務運作。

在k8s以外的環境,這種類型的程序通常在節點開機時透過系統初始化腳本或者systemd daemon來啟動。 在k8s節點上,仍然可以使用systemd執行系統程序,但這樣無法利用所有的k8s特性。

使用DaemonSet在每個節點上運行一個pod

要在所有節點上運行一個pod,只需要建立一個DaemonSet物件,這很像一個ReplicaSet或ReplicationController,除了由DaemonSet建立的pod,已經有一個指定的目標節點並且跳過k8s調度程序,它們不是隨機分布在節點上的。

DaemonSet沒有期望副本數量的概念,因為它的工作是確保一個pod匹配它的選擇器並且每個節點上運行。 如果節點下線,DaemonSet不會在其他節點重新建立pod,但是,當一個新節點加入到叢集時,DaemonSet會立刻部屬一個新的pod到新節點。 同樣如果有人無意中刪除了一個pod,讓某個節點沒有DaemonSet的pod,那麼它也會立刻幫節點重新建立一個新的,跟ReplicaSet一樣,DaemonSet會從配置的pod樣板來建立pod。

使用DaemonSet只在特定的節點上運行pod

DaemonSet將pod部屬到叢集中的所有節點上,除非特別指定這些DaemonSet pod只會在部分節點上運行。這個透過pod樣板中的nodeSelector屬性設定的。

注意:後面會學到將節點設定為不可調度(unschedulable),防止pod被部屬到該節點上。但DaemonSet甚至會將pod部屬到這些節點上,因為無法調度的屬性只會被Scheduler使用,而DaemonSet管理的pod則完全繞過Scheduler。這是當然的,因為DaemonSet通常是運行系統服務pod,即使在不可調度的節點上,系統服務通常也需要運行。

DaemonSet的範例

假設要在叢集中包含SSD硬碟的所有節點上,運行一個ssd-monitor的Daemon程序,你將會建立一個DaemonSet,它在標記具有SSD的節點上運行,同時叢集管理員也已經在所有此類節點上增加了disk=ssd的標籤,因此你將使用節點選擇器來建立DaemonSet,該選擇器只選擇具有該標籤的節點。如下圖:

圖4.9 使用含有節點選擇器的DaemonSet在特定節點上部屬pod

圖4.9 使用含有節點選擇器的DaemonSet在特定節點上部屬pod

1. 建立一個DaemonSet

建立 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

2. 建立一個DaemonSet

[root@cp200 ch4]# kubectl create -f ssd-monitor-daemonset.yaml
daemonset.apps/ssd-monitor created

3. 觀察DaemonSet 跟 pod 運作

[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

4. 給node打上標籤