Kuebernetes之DaemonSet

系列目錄html

DaemonSet確保集羣中每一個(部分)node運行一份pod副本,當node加入集羣時建立pod,當node離開集羣時回收pod。若是刪除DaemonSet,其建立的全部pod也被刪除,DaemonSet中的pod覆蓋整個集羣。node

當須要在集羣內每一個node運行同一個pod,使用DaemonSet是有價值的,如下是典型使用場景:docker

  • 運行集羣存儲守護進程,如glusterd、ceph。數據庫

  • 運行集羣日誌收集守護進程,如fluentd、logstash。api

  • 運行節點監控守護進程,如Prometheus Node Exporter, collectd, Datadog agent, New Relic agent, or Ganglia gmond。網絡

建立DaemonSet

如下是DaemonSet的示例spec文件,運行fluentd-elasticsearch image:app

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。上例中有以下內容:elasticsearch

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

緣由就是系統默認爲master節點增長了 「node-role.kubernetes.io/master」的Taint,以抵制普通pod部署,使master成爲專用節點。由於咱們預期上例DaemonSet在集羣內全局部署,所以須要加入相匹配的Toleration。ui

若是預期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 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/disk-pressure NoSchedule TaintNodesByCondition 1.8+
node.kubernetes.io/memory-pressure NoSchedule TaintNodesByCondition 1.8+
node.kubernetes.io/unschedulable NoSchedule 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 NoSchedule ScheduleDaemonSetPods, TaintNodesByCondition, hostnework 1.11+ 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 NoSchedule ExperimentalCriticalPodAnnotation(critical pod only), TaintNodesByCondition 1.8+

與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提供統一入口與負載均衡。

相關文章
相關標籤/搜索