ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

k8s DaemonSet 介绍与实例

2021-10-21 17:33:44  阅读:180  来源: 互联网

标签:name 实例 daemonset Pod k8s 节点 pod DaemonSet


我们之前说k8s中使用deployment、statefulset工作负载资源来分别维护无状态和有状态应用。这篇小作文我们会学习如何使用DaemonSet来维护一个守护进程(应用)。


一、DaemonSet是什么?

DaemonSet 是一个确保全部或者某些节点上必须运行一个 Pod的工作负载资源(守护进程),当有节点加入集群时, 也会为他们新增一个 Pod。

下面是常用的使用案例:

  • 集群守护进程,如Kurednode-problem-detector
  • 日志收集守护进程,如fluentdlogstash
  • 监控守护进程,如promethues node-exporter

通过创建DaemonSet 可以确保 守护进程pod 被调度到每个可用节点上运行。


二、DaemonSet 如何工作?

DaemonSet 是由控制器(controller manager)管理的 Kubernetes 工作资源对象。我们通过声明一个想要的daemonset状态,表明每个节点上都需要有一个特定的 Pod。协调控制回路会比较期望状态和当前观察到的状态。如果观察到的节点没有匹配的 Pod,DaemonSet controller将自动创建一个。可以参考之前《k8s工作流程详解》

在这个过程包括现有节点和所有新创建的节点。不过DaemonSet 控制器创建的 Pod 会被Kubernetes 调度器忽略,即DaemonSet Pods 由 DaemonSet 控制器创建和调度。这样带来的两个微妙的问题:

  • Pod 行为的不一致性:正常 Pod 在被创建后等待调度时处于 Pending 状态, DaemonSet Pods 创建后不会处于 Pending 状态下。
  • Pod 抢占行为由默认调度器处理。启用抢占后,DaemonSet 控制器将在不考虑 Pod 优先级和抢占 的情况下制定调度决策。

所以在k8s v1.12以后DaemonSet Controller 将会向 DaemonSet 的 Pod 添加 .spec.nodeAffinity 字段,而不是 .spec.nodeName 字段,并进一步由 kubernetes 调度器将 Pod 绑定到目标节点。如果 DaemonSet 的 Pod 已经存在了 nodeAffinity 字段,该字段的值将被替换。

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

daemonset pod的默认容忍规则如下:

image-20211021134258976

DaemonSet 默认在每个节点上创建一个 Pod。当然也可以使用节点选择器来限制可接受节点的数量。DaemonSet 控制器将仅在与 YAML 文件中预定义的nodeSelector字段匹配的节点上创建Pod。我们在下面会使用到。


三、DaemonSet实例

创建DaemonSet

我们只需要将前面deployment中的kind调整为DaemonSet 就可以创建出一个DaemonSet守护进程

apiVersion: apps/v1 
kind: DaemonSet 
metadata: 
  name: my-daemonset
spec: 
  selector: 
    matchLabels: 
      app: my-daemon
  template: 
    metadata: 
      labels: 
        app: my-daemon
    spec: 
      containers: 
        - name: daemonset-container 
          image: httpd 
          ports: 
          - containerPort : 80

通过apply应用后查看资源状态

$ kubectl get daemonset
NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
my-daemonset    1         1         1       1            1           <none>                   10m

由于我们minikube只有一个node 所以只建立了一个副本,在节点通过get查看到已创建出这个daemonset pod

$ kubectl get pod 
NAME                  READY   STATUS    RESTARTS   AGE
my-daemonset-97z2g    1/1     Running   0          10m

在daemonset资源状态中可以看到NODE SELECTOR的值为none,显然我们可以通过在pod模板中添加nodeSelector使DaemonSet 控制器仅在与Node 选择算符匹配的节点上创建出pod,接下来我们添加一个nodeSelector

apiVersion: apps/v1 
kind: DaemonSet 
metadata: 
  name: my-daemonset
spec: 
  selector: 
    matchLabels: 
      app: my-daemon
  template: 
    metadata: 
      labels: 
        app: my-daemon
    spec: 
      containers: 
        - name: daemonset-container 
          image: httpd 
          ports: 
          - containerPort : 80
      nodeSelector:
       kubernetes.io/hostname: minikube 

