Kubernetes:守护进程DaemonSet

Kubernetes

在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-readyNoExecuteDaemonSet Pod 可以被调度到不健康或还不准备接受 Pod 的节点上。在这些节点上运行的所有 DaemonSet Pod 将不会被驱逐。
node.kubernetes.io/unreachableNoExecuteDaemonSet Pod 可以被调度到从节点控制器不可达的节点上。在这些节点上运行的所有 DaemonSet Pod 将不会被驱逐。
node.kubernetes.io/disk-pressureNoScheduleDaemonSet Pod 可以被调度到具有磁盘压力问题的节点上。
node.kubernetes.io/memory-pressureNoScheduleDaemonSet Pod 可以被调度到具有内存压力问题的节点上。
node.kubernetes.io/pid-pressureNoScheduleDaemonSet Pod 可以被调度到具有进程压力问题的节点上。
node.kubernetes.io/unschedulableNoScheduleDaemonSet Pod 可以被调度到不可调度的节点上。
node.kubernetes.io/network-unavailableNoSchedule仅针对请求主机联网的 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

Related Posts

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注