k8s–基础–19–DaemonSet


1、介绍

  1. 是个控制器
  2. 能够确保k8s的所有节点都运行一个相同的pod副本,假设这个pod名称为pa
    1. 当增加node节点时,这个节点会自动创建一个pa副本
    2. 当删除node节点时,pa副本会自动删除
  3. 删除daemonset会删除它们创建的pod

1.1、使用场景

  1. 需要在每一个node节点运行一个存储服务,例如gluster,ceph
  2. 需要在每一个node节点运行一个日志收集服务,例如fluentd,logstash
  3. 需要在每一个node节点运行一个监控服务,例如Prometheus Node Exporter,zabbix agent等

1.2、用法

1.2.1、简单用法

在所有的节点上都启动一个 DaemonSet

1.2.2、复杂用法

单独对每种 daemon 类型使用多个 DaemonSet,但具有不同的标志,并且对不同硬件类型具有不同的内存、CPU要求。

2、创建DaemonSet

2.1、创建脚本

vi /root/test2/daemonset-nginx.yaml 

内容

 

apiVersion: apps/v1
kind: DaemonSet
metadata:
  # DaemonSet的名称
  name: daemonset-nginx
  # 命名空间
  namespace: kube-system
  labels:
    # DaemonSet 标签
    la-nginx: daemonset-nginx
spec:
  # 标签选择器
  selector:
    matchLabels:
      # 使用 k2-nginx: daemonset-nginx2 标签的template
      k2-nginx: daemonset-nginx2
  # 定义模板
  template:
    metadata:
      labels:
        # 定义标签
        k2-nginx: daemonset-nginx2
    spec:
      # 定义容忍度,容忍哪些污点
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      # 定义容器
      containers:
      - name: c-nginx
        image: nginx
        # 定义资源
        resources:
          # 最大CPU和内存
          limits:
            cpu: 200m
            memory: 200Mi 
          # 最小CPU和内存
          requests:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
          # 引入名称为nginx-volume1的存储定义
        - name: nginx-volume1
          # 容器存储卷目录
          mountPath: /usr/share/nginx/html
        - name: nginx-volume2
          mountPath: /usr/share/nginx/conf
          readOnly: true
      # pod中断所需的时间
      terminationGracePeriodSeconds: 30
      volumes:
        # 存储卷名称
      - name: nginx-volume1
        # 存储卷类型
        hostPath:
          # 节点的目录
          path: /data/nginx-volume1
      - name: nginx-volume2
        hostPath:
          path: /data/nginx-volume2
 
 

2.2、执行

kubectl apply -f /root/test2/daemonset-nginx.yaml 

# 查看
kubectl -n kube-system get pods  -o wide

在这里插入图片描述

3、DaemonSet运行在哪个节点上

  1. 有指定节点,那就在指定节点创建pod
  2. 未指定节点,将在所有节点上创建Pod

3.1、daemonset.spec.template.spec.nodeName

DaemonSet只在某个节点上创建Pod

在这里插入图片描述


apiVersion: apps/v1
kind: DaemonSet
metadata:
  # DaemonSet的名称
  name: daemonset-nginx
  # 命名空间
  namespace: kube-system
  labels:
    # DaemonSet 标签
    la-nginx: daemonset-nginx
spec:
  # 标签选择器
  selector:
    # 匹配拥有哪些标签的pod
    matchLabels:
      # 使用 k2-nginx: daemonset-nginx2 标签的template
      k2-nginx: daemonset-nginx2
  # 定义模板
  template:
    metadata:
      labels:
        # 定义标签
        k2-nginx: daemonset-nginx2
    spec:  
      # DaemonSet将在node1节点上创建Pod
      nodeName: node1
      # 定义容忍度,容忍哪些污点
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      # 定义容器
      containers:
      - name: c-nginx
        image: nginx

在这里插入图片描述

3.2、daemonset.spec.template.spec.affinity

DaemonSet控制器将在与该节点关联相匹配的节点上创建Pod。

kubectl explain daemonset.spec.template.spec.affinity

