kubernetes | 部署守护进程

2022年3月17日 · 2442 字 · 5 分钟 · Kubernetes

一、DaemonSet 概述

官方文档:daemonset

DaemonSet 确保在所有(或部分)Node 节点上运行 Pod 的副本。随着新的 Node 被添加到群集中的同时,会将 Pod 添加到新 Node 中。随着节点从群集中删除,垃圾收集器也将会删除这些 Pod。DaemonSet 的一些典型场景和用法:

  • 集群存储:在每个 Node 节点上,运行集群存储守护程序,例如 glusterd,ceph。
  • 日志收集:在每个 Node 节点上,运行日志收集守护程序,例如 fluentd 或 logstash。
  • 节点监控:在每个 Node 节点上,运行节点监控守护程序,例如 Prometheus Node Exporter,collectd,Dynatrace OneAgent,Datadog agent,New Relic agent,Ganglia gmond 或者 Instana agent。

二、创建 DaemonSet 应用

1、在每个 node 节点安装数据采集工具,编写 yaml 文件 test.yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: ds-test
  labels:
    app: filebeat
spec:
  # 标签选择器
  selector:
    matchLabels:
      app: filebeat
  # 标签类型
  template:
    metadata:
      labels:
        app: filebeat
    spec:
      # 配置容器
      containers:
      - name: logs
        image: elastic/filebeat:7.10.1
        ports:
        - containerPort: 80
        # 挂载目录
        volumeMounts:
        - name: varlog
          mountPath: /tmp/log
      volumes:
      - name: varlog
        hostPath:
          path: /var/log

2、必填字段
与 Kubernetes 中其它的对象一样,DaemonSet 必须包含 apiVersion,kind 和 metadata 字段。同时,DaemonSet 还需要 spec 字段部分的内容。

3、Pod 模板
.spec.template 是 .spec 的必填字段。.spec.template 用来定义 Pod 模板。DaemonSet 中的 Pod 模板必须设置 RestartPolicy 等于 Always,未指定的默认值即为 Always。

4、Pod 选择器
通过 .spec.selector 字段定义 Pod 选择器。从 Kubernetes 1.8 开始,必须指定一个与 .spec.template 标签相匹配选择器。一旦创建了 DaemonSet,就不能对 .spec.selector 进行修改,改变 Pod 选择器可能会导致 Pod 成为孤儿。 .spec.selector 是一个由两个字段组成的对象:

  • matchLabels 与 ReplicationControlle 的 .spec.selector 字段同样的工作机制。
  • matchExpressions 允许通过指定键,值列表以及与键和值相关的运算符来构建更复杂的选择器。

如果同时指定了两者时,结果取两者的和。如果指定了.spec.selector,则必须匹配 .spec.template.metadata.labels,如果不匹配将会被 API 拒绝。

5、仅在某些节点上运行 Pod
如果指定了 .spec.template.spec.nodeSelector,则 DaemonSet 控制器将在与该节点选择器匹配的 Node 节点上部署 Pod 。同样,如果指定了 .spec.template.spec.affinity,则 DaemonSet 控制器将在与该节点关联相匹配的 Node 节点上创建 Pod 。如果您未指定上述两个字段,则 DaemonSet 控制器将会在所有的 Node 节点上创建 Pod。

三、部署 DaemonSet 应用

#1. 部署 DaemonSet 应用
kubectl apply -f test.yaml 
daemonset.apps/ds-test created

#2. 查看 DaemonSet 应用
kubectl get  pods
NAME                   READY   STATUS    RESTARTS   AGE
ds-test-7krrv          1/1     Running   0          59s
ds-test-jnxzm          1/1     Running   0          59s
web-5bb6fd4c98-54ll2   1/1     Running   0          2d
web-5bb6fd4c98-585rn   1/1     Running   0          2d

四、进入 DaemonSet 查看

> kubectl  exec -it ds-test-7krrv bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@ds-test-7krrv:/# ls /tmp/log/
anaconda	   containers	       maillog		  secure-20211108	vmware-network.5.log	vmware-vmtoolsd-root.log
audit		   cron		       maillog-20211108   spooler		vmware-network.6.log	wtmp
boot.log	   cron-20211108       messages		  spooler-20211108	vmware-network.7.log	yum.log
boot.log-20200806  dmesg	       messages-20211108  tallylog		vmware-network.8.log	yum.log-20211108
boot.log-20200810  dmesg.old	       ntpstats		  tuned			vmware-network.9.log
boot.log-20211108  firewalld	       pods		  vmware-network.1.log	vmware-network.log
boot.log-20211109  grubby	       rhsm		  vmware-network.2.log	vmware-vgauthsvc.log.0
btmp		   grubby_prune_debug  sa		  vmware-network.3.log	vmware-vmsvc-root.log
btmp-20211108	   lastlog	       secure		  vmware-network.4.log	vmware-vmsvc.log
root@ds-test-7krrv:/#

