前言
Deployment 管理的 Pod 允許在一個節點上運行多個副本。
當需要在節點上運行收集日誌或者執行監控任務的容器時,顯然不適合啓動多個 Pod 副本。
這種場景下,我們可以啓用 DaemonSet 控制器來管理 Pod。
更新歷史
- 20200620 - 初稿 - 左程立
- 原文地址 - https://blog.zuolinux.com/2020/06/20/about-controller-daemonset.html
Daemon Pod 的特點
- Pod 運行在集羣中的全部或者部分節點上
- 每個節點上只能有一個這樣的 Pod
- 當集羣中加入了新節點,Pod 會自動在新節點上創建
- 當節點被從集羣中移除後,節點上 Pod 會自動被回收掉
Daemon Pod 適用的場景
- 網絡插件的 Agent
- 存儲插件的 Agent
- 監控任務的 Agent
- 收集日誌的 Agent
DaemonSet
創建一個 DS
cat daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd-elasticsearch
namespace: kube-system
labels:
k8s-app: fluentd-logging
spec:
selector:
matchLabels:
name: fluentd-elasticsearch
template:
metadata:
labels:
name: fluentd-elasticsearch
spec:
tolerations:
# this toleration is to have the daemonset runnable on master nodes
# remove it if your masters can't run pods
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
# kubectl apply -f daemonset.yaml
daemonset.apps/fluentd-elasticsearch created
查看
[root@master01 ~]# kubectl get ds --namespace kube-system
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
fluentd-elasticsearch 6 6 6 6 6 <none> 11m
目前集羣中有 3 個 master,3 個 worker,一共 6 個節點,可以看到 6 個節點上都運行了該 node
工作流程
DaemonSet Controller,從 Etcd 裏獲取所有的 Node 列表,然後遍歷所有的 Node。
然後檢查當前這個 Node 上是不是有一個攜帶了 name=fluentd-elasticsearch 標籤的 Pod 在運行。
而檢查的結果,大概有這麼三種情況:
- Node 上沒有這種 Pod,那麼就意味着要在這個 Node 上創建這個 Pod;
- Node 上有這種 Pod,但是數量大於 1,那就說明要把多餘的 Pod 從這個 Node 上刪除掉;
- 只有一個這種 Pod,說明這個節點是正常的。
重要參數
spec.affinity.nodeAffinity
通過命令
# kubectl edit pod fluentd-elasticsearch-22g5r --namespace=kube-system
可以看到 DaemonSet 自動給 Pod 增加了參數
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- master03
限制了該 Pod 只能運行在 master03 這個 Node 上
tolerations
同樣通過上面的命令,可以看到有參數
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
- effect: NoSchedule
key: node.kubernetes.io/disk-pressure
意味着可以容忍所有標記有如下“污點”的 Node,可以在這些 Node 上運行 master/not-ready/unreachable/disk-pressure
正常情況下,如果 Node 上被標記了這些“污點”,Pod 被禁止調度到這樣的 Node 上運行
但 DaemonSet 給 Pod 加上了 tolerations,使 Pod 可以忽略這些污點,從而成功將 Pod 調度到“污點”節點上
如果節點有故障導致 Pod 啓動失敗,DaemonSet 會一直嘗試,直到 Pod 成功啓動
僅在部分節點運行 Pod
可以在 YAML 中手工指定 .spec.template.spec.affinity,這樣 Pod 會運行在指定的 Node 上
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-name
如果沒有指定該參數,那麼 Pod 會運行在所有 Node 上
DaemonSet 優點
我們也可以自己寫一個守護進程來執行類似的工作,使用 DaemonSet Pod 有哪些優點呢。
- DaemonSet Pod 自帶自身監控功能,省去了我們自己再寫一個針對守護進程的監控程序的工作
- DaemonSet Pod 不管運行什麼任務,都是統一的語言和管理方式
- DaemonSet Pod 自帶了資源限制功能,避免了守護進程長時間運行佔用過多資源對宿主機造成影響
結束語
DaemonSet 傾向於精確控制 Pod 運行在哪些機器上,確保這些機器上都有這個 Pod 在運行。
而 Deployment 更適合於管理離用戶更近的無狀態類 Pod,比如 Web 服務。
它們的共同點是,都不希望自己管理的 Pod 終止,Pod 出現問題後可以自愈。
聯繫我
微信公衆號:zuolinux_com