DaemonSet

DaemonSet简介

DaemonSet:服务守护进程,它的主要作用是在k8s集群所有的节点中运行我们部署的守护进程,相当于在集群节点上分别部署pod副本,如果有新的节点加入集群,DaemonSet会自动在该节点上运行我们需要的部署的pod副本,相反,如果有节点退出户集群,DaemonSet也会移除部署在旧节点的pod副本。

1,DaemonSet的主要特征:

  • 这个pod运行在k8s集群中每一个节点上(node)
  • 每一个节点上只会运行一个这样的pod实例
  • 如果新的节点加入k8s集群后,该pod会自动的在新节点上被创建出来
  • 当旧节点被删除后,它上面的pod也相应的会被回收掉

2,DaemonSet常用场景:

  • 网路组件的agent组件,如(Flannel,Calico)需要运行在每一个节点上,用来处理这个节点上的容器网路
  • 存储插件的agent组件,如(Ceph),需要运行在每一个节点上,用来在这个节点上挂载远程存储目录
  • 监控系统的数据收集组件,如(prometheus node exporter Cadvisor)需要运行在每一个节点上,负责在每一个节点上,负责这个节点上的监控信息收集
  • 日志系统的数据收集组件,如(Fluent,Logstash)需要运行在每一个节点上,复制这个节点上的日志收集

DaemonSet的实现原理

DaemonSet开始运行的时机,很多时候比整个k8s集群出现的时机都要早,比如再创建k8s集群后,node的节点上由于没有可用的容器网路,集群节点状态会是Notready,普通的pod将无法运行,这就需要通过DaemonSet部署一个网路插件ahent组件。

1,DamonSet是如何确保每一个节点只运行一个pod?

  1. DaemonSet的控制器模型DaemonSet Controller先从Etcd里获取所有node列表
  2. 然后遍历所有的node检查,当前这个node节点上是不是只有一个携带了我们定义的标签的pod在运行
  3. 如果没有定义的pod,那么意味着要在这个node上创建这样的一个pod
  4. 如果有定义的pod,但是数量大于1,那么那么就说明要调用k8s api把多余的pod从这个node上删除掉掉
  5. 如果正好只有一个定义的pod,那说明这个节点是正常的

2,如果只在定义的节点上运行pod?

首先我们会想到使用nodeSelector字段来指定node的名字,但是在k8s项目里,nodeSelector起始已经将要废弃的字段了,因为,现在有一个新功能更完善的字段可以代替它,即:nodeAffinity。

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

上面文件定义了spec.affinity字段,它是pod里面和调度相关的一个字段,然后又定义了一个nodeAffinity(节点关系),这里它的定义含义是:

  • requiredDuringSchedulingIgnoredDuringExecution:它的意思是说,这个 nodeAffinity 必须在每次调度的时候予以考虑。同时,这也意味着你可以设置在某些情况下不考虑这个nodeAffinity
  • 这个 Pod,将来只允许运行在“metadata.name”是“node-geektime”的节点上;
  • 这个 Pod,将来只允许运行在“metadata.name”是“node-geektime”的节点上;

后面会有专门的随笔介绍node,pod的亲和性

DaemonSet Controller 会在创建 Pod 的时候,自动在这个 Pod 的 API 对象资源里,加上这样一个 nodeAffinity 定义。其中,需要绑定的节点名字,正是当前正在遍历的这个 Node。当然,DaemonSet 并不需要修改用户提交的 YAML 文件里的 Pod 模板,而是在向 Kubernetes 发起请求之前,直接修改根据模板生成的 Pod 对象。

3,DaemonSet的污点和容忍(后面会有随笔详细介绍)

DaemonSet会有在这个pod自动加上另外的一个与调度相关的字段,叫做tolerations(容忍),这个字段意味着这个pod会容忍(Toleration)某些node的污点(taint),可以在有污点的节点上调度运行,从而保证每一个节点上都会被调度一个pod

DaemonSet字段添加的tolerations字段:

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

在k8s集群中,当一个节点的网路插件尚未安装时,这个节点就会被自动加上名为:node.kubernetes.io/network-unavailable的污点,通过这样的英特tolerations,调度器在调度这个pod时候,就会忽略当前节点上的污点,从而成功的将网路组件的Agent调度到这个机器上来启动

