前言
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 出现问题后可以自愈。