4、怎么调度daemonset pod

  1. 通过默认scheduler调度,DaemonSet确保所有符合条件的节点都运行相同的Pod副本
  2. 运行Pod的节点由Kubernetes调度器选择。

4.1、DaemonSet pods 由 DaemonSet 创建和调度。这将引入以下问题:

  1. Pod 行为的不一致性:
    1. 等待调度的正常Pod已被创建并处于Pending 状态,但DaemonSet pods未在Pending状态下创建。
  2. Pod preemption由默认scheduler处理。启用抢占后,DaemonSet控制器将在不考虑pod优先级和抢占的情况下制定调度决策。

4.2、ScheduleDaemonSetPods允许使用默认调度器而不是DaemonSet来调度

DaemonSets方法是将NodeAffinity添加到DaemonSet pods,而不是.spec.nodeName。 然后使用默认调度器将pod绑定到目标主机。 如果DaemonSet pod的亲和节点已存在,则替换它。

4.3、DaemonSet 控制器仅在创建或修改 DaemonSet pods时执行这些操作,并且不对 DaemonSet的spec.template进行任何更改。

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

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

5、污点和容忍度

尽管Daemon Pods遵循污点和容忍度规则,根据相关特性,会自动将以下容忍度添加到 DaemonSet Pods 中。

在这里插入图片描述

6、与DaemonSet中的Pod进行通信

与DaemonSet中的Pod进行通信的几种可能模式如下

  1. Push
  2. NodeIP和已知端口
  3. DNS
  4. Service

6.1、Push

将DaemonSet中的Pod配置为将更新发送到其他服务,例如统计数据库。

6.2、NodeIP和已知端口

  1. DaemonSet 中的Pod可以使用hostPort,从而可以通过 节点IP 访问到 Pod。
  2. 客户端能通过某种方法获取 节点IP 列表,并且基于此也可以获取到相应的端口。

6.3、DNS

创建具有相同PodSelector的 Headless Service,然后通过使用 endpoints 资源或从 DNS 中检索到多个 A 记录来发现 DaemonSet。

6.4、Service

创建具有相同PodSelector 的 Service,并使用该 Service 随机访问到某个节点上的DaemonSet pod(没有办法访问到特定节点)。

7、更新 DaemonSet

  1. 如果修改了节点标签,DaemonSet将立刻向新匹配上的节点添加Pod,同时删除不能够匹配的节点上的Pod。
  2. 可以修改DaemonSet创建的Pod。然而,不允许对Pod的所有字段进行更新。
    1. 当下次节点(即使具有相同的名称)被创建时,DaemonSet Controller 还会使用最初的模板。
  3. 可以删除一个DaemonSet。
    1. 如果使用kubectl并指定 --cascade=false,则Pod将被保留在节点上。
  4. 可以创建具有不同模板的新DaemonSet。
    1. 具有不同模板的新DaemonSet将能够通过标签匹配并识别所有已经存在的Pod。
  5. 如果有任何Pod需要替换,则DaemonSet根据它的 updateStrategy来替换

8、DaemonSet 的可替代选择

8.1、init 脚本

我们很可能希望直接在一个节点上启动daemon(守护)进程(例如,使用 init、upstartd、systemd)。这非常好,但基于DaemonSet来运行这些进程有如下一些好处

  1. 像对待应用程序一样,具备为daemon提供监控和管理日志的能力。
  2. 为daemon和应用程序使用相同的配置语言和工具(如Pod模板、kubectl)。
  3. 在资源受限的容器中运行daemon,能够增加daemon和应用容器的隔离性。然而,这也实现了在容器中运行daemon,但却不能在Pod中运行, 例如:直接基于Docker启动

9、Deployments和Daemonset区别联系

9.1、相似性

  1. 都能创建Pod
  2. 创建的Pod对应的进程都不希望被终止掉,举例如下
    1. Web 服务器
    2. 存储服务器

9.2、使用Deployments的场景

无状态的Sevice使用Deployments,需要实现对副本的数量进行扩缩容、平滑升级,就用Deployments

9.3、使用Daemonset的场景

需要Pod副本总是运行在全部或特定主机上,并需要先于其他Pod启动,就用daemonset。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