...
template:
    metadata:
      labels:
        name: network-plugin-agent
    spec:
      tolerations:
      - key: node.kubernetes.io/network-unavailable
        operator: Exists
        effect: NoSchedule

尽管DaemonSet pod遵守污点(taint)和容忍(tolerations),但是一下的容忍会根据相关特性字段添加到DaemonSet管理的pod中

Toleration Key 影响 版本 描述
node.kubernetes.io/not-ready NoExecute 1.13+ 当存在节点问题(如网络分区)时,DaemonSet pod不会被驱逐。
node.kubernetes.io/unreachable NoExecute 1.13+ 当存在节点问题(如网络分区)时,DaemonSet pod不会被驱逐。
node.kubernetes.io/disk-pressure NoSchedule 1.8+ 当存在节点问题(如网络分区)时,DaemonSet pod不会被驱逐。
node.kubernetes.io/memory-pressure NoSchedule 1.8+ 当存在节点问题(如网络分区)时,DaemonSet pod不会被驱逐。
node.kubernetes.io/unschedulable NoSchedule 1.12+ 在默认的调度程序中,DaemonSet pod允许不可调度的属性。
node.kubernetes.io/network-unavailable NoSchedule 1.12+ 使用主机网络的DaemonSet pod,默认调度器允许网络不可用属性。

DaemonSet的使用方法

定义一个DaemonSet

创建一个DaemonSet和Deployment相似,比如创建一个nginx的DaemonSet:

[root@k8s-master01 ns-slx-study]# cat DaemonSet.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: nginx-ds
  name: nginx01-ds
spec:
  selector:
    matchLabels:
      app1: nginx-mb-ds
  template:
    metadata:
      labels:
        app1: nginx-mb-ds
    spec:
      nodeSelector:  #选择指定的node上的标签,是pod级别的
        disktype: ssd
      containers:
      - name: nginx123
        image: nginx:1.15.12
        imagePullPolicy: IfNotPresent

1,必须字段

  和其他所有 Kubernetes 配置一样,DaemonSet 需要 apiVersion、kind 和 metadata 字段,同时也需要一个.spec 配置段

2,pod模板

  .spec 唯一需要的字段是.spec.template。.spec.template 是一个 Pod 模板,它与 Pod 具有相同的配置方式,但它不具有 apiVersion 和 kind 字段。除了 Pod 必需的字段外,在 DaemonSet 中的 Pod 模板必须指定合理的标签。

3,pod Selector

  .spec.selector 字段表示 Pod Selector,它与其他资源的.spec.selector 的作用相同。

4,指定节点部署

  nodeSelector 字段,必须在node上大对应的label

#创建命令
kubectl create -f DaemonSet.yaml
# 使用-o wide 可以查看 Pod 所在的节点时
 kubectl get po -o wide

DaemonSet更新和回滚

如果添加了新节点或修改了节点标签(Label),DaemonSet 将立刻向新匹配上的节点添加Pod,同时删除不能匹配的节点上的 Pod。

在k8s1.16以后的版本中,可以在DaemonSet 上执行滚动更新,未来的 Kubernetes 版本将支持节点的可控更新

DaemonSet 更新策略和 StatefulSet 类似,也有 OnDelete 和 RollingUpdate 两种方式。

  updateStrategy:
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 1
    type: RollingUpdate

方式:edit 和yaml ,更建议使用edit的方式

命令行方式(不建议)

#更新
kubectl edit ds/<daemonset-name>
kubectl patch ds/<daemonset-name> -p=<strategic-merge-patch>
#更新镜像
kubectl set image ds/<daemonset-name><container-name>= <container-newimage> --record=true
#查看更新状态
kubectl rollout status ds/<daemonset-name>
#列出所有修订版本
kubectl rollout history daemonset <daemonset-name>
#回滚到指定revision
kubectl rollout undo daemonset <daemonset-name> --to-revision=<revision>
DaemonSet 的更新和回滚与 Deployment 类似

参考:DaemonSet | Kubernetes

posted @ 2023-02-25 01:14  百因必有果  阅读(289)  评论(0编辑  收藏  举报