DaemonSet是Kubernetes API对象的一种类型,它可以在集群中的所有节点上复制相同的Pod。
本文将深入介绍DaemonSet是什么,它的工作原理以及何时应该使用它们。我们还将提供一个简单的教程,展示如何在您自己的集群中部署一个DaemonSet。
什么是 Kubernetes DaemonSet?
图片
DaemonSet是 Kubernetes API 对象,允许在每个Node节点上将 Pod 作为守护进程运行。当加入集群的新节点会自动运行属于 DaemonSet 的 Pod,同样,当下线一个节点时,这个节点运行的DaemonSet 的 Pod也会被回收。DaemonSet 通常用于长期运行的后台服务,例如节点监控和日志收集代理等。
默认情况下,DaemonSet会在每个节点始终运行一个P od 实例。当然我们可以选择自定义 DaemonSet 的配置,可以让它只在指定的节点上调度 Pod。
由于 DaemonSet设计目标是可靠地在每个节点上运行一个Pod,因此它们具有默认的"tolerations"(容忍度),这使得它们可以在通常会阻止调度新Pod的情况下继续调度。例如,即使目标节点面临资源约束或不接受新的Pod,DaemonSet的Pod仍然会被调度。
Pod、ReplicaSets、Deployments、StatefulSets 和 DaemonSets 之间有什么区别?
Pod 是 Kubernetes 中的基本单元:它们表示在集群中运行的一个或多个容器的集合。
ReplicaSets 建立在这一基础之上,它提供了一种结构,可保证在给定时间内运行指定数量的 Pod 副本。Deployments实现了对 ReplicaSets 的声明式管理,是大多数无状态应用程序在 Kubernetes 中的部署方式,而 StatefulSets 则简化了需要持久数据存储的有状态工作负载的使用。
DaemonSets 与其他工作负载类型不同,因为它们有独特的调度行为。Pod、ReplicaSets 和 Deployments 会自动调度到可用的Node节点,直到运行了所需数量的副本。除非设置亲和性规则,否则我们无法知道哪个节点上运行了我们的Pod。而 DaemonSets 可确保每个节点都运行 Pod。
DaemonSet 应用场景?
运行节点监控代理
比如我们使用Prometheus 监控node节点资源,一般会部署一个node_exporter,来收集每个节点资源信息,这种就比较适合,DaemonSet 无需任何特殊配置即可实现以上需求。
收集节点日志
同样,收集节点级日志(如 Kubelet 和内核日志、运行的 pod的日志)也可以使用DaemonSet,比如监控系统 Loki,会在每个部署一个promtail进行日志收集,如下图
图片
图片
备份节点数据
备份是 DaemonSet 的另一个应用场景。使用 DaemonSet 可确保所有节点数据都进行备份,而无需在节点发生变化时扩展或重新配置备份服务。如果某些节点不需要备份,我们可以自定义 DaemonSet,以便只覆盖标记节点。
DaemonSet 示例
前面我们介绍了 DaemonSets 背后的原理,下面我们来运行的简单示例。
由于 DaemonSets 会在多个节点上部署Pod,因此我们需要有一个多节点 Kubernetes 集群。下面是我的一个集群,同学们可以自行搭建
图片
如何创建 DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:latest
该模板是一个常规的 Kubernetes Pod 规范,它定义了 DaemonSet 将运行的容器,下面我们执行 apply 进行部署
kubectl apply -f fluentd.yaml
图片
等 DaemonSet 的 Pod 启动,然后查询出 Pod 以及它们部署到的节点
kubectl get pods -l name=fluentd -o wide
图片
可以看到 Kubernetes 已自动将 Fluentd Pod 调度到集群中的三个节点上。
kubectl get daemonsets命令会显示 DaemonSet 对象的状态,比如集群中当前节点数量的所需运行 Pod 数量,以及当前是否已就绪、可用。
图片
如何更新 DaemonSet
DaemonSet 的更新方式与其他 Kubernetes 对象相同。我们可以使用和命令,或者通过编辑 YAML 文件然后重复该命令来进行声明性更新,具体命令如下
kubectl update
kubectl patch
kubectl apply
如何删除 DaemonSet
标准 Kubernetes 删除也适用于 DaemonSet。可以使用以下命令停止并删除 DaemonSet 创建的所有 Pod,然后删除 DaemonSet 对象本身:kubectl delete
图片
或者,我们可以仅删除 DaemonSet 对象,同时保持其 Pod 继续运行。在在发出删除命令时指定:--cascade=orphan即可
图片
可以看到pod还在现有节点上运行。如果我们创建另一个同名的 DaemonSet,那么它将自动关联上面的 Pod。
图片
指定节点运行DaemonSet类型的 Pod
我们可以使用关联性规则配置 DaemonSet,让它在集群的特定节点上运行 Pod。这些约束会使用
spec.template.spec.nodeSelector或者spec.template.spec.affinity进行配置
下面是 Fluentd DaemonSet 清单的修改版本:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
spec:
selector:
matchLabels:
name: fluentd
template:
metadata:
labels:
name: fluentd
spec:
nodeSelector:
log-collection-enabled: "true"
containers:
- name: fluentd-elasticsearch
image: quay.io/fluentd_elasticsearch/fluentd:latest
以上表示只在节点的标签为log-collection-enabled: "true"运行,下面我们选择一个标签进行标记然后在运行
kubectl label node xxx.58 log-collection-enabled=true
然后更新 DaemonSet 清单:
kubectl apply -f fluentd2.yaml
图片
可以看到节点选择器已经生效。DaemonSet 的当前和可用 Pod 计数显示为 1,因为只有一个节点被标记了对应的标签
图片
如何扩展 DaemonSet
在Kubernetes中,DaemonSet的作用是在每个节点上运行一个Pod,以确保集群中的每个节点都有对应的Pod实例。要将DaemonSet缩小到0,即停止在所有节点上运行相关的Pod实例,可以通过将DaemonSet的nodeSelector设置为不匹配任何节点的值来实现。
我们可以使用kubectl patch命令来修改DaemonSet的配置,将nodeSelector设置为一个不匹配任何节点的占位值。比如,以下命令将DaemonSet的nodeSelector设置为dummy-nodeselector: abc:
kubectl patch daemonset fluentd -p '{"spec": {"template": {"spec": {"nodeSelector": {"dummy-nodeselector": "abc"}}}}}'
这将导致DaemonSet不再在任何节点上调度新的Pod实例,从而实现了缩小到0的效果。
DaemonSet 最佳实践
以下是使用DaemonSet的最佳实践,这些实践将帮助您最大化性能和可靠性。
仅当Pod的扩缩容与节点数量关联时使用DaemonSet
DaemonSet的设计目的是在节点上扩展Pod节点。当需要独立于集群的节点数量来部署Pod时,我们应使用常规工作负载对象,如ReplicaSet和Deployment。
确保所有DaemonSet Pod具有正确的重启策略
DaemonSet中的Pod的重启策略必须设置为Always,如果选择指定该值,Pod将随节点一起重新启动。
不要手动管理DaemonSet Pod
作为DaemonSet的一部分创建的Pod不应该被手动编辑或删除。在DaemonSet之外进行更改可能导致Pod被孤立。
使用回滚快速恢复DaemonSet的更改
使用 DaemonSets 作为集群的后台服务的一个优点是,如果出现问题,我们可以轻松回滚到早期版本。启动回滚比手动恢复进行新的部署更快、更可靠。