Kubernetes专栏

Kubernetes:DaemonSet剖析

2021-03-28  本文已影响0人  wyatt_plus

一. 简介

DaemonSet 的主要作用,是在 Kubernetes 集群里,运行一个 Daemon Pod。 DaemonSet 只管理 Pod 对象,然后通过 nodeAffinity 和 Toleration 这两个调度器的小功能,保证了每个节点上有且只有一个 Pod。
所以,这个 Pod 有如下三个特征:

Daemon Pod 的意义确实是非常重要的。比如的作用:

二. nodeAffinity

我们的 DaemonSet Controller 会在创建 Pod 的时候,自动在这个 Pod 的 API 对象里,加上这样一个 nodeAffinity 定义。

2.1 场景

在这个 Pod 里,声明了一个 spec.affinity 字段,然后定义了一个 nodeAffinity。其中,spec.affinity 字段,是 Pod 里跟调度相关的一个字段。

2.2 案例

比如我们创建如下的一个YAML文件:

apiVersion: v1
kind: Pod
metadata:
  name: demo-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: metadata.name
            operator: In
            values:
            - demo-node

关于上面参数的具体含义:

2.3 作用

在 nodeAffinity 的定义处,可以支持更加丰富的语法,比如operator: In(即:部分匹配)。
我们的 DaemonSet Controller 会在创建 Pod 的时候,自动在这个 Pod 的 API 对象里,加上这样一个 nodeAffinity 定义。

三. Toleration

3.1 场景

DaemonSet 还会给这个 Pod 自动加上另外一个与调度相关的字段,叫作 tolerations。这个字段意味着这个 Pod,会“容忍”(Toleration)某些 Node 的“污点”(Taint)。

3.2 案例

apiVersion: v1
kind: Pod
metadata:
  name: with-toleration
spec:
  tolerations:
  - key: node.kubernetes.io/unschedulable
    operator: Exists
    effect: NoSchedule

在正常情况下,被标记了 unschedulable“污点”的 Node,是不会有任何 Pod 被调度上去的(effect: NoSchedule)。可是,DaemonSet 自动地给被管理的 Pod 加上了这个特殊的 Toleration,就使得这些 Pod 可以忽略这个限制,继而保证每个节点上都会被调度一个 Pod。
当然,如果这个节点有故障的话,这个 Pod 可能会启动失败,而 DaemonSet 则会始终尝试下去,直到 Pod 启动成功。

3.3 作用

通过这样一个 Toleration,调度器在调度这个 Pod 的时候,就会忽略当前节点上的“污点”,从而成功地将网络插件的 Agent 组件调度到这台机器上启动起来。
这种机制,正是我们在部署 Kubernetes 集群的时候,能够先部署 Kubernetes 本身、再部署网络插件的根本原因:因为当时我们所创建的 Weave 的 YAML,实际上就是一个 DaemonSet。

四. ControllerRevision

DaemonSet 使用 ControllerRevision,来保存和管理自己对应的“版本”。在 Kubernetes 项目里,ControllerRevision 其实是一个通用的版本管理对象。这样,Kubernetes 项目就巧妙地避免了每种控制器都要维护一套冗余的代码和逻辑的问题。

4.1 概念

Kubernetes v1.7 之后添加了一个 API 对象,名叫 ControllerRevision,专门用来记录某种 Controller 对象的版本。
ControllerRevision 对象,实际上是在 Data 字段保存了该版本对应的完整的 DaemonSet 的 API 对象。并且,在 Annotation 字段保存了创建这个对象所使用的 kubectl 命令。

4.2 回滚原理

现在 DaemonSet Controller 就可以使用这个历史 API 对象,对现有的 DaemonSet 做一次 PATCH 操作(等价于执行一次 kubectl apply -f “旧的 DaemonSet 对象”),从而把这个 DaemonSet“更新”到一个旧版本。
这也是为什么,在执行完这次回滚完成后,会发现,DaemonSet 的 Revision 并不会从 Revision=2 退回到 1,而是会增加成 Revision=3。这是因为,一个新的 ControllerRevision 被创建了出来。

五. 总结

DaemonSet其实就是依靠nodeAffinity和Toleration 实现的。这是一种不需要增加设计结构,而直接使用标签等方式完成的Daemon进程。这样的结构非常符合Kubernetes的控制器模式,一切皆对象。

个人博客: Wyatt's Blog

Reference

https://time.geekbang.org/column/article/41366?utm_campaign=guanwang&utm_source=baidu-ad&utm_medium=ppzq-pc&utm_content=title&utm_term=baidu-ad-ppzq-title
https://medium.com/kubernetes-tutorials/a-guide-to-kubernetes-daemonsets-6db7920ad140

上一篇下一篇

猜你喜欢

热点阅读