1

K8s 中 Daemon 服务设计模式

 3 years ago
source link: https://kubesphereio.com/post/daemon-service/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
K8s 中 Daemon 服务设计模式

Daemon Service 模式允许在目标节点上调度和运行优先级高的、专注于基础设施的 Pod。管理员主要使用它来运行特定于节点的 Pods,以增强 Kubernetes 平台的功能。

软件系统中守护进程的概念存在于许多层面。在操作系统的层面上,守护进程是一个长期运行、自我恢复的计算机程序,它作为后台进程运行。在 Unix 中,守护进程的名称以 “d “结尾,如 httpd、named 和 sshd。在其他操作系统中,则使用服务启动的任务和幽灵作业等替代术语。

不管它们被称为什么,这些程序的共同特点是它们作为进程运行,通常不与显示器、键盘和鼠标交互,并且在系统启动时启动。在应用程序层面也存在类似的概念。例如,在 JVM 中守护线程在后台运行,为用户线程提供支持服务。这些守护线程的优先级较低,在后台运行,在应用程序的生命周期没有发言权,执行任务类似垃圾收集或结束。

同样,Kubernetes 中也有 DaemonSet 的概念。考虑到 Kubernetes 是一个分布式平台,分布在多个节点上,以管理应用 Pods 为主要目标,因此 DaemonSet 由运行在集群节点上的 Pods 代表,并为集群的其他节点提供一些后台功能。

ReplicaSet 和它的前身 ReplicationController 是负责确保特定数量的 Pods 运行的控制结构。这些控制器不断地监控运行中的 Pod 的列表,并确保实际的 Pod 数量总是与期望的数量相匹配。在这方面,DaemonSet 是一个类似的结构,负责确保一定数量的 Pods 始终在运行。不同的是,前两者运行特定数量的 Pod,通常是由高可用性和用户负载的应用需求驱动,而不考虑节点数量。

另一方面,DaemonSet 不是由消费者负载驱动决定运行多少个 Pod 实例和在哪里运行时。它的主要目的是在每个节点或特定节点上保持运行一个 Pod。接下来让我们在例 1-1 中看到这样一个 DaemonSet 的定义。

1.1 DaemonSet 实例
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata: 
  name: random-refresher
spec:
  selector:
    matchLabels:
      app: random-refresher
  template:
    metadata:
      labels:
        app: random-refresher
    spec: 
      nodeSelector:
        feature: hw-rng 
      containers:
      - image: k8spatterns/random-generator:1.0
        name: random-generator
        command:
        - sh
        - -c
        - >-
          "while true; do
          java -cp / RandomRunner /host_dev/random 100000;
          sleep 30; done"
        volumeMounts:
        - mountPath: /host_dev
          name: devices
        volumes:
        - name: devices
          hostPath:
            path: /dev

考虑到这种行为,DaemonSet 的主要候选者通常是与基础设施相关的进程,如日志收集器、度量导出器,甚至是 kube-proxy,这些进程会执行整个集群的操作。DaemonSet 和 ReplicaSet 的管理方式有很多不同,但主要有以下几点:

  • 默认情况下,DaemonSet 会给每个节点调度一个 Pod 实例。这可以通过使用 nodeSelector 字段来控制和限制节点的子集。
  • DaemonSet 创建的 Pod 已经指定了 nodeName。因此,DaemonSet 不需要 Kubernetes 调度器的存在就可以运行容器。这也允许使用 DaemonSet 来运行和管理 Kubernetes 组件。
  • 由 DaemonSet 创建的 Pod 可以在调度器启动之前运行,这使得它们可以在任何其他 Pod 被调度在节点上之前运行。
  • 由 DaemonSet 管理的 Pods 应该只在目标节点上运行,因此,被许多控制器以更高的优先级和不同的方式对待。例如,descheduler 会避免驱逐这类 Pod,集群 autoscaler 会单独管理它们等等。

通常,一个 DaemonSet 会在每个节点或节点子集上创建一个单一的 Pod。鉴于此,DaemonSets 管理的 Pod 有几种方式可以到达。

  • Service
    创建一个与 DaemonSet 相同的 Pod 选择器的 Service,并使用该 Service 到达一个守护者 Pod 负载均衡到随机节点。
  • DNS
    创建一个无头服务,其 Pod 选择器与 DaemonSet 相同,可用于从 DNS 中检索包含所有 Pod IP 和端口的多个 A 记录。
  • NodeIP with HostPort
    在 DaemonSet 中的 Pod 可以指定一个 hostPort,并通过节点 IP 地址和指定的端口进行访问。由于 hostIp 和 hostPort 以及协议的组合必须是唯一的,所以 Pod 可以被调度的地方数量是有限的。
  • Push
    DaemonSets Pods 中的应用可以将数据推送到 Pods 外部的指定位置或服务。不需要消费者到达 DaemonSets Pods。

另一种类似于 DaemonSet 运行容器的方式是通过静态 Pods 机制。Kubelet 除了与 Kubernetes APIServer 对话并获取 Pod 清单外,还可以从本地目录获取资源定义。这样定义的 Pod 只由 Kubelet 管理,并且只在一个节点上运行。API 服务并不观察这些 Pod,也没有控制器,也没有对它们进行健康检查。Kubelet 观察这样的 Pod,并在它们崩溃时重新启动它们。同样,Kubelet 也会定期扫描配置的目录,查看 Pod 定义的变化,并相应地添加或删除 Pod。

静态 Pods 可以用来分拆 Kubernetes 系统进程或其他容器的容器化版本。但 DaemonSets 与平台的其他部分集成度更好,推荐使用 DaemonSets,而不是静态 Pods。

我们描述的模式和 Kubernetes 特性主要是由开发者而不是平台管理员使用的。DaemonSet 介于两者之间,更倾向于管理员工具箱,但我们把它包括在这里,因为它对应用开发者也有适用性。DaemonSets 和 CronJobs 也是 Kubernetes 如何将 Crontab 和守护脚本等单节点概念转化为管理分布式系统的多节点集群基元的完美例子。这些都是开发人员也必须熟悉的新的分布式概念。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK