「常駐服務」模式讓你能把具優先權、以基礎設施為導向的 Pod 配置並執行在目標節點上。它主要由管理員使用,用來執行節點特定的 Pod 以強化 Kubernetes 平台能力。
問題#
常駐程式(daemon)的概念存在於軟體系統的許多層級:
- 作業系統層級:daemon 是長時間執行、能自我復原、以背景行程形式運作的程式。Unix 中它們的名字以「d」結尾,例如
httpd、named、sshd;其他作業系統則用 services-started tasks、ghost jobs 等說法。無論叫什麼,共通特徵都是:以行程執行、通常不與螢幕鍵盤滑鼠互動、在系統開機時啟動。 - 應用層級:JVM 中的 daemon thread 在背景執行,為使用者執行緒提供支援服務。它們優先權低、在背景運作、對應用的生死沒有發言權,負責垃圾回收或終結化這類任務。
Kubernetes 中也有對應的 DaemonSet 概念。考慮到 Kubernetes 是一個橫跨多節點、主要目標是管理應用 Pod 的分散式平台,DaemonSet 就是那些跑在叢集節點上、為叢集其餘部分提供背景能力的 Pod。
解法#
ReplicaSet 及其前身 ReplicationController 是負責「確保特定數量 Pod 正在執行」的控制結構:它們持續監控執行中的 Pod 清單,確保實際數量永遠符合期望數量。就這點而言,DaemonSet 是類似的建構,同樣負責確保一定數量的 Pod 持續執行。
差別在於驅動力不同:ReplicaSet 執行特定數量的 Pod,通常由應用的高可用需求與使用者負載驅動,與節點數無關;DaemonSet 則不由使用者負載決定要跑幾個實例、跑在哪裡,它的主要目的是在每個節點(或特定節點)上維持執行一個 Pod。
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: random-refresher
spec:
selector:
matchLabels:
app: random-refresher
template:
metadata:
labels:
app: random-refresher
spec:
nodeSelector:
feature: hw-rng # 只使用 feature 標籤值為 hw-rng 的節點
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
command:
- sh
- -c
- >-
"while true; do
java -cp / RandomRunner /host_dev/random 100000;
sleep 30; done"
volumeMounts: # DaemonSet 常掛載節點檔案系統的一部分以執行維護動作
- mountPath: /host_dev
name: devices
volumes:
- name: devices
hostPath: # 用 hostPath 直接存取節點目錄
path: /dev基於這樣的行為,DaemonSet 的主要候選對象通常是基礎設施相關的行程:日誌收集器、指標匯出器,甚至執行叢集層級操作的 kube-proxy。
DaemonSet 與 ReplicaSet 的主要差異#
- 預設情況下,DaemonSet 在每個節點放置一個 Pod 實例;可用
nodeSelector欄位控制並限縮到節點子集。 - DaemonSet 建立的 Pod 已經指定了
nodeName。因此 DaemonSet 不需要 Kubernetes 排程器存在就能執行容器——這也讓它能用來執行與管理 Kubernetes 元件本身。 - DaemonSet 建立的 Pod 可以在排程器啟動之前執行,使它們能先於節點上任何其他 Pod 就位。
- 由於不使用排程器,DaemonSet 控制器不尊重節點的
unschedulable欄位。 - DaemonSet 管理的 Pod 只該跑在目標節點上,因此被許多控制器以更高優先權、且不同的方式對待。例如 descheduler 會避免逐出這類 Pod,cluster autoscaler 也會另外處理它們。
如何存取 DaemonSet 的 Pod#
DaemonSet 通常在每個(或部分)節點上建立單一 Pod。要接觸這些 Pod 有幾種方式:
- Service:建立一個與 DaemonSet 使用相同 Pod 選擇器的 Service,透過它以負載平衡的方式連到某個隨機節點上的常駐 Pod。
- DNS:建立一個相同選擇器的 headless Service,從 DNS 取得多筆 A 記錄,內含所有 Pod 的 IP 與埠。
- NodeIP + hostPort:DaemonSet 中的 Pod 可指定
hostPort,藉由節點 IP 位址與該埠來存取。由於hostIp、hostPort與 protocol 的組合必須唯一,Pod 能被排程的位置因此受限。 - Push:由 DaemonSet Pod 內的應用主動把資料推送到 Pod 之外某個眾所周知的位置或服務。這樣就完全不需要消費端來連接這些 Pod。
延伸:Static Pods
另一種類似 DaemonSet 的容器執行方式是 static Pod 機制。kubelet 除了與 Kubernetes API Server 溝通、取得 Pod 資訊清單之外,也能從本地目錄讀取資源定義。
以這種方式定義的 Pod:
- 只由 kubelet 管理,且只在單一節點上執行。
- API 服務不會觀察這些 Pod,沒有控制器,也不會對它們執行健康檢查。
- kubelet 監看這些 Pod,在它們崩潰時重啟;並定期掃描設定的目錄,依 Pod 定義的變動增減 Pod。
Static Pod 可用來啟動容器化版本的 Kubernetes 系統行程或其他容器。但 DaemonSet 與平台其餘部分整合得更好,建議優先於 static Pod 使用。
討論#
本書描述的模式與 Kubernetes 功能,主要面向開發者而非平台管理員。DaemonSet 位於兩者之間、更偏向管理員的工具箱,但我們仍收錄它,因為它對應用開發者同樣適用。
DaemonSet 與 CronJob 都是絕佳範例,展示 Kubernetes 如何把 crontab、常駐腳本這類單機概念,轉化為管理分散式系統的多節點叢集原語。這些是開發者也必須熟悉的新分散式概念。
更多資訊#
- Daemon Service Example
- DaemonSets
- Performing a Rolling Update on a DaemonSet
- DaemonSets and Jobs
- Static Pods