天天看點

Kuebernetes之DaemonSet

系列目錄

DaemonSet確定叢集中每個(部分)node運作一份pod副本,當node加入叢集時建立pod,當node離開叢集時回收pod。如果删除DaemonSet,其建立的所有pod也被删除,DaemonSet中的pod覆寫整個叢集。

當需要在叢集内每個node運作同一個pod,使用DaemonSet是有價值的,以下是典型使用場景:

  • 運作叢集存儲守護程序,如glusterd、ceph。
  • 運作叢集日志收集守護程序,如fluentd、logstash。
  • 運作節點監控守護程序,如Prometheus Node Exporter, collectd, Datadog agent, New Relic agent, or Ganglia gmond。

建立DaemonSet

以下是DaemonSet的示例spec檔案,運作fluentd-elasticsearch image:

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: k8s.gcr.io/fluentd-elasticsearch:1.20
        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中沒有restart policy字段,預設為Always。如果有的話,必需将值設定成Always,否則在建立時出出現不可用錯誤。

DaemonSet同樣會受到Taint的抵制,如果不在配置中加入比對的Toleration,那麼DaemonSet不會在擁有Taint屬性的node上部署pod。上例中有如下内容:

tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
           

原因就是系統預設為master節點增加了 “node-role.kubernetes.io/master”的Taint,以抵制普通pod部署,使master成為專用節點。因為我們預期上例DaemonSet在叢集内全局部署,是以需要加入相比對的Toleration。

如果預期DaemonSet隻在特定節點上運作,可以在上述配置檔案中加入.spec.template.spec.nodeSelector字段。.

spec.template.spec.nodeSelector字段内加入節點選擇器(node selector)或者親和選擇器(node affinity),則DaemonSet隻會在滿足條件的node上部署pod。總之,可以通過Taint、Toleration、Affinity、node label控制DaemonSet部署pod的節點範圍。

将以上内容儲存在daemonset.yaml檔案中,執行如下指令建立DaemonSet:

kubectl create -f https://k8s.io/examples/controllers/daemonset.yaml
           

系統如何排程DaemonSet pod?

預設情況下DaemonSet在建立pod時,為其增加spec.nodeName字段,也就是說所建立的pod運作在那個節上在建立階段就已經确定,是以DaemonSet中的pod實際上沒有接受kubernetes scheduler的排程,它不需要排程,是以産生以下兩個特性:

  • DaemonSet中的pod不遵從節點的unreachable條件,也就是即使節點被系統判定為不可達,DaemonSet仍然試圖在其上部署pod。
  • 在叢集引導階段,即使kubernetes scheduler還沒有部署生效,DaemonSet仍然可以将pod部署到叢集中的任何節點,此特性主要是在叢集引導階段使用。

因為DaemonSet不同于正常pod的排程特性,它帶來兩個問題:

  • pod行為不一緻。普通pod被建立以後等待排程的階段稱為pending,因為DaemonSet中的pod無需排程,因而無此狀态,使用者會是以産生迷惑。
  • pod優先級特性由kubernetes scheduler實作,DaemonSet無此特性。當系統打開pod優先級功能時,pod優先級特性會被DaemonSet中的pod忽略。

為了解決以上兩個問題,kubernetes增加了通過設定允許DaemonSet使用kurbernetes scheduler的功能,并在1.11的 alpha版本中成為穩定特性。其實作機制是DaemonSet在建立pod時,不再自動添加.spec.nodeName,而是以nodeAffinity取而代之,示例如下:

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

其中"target-host-name"就是原來.spec.nodeName的值,這樣pod就會被kubernetes scheduler排程。通過以上操作解決了上述兩個問題。但DaemonSet的排程有自己因有的特性,在上文中提到的“不受節點unreachable條件限制”,為了使DaemonSet在使用kubernetes scheduler時仍然保持此特性需要打開叢集的"TaintNodesByCondition"特性,如果DaemonSet使用主機網絡那麼必需在DaemonSet中添加如下的Toleration:

node.kubernetes.io/network-unavailable:NoSchedule
           

DaemonSet自動添加的Toleration

系統在某此條件下會自動為節點添加Taint,比如硬碟不足、網絡不可達等,以阻止新pod往不滿足條件的節點上排程。但DaemonSet的目的是在全部有資格的node上部署,不希望被這種Taint打斷,因經系統也預設為DaemonSet上的pod添加Toleration。如下表:

Toleration Key Effect Alpha Features Version Description
node.kubernetes.io/not-ready NoExecute TaintBasedEvictions 1.8+ when TaintBasedEvictions is enabled,they will not be evicted when there are node problems such as a network partition.
node.kubernetes.io/unreachable
node.kubernetes.io/disk-pressure NoSchedule TaintNodesByCondition
node.kubernetes.io/memory-pressure
node.kubernetes.io/unschedulable ScheduleDaemonSetPods, TaintNodesByCondition 1.11+ When ScheduleDaemonSetPodsis enabled, TaintNodesByConditionis necessary to make sure DaemonSet pods tolerate unschedulable attributes by default scheduler.
node.kubernetes.io/network-unavailable ScheduleDaemonSetPods, TaintNodesByCondition, hostnework When ScheduleDaemonSetPodsis enabled, TaintNodesByConditionis necessary to make sure DaemonSet pods, who uses host network, tolerate network-unavailable attributes by default scheduler.
node.kubernetes.io/out-of-disk ExperimentalCriticalPodAnnotation(critical pod only), TaintNodesByCondition

與DaemonSet中pod通信的幾種模式

  • Push:收集資料并向其它服務發送,如将收集到的統計資訊發送給統計類型資料庫。
  • NodeIP and Known Port:DaemonSet中的pod可以被設定使用主機網絡的一個port,而用戶端可以很友善的知道節點IP清單,是以可以通過節點IP位址與port通路DaemonSet pod。
  • DNS:建立無頭服務并且讓它的選擇器比對所有DaemonSet的pod,這樣DaemonSet中的pod就會成為無頭服務的endpoints。類似于StatefulSet。
  • Service:讓Service選中DaemonSet,為通路DaemonSet中的pod提供統一入口與負載均衡。