这样我们的pod只会在hostname为minikube的Node上创建DaemonSet守护进程的pod

$ kubectl get daemonset
NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                     AGE
my-daemonset    1         1         1       1            1           kubernetes.io/hostname=minikube   30m

除了通过nodeSelector来控制节点调度外,还可以通过上面提到的容忍策略即tolerations使daemonset pod 调度到“非正常“Node。

我们可以来看一个fluentd的官方elasticsearch daemonset

源文件地址:fluentd-daemonset-elasticsearch.yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
    version: v1
spec:
  selector:
    matchLabels:
      k8s-app: fluentd-logging
      version: v1
  template:
    metadata:
      labels:
        k8s-app: fluentd-logging
        version: v1
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch
        env:
          - name:  FLUENT_ELASTICSEARCH_HOST
            value: "elasticsearch-logging"
          - name:  FLUENT_ELASTICSEARCH_PORT
            value: "9200"
          - name: FLUENT_ELASTICSEARCH_SCHEME
            value: "http"
          # Option to configure elasticsearch plugin with self signed certs
          # ================================================================
          - name: FLUENT_ELASTICSEARCH_SSL_VERIFY
            value: "true"
          # Option to configure elasticsearch plugin with tls
          # ================================================================
          - name: FLUENT_ELASTICSEARCH_SSL_VERSION
            value: "TLSv1_2"
          # X-Pack Authentication
          # =====================
          - name: FLUENT_ELASTICSEARCH_USER
            value: "elastic"
          - name: FLUENT_ELASTICSEARCH_PASSWORD
            value: "changeme"
          # Logz.io Authentication
          # ======================
          - name: LOGZIO_TOKEN
            value: "ThisIsASuperLongToken"
          - name: LOGZIO_LOGTYPE
            value: "kubernetes"
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        # When actual pod logs in /var/lib/docker/containers, the following lines should be used.
        # - name: dockercontainerlogdirectory
        #   mountPath: /var/lib/docker/containers
        #   readOnly: true
        # When actual pod logs in /var/log/pods, the following lines should be used.
        - name: dockercontainerlogdirectory
          mountPath: /var/log/pods
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      # When actual pod logs in /var/lib/docker/containers, the following lines should be used.
      # - name: dockercontainerlogdirectory
      #   hostPath:
      #     path: /var/lib/docker/containers
      # When actual pod logs in /var/log/pods, the following lines should be used.
      - name: dockercontainerlogdirectory
        hostPath:
          path: /var/log/pods

特别之处在于,为了收集master节点上的pod日志,将会容忍fluentd调度到master节点。其中tolerations如下

image-20211021114701977

Daemon Pods 通信

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

  • 推送(Push):配置 DaemonSet 中的 Pod,将更新发送到另一个服务,例如统计数据库。
  • NodeIP 和已知端口:DaemonSet 中的 Pod 可以使用 hostPort,从而可以通过节点 IP 访问到 Pod。客户端能通过某种方法获取节点 IP 列表,并且基于此也可以获取到相应的端口。比如prometheus的node-exporter。
  • DNS:创建具有相同 Pod 选择算符的 无头服务 通过使用 endpoints 资源或从 DNS 中检索到多个 A 记录来发现 DaemonSet。

DaemonSet 更新

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

可以删除一个 DaemonSet。如果使用 kubectl 指定 --cascade=orphan 选项, 则 Pod 将被保留在节点上。接下来如果创建使用相同选择算符的新 DaemonSet, 新的 DaemonSet 会收养已有的 Pod。 如果有 Pod 需要被替换,DaemonSet 会根据其 updateStrategy 来替换。

比如prometheus中的node-exporter

image-20211021121548126

以上是关于k8s中的DaemonSet相关内容。


参考:

daemonset

node-affinity

node-exporter-daemonset

希望小作文对你有些许帮助,如果内容有误请指正。

您可以随意转载、修改、发布本文,无需经过本人同意。blogiqsing.github.io

标签:name,实例,daemonset,Pod,k8s,节点,pod,DaemonSet
来源: https://www.cnblogs.com/qsing/p/15434348.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有