五、调度 Daemon Pods

由 DaemonSet 控制器调度(自 1.12 版本起,默认禁用)
通常,由 Kubernetes 调度器选择 Pod 所运行的机器。但是,由 DaemonSet 控制器创建的 Pod,在创建是就已经为 Pod 选择了机器(在创建 Pod 时指定.spec.nodeName,因此调度器会忽略它)。因此:

  • DaemonSet 控制器将不会考虑 unschedulable 的 Node 节点。
  • 即使尚未启动调度器,DaemonSet 控制器也可以生成 Pod,这可以帮助集群引导程序。

由默认调度器调度(自 1.12 版本起,默认启用)
特性状态: Kubernetes v1.13 beta

DaemonSet 确保所有符合条件的节点都运行 Pod 的副本。通常,由 Kubernetes 调度器选择 Pod 所运行的 Node 节点。但是,DaemonSet Pods 是由 DaemonSet 控制器所创建和调度的。这就产生了以下的问题:

  • 不一致的 Pod 行为:正常的 Pod,在创建是处于 Pending 状态;但 DaemonSet Pod 在创建时,并不是处于 Pending 状态。这使用户感到困惑。
  • Pod 抢占由默认调度器处理:启用抢占后,DaemonSet 控制器将在不考虑 Pod 优先级和抢占的情况下制定调度决策。

ScheduleDaemonSetPods 允许使用默认调度器而不是 DaemonSet 控制器来调度 DaemonSet,方法是将 NodeAffinity 术语添加到 DaemonSet Pods,而不是使用 .spec.nodeName 术语。默认调度器将 Pod 绑定到目标主机。如果 DaemonSet pod 的节点关联已存在,则替换它。DaemonSet 控制器仅在创建或修改 DaemonSet Pods 时执行这些操作,并且不对 DaemonSet 的 spec.template 进行任何更改。

nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchFields:
      - key: metadata.name
        operator: In
        values:
        - target-host-name

此外,node.kubernetes.io/unschedulable:NoSchedule 容忍会自动添加到 DaemonSet Pods。在调度 DaemonSet Pod 时,默认调度器会忽略 unschedulable 的 Node 节点。

污点和容忍
根据相关特性,DaemonSet Pods 会自动添加以下的容忍度。

容忍键 (Taint Key)影响 (Effect)版本描述
node.kubernetes.io/not-readyNoExecute1.13+当存在诸如网络分区之类的节点问题时,不会驱逐 DaemonSet pod。
node.kubernetes.io/unreachableNoExecute1.13+当存在诸如网络分区之类的节点问题时,不会驱逐 DaemonSet pod。
node.kubernetes.io/disk-pressureNoSchedule1.8+节点磁盘压力大时,依然允许 DaemonSet 调度至该节点。
node.kubernetes.io/memory-pressureNoSchedule1.8+节点内存压力大时,依然允许 DaemonSet 调度至该节点。
node.kubernetes.io/unschedulableNoSchedule1.12+DaemonSet pods 可以通过默认调度程序容忍节点“不可调度”(如 Cordon 状态)的属性。
node.kubernetes.io/network-unavailableNoSchedule1.12+使用主机网络 (HostNetwork) 的 DaemonSet pod 可以容忍网络不可用属性。

六、与 Daemon Pods 进行通信

下面是与 DaemonSet 中 Pod 进行通信的一些可能模式:

  • 推送:DaemonSet 中的 Pod 配置为将更新发送给另一个服务,例如统计数据库。他们没有客户。
  • NodeIP 和已知端口:DaemonSet 中的 Pod 可以使用 hostPort,以便可以通过 Node 节点 IP 访问 Pod。客户端以某种方式知道节点 IP 列表,并按知道端口。
  • DNS:使用相同的 Pod 选择器创建无头服务 (headless service),然后使用该 endpoints 资源发现 DaemonSets 或从 DNS 检索多个记录。
  • 服务:使用相同的 Pod 选择器创建服务,并使用该服务在随机 Node 节点上访问守护程序。(无法到达特定节点。)

七、更新 DaemonSet

如果更改了 Node 节点标签,DaemonSet 会立即将 Pod 添加到新匹配的 Node 节点,并从不匹配的 Node 节点中删除 Pod。可以修改 DaemonSet 创建的 Pod。但是,不允许更新 Pod 所有字段。此外,DaemonSet 控制器将在下次创建节点(即使具有相同名称)时使用原始模板。可以删除 DaemonSet,如果通过 kubectl 指定了 –cascade=false,则 Pod 会保留在 Node 节点上。可以使用不同的模板创建新的 DaemonSet,具有不同模板的新 DaemonSet 将所有现有 Pod 识别为具有匹配标签。尽管 Pod 模板不匹配,它也不会修改或删除它们,需要通过删除 Pod 或删除节点来强制创建新的 Pod。