在k8s中,使用deployment、statefulset工作负载资源来分别维护无状态和有状态应用。接下来讲讲如何使用DaemonSet来维护一个守护进程(应用)。
1. DaemonSet简介
DaemonSet确保全部(或者某些)节点上运行一个Pod的副本。当有节点加入集群时,也会为他们新增一个Pod。当有节点从集群移除时,这些Pod也会被回收。删除DaemonSet将会删除它创建的所有Pod。
DaemonSet的一些典型用法:
- 在每个节点上运行集群守护进程,如,ceph,glusterd。
- 在每个节点上运行日志收集守护进程,如,fluentd,logstash。
- 在每个节点上运行监控守护进程,如,Prometheus Node Exporter,collectd,Dynatrace OneAgent,Datadog agent,New Relic agent,Ganglia gmond或者Instana agent。
通过创建DaemonSet可以确保守护进程pod被调度到每个可用节点上运行。
守护进程Pod具有的特点如下:
- 它运行在k8s集群中的每个节点(大多数情况下)上;
- 每个节点上只有一个这样的Pod;
- 当有新节点加入k8s集群时,就会在该新节点上自动创建Pod;
- 当一个节点被删除时,Pod会相应的被回收。
2. DaemonSet与Deployment的区别
- Deployment部署的副本Pod会分布在各个Node上,每个Node都可能运行好几个副本。
- Daemon的不同之处在于:每个Node上最多只能运行一个副本。
3. Daemon Pods是如何被调度的
DaemonSet确保所有符合条件的节点都运行该Pod的一个副本。DaemonSet控制器为每个符合条件的节点创建一个Pod,并添加Pod的 spec.affinity.nodeAffinity 字段以匹配目标主机。Pod被创建之后,默认的调度程序通常通过设置 .spec.nodeName 字段来接管Pod并将Pod绑定到目标主机。如果新的Pod无法放在节点上,则默认的调度程序可能会根据新Pod的优先级抢占(驱逐)某些现存的Pod。
用户通过设置DaemonSet的 .spec.template.spec.schedulerName 字段,可以为DaemonSet的Pod指定不同的调度程序。
当评估符合条件的节点时,原本在 .spec.template.spec.affinity.nodeAffinity 字段上指定的节点亲和性将由DaemonSet控制器进行考量,但在创建Pod上会被替换为与符合条件的节点名称匹配的节点亲和性。
ScheduleDaemonSetPods允许你使用默认调度器而不是DaemonSet控制器来调度这些DaemonSet,方法是 将NodeAffinity条件而不是 .spec.nodeName条件添加到这些DaemonSet Pod。默认调度器接下来将Pod绑定到目标主机。如果DaemonSet Pod的节点亲和性配置已存在,则被替换(原始的节点亲和性配置在选择目标主机之前被考虑)。DaemonSet控制器仅在创建或修改DaemonSet Pod时执行这些操作,并且不会更改DaemonSet的 spec.template。
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-name
4. 编写DaemonSet Spec
创建DaemonSet
可以在yaml文件里中描述DaemonSet。例如,下面的daemonset.yaml文件描述了一个运行fluentd-elasticsearch Docker镜像的DaemonSet:
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:
# 这些容忍度设置是为了让该守护进程集在控制平面节点上运行
# 如果你不希望自己的控制平面节点运行 Pod,可以删除它们
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
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
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
基于yam文件创建DaemonSet:
kubectl apply -f daemonset.yaml
5. 污点和容忍度
DaemonSet控制器会自动将一组容忍度添加到 DaemonSet Pod:
容忍度键名 | 效果 | 描述 |
node.kubernetes.io/not-ready | NoExecute | DaemonSet Pod 可以被调度到不健康或还不准备接受 Pod 的节点上。在这些节点上运行的所有 DaemonSet Pod 将不会被驱逐。 |
node.kubernetes.io/unreachable | NoExecute | DaemonSet Pod 可以被调度到从节点控制器不可达的节点上。在这些节点上运行的所有 DaemonSet Pod 将不会被驱逐。 |
node.kubernetes.io/disk-pressure | NoSchedule | DaemonSet Pod 可以被调度到具有磁盘压力问题的节点上。 |
node.kubernetes.io/memory-pressure | NoSchedule | DaemonSet Pod 可以被调度到具有内存压力问题的节点上。 |
node.kubernetes.io/pid-pressure | NoSchedule | DaemonSet Pod 可以被调度到具有进程压力问题的节点上。 |
node.kubernetes.io/unschedulable | NoSchedule | DaemonSet Pod 可以被调度到不可调度的节点上。 |
node.kubernetes.io/network-unavailable | NoSchedule | 仅针对请求主机联网的 DaemonSet Pod 添加此容忍度,即 Pod 具有 spec.hostNetwork: true。这些 DaemonSet Pod 可以被调度到网络不可用的节点上。 |
也可以在 DaemonSet 的 Pod 模板中定义自己的容忍度并将其添加到 DaemonSet Pod。
因为 DaemonSet 控制器自动设置 node.kubernetes.io/unschedulable:NoSchedule 容忍度, 所以 Kubernetes 可以在标记为不可调度的节点上运行 DaemonSet Pod。
如果你使用 DaemonSet 提供重要的节点级别功能, 例如集群联网, Kubernetes 在节点就绪之前将 DaemonSet Pod 放到节点上会很有帮助。 例如,如果没有这种特殊的容忍度,因为网络插件未在节点上运行,所以你可能会在未标记为就绪的节点上陷入死锁状态, 同时因为该节点还未就绪,所以网络插件不会在该节点上运行。
6. 与Daemon Pod通信
与 DaemonSet 中的 Pod 进行通信的几种可能模式如下:
- 推送(Push):配置 DaemonSet 中的 Pod,将更新发送到另一个服务,例如统计数据库。 这些服务没有客户端。
- NodeIP 和已知端口:DaemonSet 中的 Pod 可以使用 hostPort,从而可以通过节点 IP 访问到 Pod。客户端能通过某种方法获取节点 IP 列表,并且基于此也可以获取到相应的端口。
- DNS:创建具有相同 Pod 选择算符的无头服务, 通过使用 endpoints 资源或从 DNS 中检索到多个 A 记录来发现 DaemonSet。
- Service:创建具有相同 Pod 选择算符的服务,并使用该服务随机访问到某个节点上的守护进程(没有办法访问到特定节点)。
参考链接:
https://www.kubernetes.org.cn/4995.html
https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/daemonset/
https://www.cnblogs.com/zouzou-busy/p/16154572.html