Deployment 部署的副本 Pod 會分布在各個 Node 上,每個 Node 都可能運行好幾個副本。DaemonSet 的不同之處在於:每個 Node 上最多只能運行一個副本。
1.DaemonSet 的典型應用場景
-
在集群的每個節點上運行存儲 Daemon,比如 分布式存儲 glusteFS 或 ceph。
-
在每個節點上運行日志收集 Daemon,比如 flunentd 或 logstash。
-
在每個節點上運行監控 Daemon,比如 Prometheus Node Exporter 或 collectd
其實 Kubernetes 自己就在用 DaemonSet 運行系統組件。執行如下命令:
kubectl get daemonset --namespace=kube-system

daemonSet kube-flannel-ds 和 kube-proxy 分別負責在每個節點上運行 flannel 和 kube-proxy 組件。

因為 flannel 和 kube-proxy 屬於系統組件,需要在命令行中通過 --namespace=kube-system 指定 namespace kube-system。如果不指定則只返回默認 namespace default 中的資源。
下面詳細分析兩個 k8s 自己的 DaemonSet:kube-flannel-ds 和 kube-proxy 。
2.kube-flannel-ds
下面我們通過分析 kube-flannel-ds 來學習 DaemonSet。
還記得之前是如何部署 flannel 網絡的嗎?我們執行了如下兩個命令:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
flannel 的 DaemonSet 就定義在 kube-flannel.yml 中:

① DaemonSet 配置文件的語法和結構與 Deployment 幾乎完全一樣,只是將 kind 設為 DaemonSet。
② hostNetwork 指定 Pod 直接使用的是 Node 的網絡,相當於 docker run --network=host。考慮到 flannel 需要為集群提供網絡連接,這個要求是合理的。
③ containers 定義了運行 flannel 服務的兩個容器。
我們再來分析另一個 DaemonSet kube-proxy。
3.kube-proxy
由於無法拿到 kube-proxy 的 YAML 文件,只能運行如下命令查看其配置:
kubectl edit daemonset kube-proxy --namespace=kube-system


同樣為了便於理解,這里只保留了最重要的信息。
① kind: DaemonSet 指定這是一個 DaemonSet 類型的資源。
② containers 定義了 kube-proxy 的容器。
③ status 是當前 DaemonSet 的運行時狀態,這個部分是 kubectl edit特有的。
其實 Kubernetes 集群中每個當前運行的資源都可以通過 kubectl edit 查看其配置和運行狀態,比如
kubectl edit deployment nginx-deployment
4.DaemonSet使用
下面以 Prometheus Node Exporter 為例演示如何運行自己的 DaemonSet。
Prometheus 是流行的系統監控方案,Node Exporter 是 Prometheus 的 agent,以 Daemon 的形式運行在每個被監控節點上。
如果是直接在 Docker 中運行 Node Exporter 容器,命令為:
docker run -d \ -v "/proc:/host/proc" \ -v "/sys:/host/sys" \ -v "/:/rootfs" \ --net=host \ prom/node-exporter \ --path.procfs /host/proc \ --path.sysfs /host/sys \ --collector.filesystem.ignored-mount-points "^/(sys|proc|dev|host|etc)($|/)"
將其轉換為 DaemonSet 的 YAML 配置文件 node_exporter.yml:
apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: node-exporter-daemonset spec: template: metadata: labels: app: prometheus spec: hostNetwork: true containers: - name: node-exporter image: prom/node-exporter imagePullPolicy: IfNotPresent command: - /bin/node_exporter - --path.procfs - /host/proc - --path.sysfs - /host/sys - --collector.filesystem.ignored-mount-points - ^/(sys|proc|dev|host|etc)($|/) volumeMounts: - name: proc mountPath: /host/proc - name: sys mountPath: /host/sys - name: root mountPath: /rootfs volumes: - name: proc hostPath: path: /proc - name: sys hostPath: path: /sys - name: root hostPath: path: /

① 直接使用 Host 的網絡。
② 設置容器啟動命令。
③ 通過 Volume 將 Host 路徑 /proc、/sys 和 / 映射到容器中。
執行 kubectl apply -f node_exporter.yml:

DaemonSet node-exporter-daemonset 部署成功,k8s-node1 和 k8s-node2 上分別運行了一個 node exporter Pod。
