3.5 控制器——DaemonSet(守護線程集)

3.5 控制器——DaemonSet(守護線程集)

 每個DaemonSet可以確保某些甚至全部節點運行一個Pod的副本,當node加入集羣時,Pod就會加入這些節點,同樣的,當節點從集羣中移除時,這些pods被垃圾回收。刪除一個DaemonSet將會清理由其創建的Pod。DaemonSet典型的應用場景有:

  • 運行羣集存儲守護程序,比如每個節點上的glusterdceph
  • 在每個節點上運行的日誌收集守護程序,比如fluentdlogstash
  • 在每個節點上運行節點監測守護程序,比如Prometheus Node ExporterSysdig Agent以及collectd等等;

在一個簡單的例子中,一個覆蓋所有節點的守護進程集將用於每種類型的守護進程。複雜的設置可能在單獨一種Daemon中使用多個DaemonSet,但可能帶有不同的標識、不同的存儲等。

【DaemonSet的規約Spec】

DaemonSet需要的字段有apiVersionkindmetadata,除此外,也需要.spec的內容:

  1. Pod模板,即.spec.template.spec中必要的字段,除非它是嵌套的沒有apiVersionkind。此外,DaemonSet中的Pod模板需要指定標籤pod selector,同時也DaemonSet中的Pod模板也需要重啓策略RestartPolicy,這個值總是爲Always(或者直接不指定,默認也是Always);
  2. 標籤選擇器Pod Selector,.spec.selectorJob中選擇器一樣,和之前的一樣,必須指定一個Pod的選擇器和.spec.template匹配,Pod選擇器如果不配置將不會有默認值,選擇器默認值與kubectl apply不兼容。同樣的,一旦DaemonSet被創建,.spec.selector將不能改變,如果改變將會導致之前的Pod變成遊離(即沒有DaemonSet管理了),.spec.selector字段由matchLabels(和ReplicationController中的.spec.selector一樣)和matchExpressions(它允許通過指定key值和value值以及操作符創建更加複雜的選擇器組,即多個選擇器組成)組成。
  3. 節點選擇器:.spec.template.spec.nodeSelector,如果指定了這個值,DaemonSet控制器將會在和 node selector 匹配的節點上創建Pod;同樣的如果指定了.spec.template.spec.affinity,DaemonSet控制器將會在和node.affinity匹配的節點上創建Pod;但如果都不指定,DaemonSet將會在所有節點(包括Master節點)上創建Pod。

注:關於上述的第二點,.spec.selector如果指定,那必須和.spec.template.metadata.labels相匹配,否則請求將會被API拒絕;此外,通常不應再通過其他的控制器創建標籤與此選擇器匹配的任何pods,否則DaemonSet會認爲這些Pod不是自己創建的,而是其他的控制器創建的。

下面是一個ES的DaemonSet配置daemonset.yaml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: gcr.io/fluentd-elasticsearch/fluentd:v2.5.1
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

可以創建這麼個DaemonSet:kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml,在各個節點拉取對應的鏡像(這裏使用的是我自己的阿里雲的鏡像,已公開大家可以公用)並修改tag:

docker pull registry.cn-shanghai.aliyuncs.com/fluentd-elasticsearch/fluentd:v2.5.1
docker tag registry.cn-shanghai.aliyuncs.com/fluentd-elasticsearch/fluentd:v2.5.1 gcr.io/fluentd-elasticsearch/fluentd:v2.5.1
docker rmi registry.cn-shanghai.aliyuncs.com/fluentd-elasticsearch/fluentd:v2.5.1

注意修改docker的驅動爲cgroupfs

【Daemon Pod 的調度】

 正常情況下,Pod運行的機器(節點)是由K8S的調度器選擇的,但由DaemonSet控制器創建的Pod是已經選擇了機器(在Pod創建時通過.spec.nodeName指定),DaemonSet確保所有符合條件的節點都運行pod的副本。但1.12之後的版本中可以使用ScheduleDaemonSetPods使用默認的K8S調度器進行調度,在DaemonSet的Pod中使用NodeAffinity替換.spec.nodeName,默認的調度器用於將Pod綁定到目標host。如果匹配node affinity的DaemonSet Pod 已經存在則替換。DaemonSet控制器僅會在創建、修改DaemonSet Pod時纔會操作,其不會對DaemonSet的spec.template有任何改變。

【和Daemon Pod通信】

 與DaemonSet中的pods通信的一些可能模式:

  • Push:DaemonSet中的Pod被配置成將更新發送到另一個服務,比如數據庫的狀態,它們沒有客戶端;
  • NodeIP和Known Port:DaemonSet中的Pod可以使用hostPort,因此那些Pod可以通過node IP獲取,客戶端並不知到節點IP的列表,只是按約定知道端口;
  • DNS:使用一些Pod selector創建一個Headless Service,然後使用endpoints資源發現DaemonSet或從DNS檢索多個記錄;
  • Service:使用一個Pod Selector創建一個Service,使用Service到達隨機節點上的Daemon;

【更新DaemonSet】

 如果node的標籤改變了,DaemonSet將會及時的將這些Pod添加到新匹配到的節點,並且從新的未匹配的節點上刪除Pod。可以更改DaemonSet創建的Pod,但不允許更新Pod的所有字段,DaemonSet控制器將會在新節點創建時使用原始模板。

 刪除DaemonSet,如果使用kubectl指定了--cascade=false,Pod將會遺留在節點上,可以使用不同的模板創建新的DaemonSet,新的DaemonSet將自識別節點上標籤匹配的Pod。儘管pod模板不匹配,但它不會修改或刪除它們,需要通過刪除Pod或Node來強制創建一個新的Pod。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章