Kubernetes的DaemonSet(上篇)


背景

靜兒作為美團容器化團隊HULK的一員,經常需要和Kubernetes(k8s)打交道。第一次登陸node(宿主機)的時候,發現連續登陸幾台都看到了Prometheus-Node-Exporter字樣的docker進程。他們和普通的Pod(容器)一樣,占用IP等資源,占用宿主機允許的pod數上限。后來通過看書了解到這是DaemonSet控制管理的Pod.

 

DaemonSet官方文檔譯文

一個DaemonSet確保了所有的node上僅有一個的Pod的一個實例。當node被添加到集群中,Pod也被添加上去。當node被從集群移除,這些Pod會被垃圾回收。刪除一個DaemonSet將會清理它創建的Pod。

舉一些DaemonSet典型用法的例子:

  • 在每個node上運行一個集群存儲守護進程,例如glusterd、ceph

  • 在每個node上運行一個日志集合,例如fuentd或者logstash

  • 在每個node上運行一個node監控后台線程,例如Prometheus Node Exporter,collectd,Dynatrace OneAgent,AppDynamics Agent,Datadog agent,New Relic agent,Ganglia gmod 或者Instana agent.

在一種簡單的場合下,一個DeamonSet會被使用在任意種后台線程、覆蓋所有的node。在更復雜的安裝方式中,多個DaemonSet會被用於一種后台線程。但是在不同的硬件類型會對應不同的標識或者不同的內存和CPU請求。

寫一個DaemonSet Spec

創建一個DaemonSet

在YAML文件中生命一個DaemonSet。daemonset.yaml文件描述了一個運行着fluentd-elasticsearch的docker鏡像的DaemonSet。

controllers/daemonset.yaml

apiVersion: apps/v1kind: DaemonSetmetadata:  name: fluentd-elasticsearch  namespace: kube-system  labels:    k8s-app: fluentd-loggingspec:  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
  • 創建一個基於YAML文件的DaemonSet

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

所需的字段

和其他的Kubernetes配置文件一樣,一個DaemonSet需要apiVersion,kind和metadata字段。配置文件的通用信息,可以看deploying application,configuring containers和object management using kubectl文檔。

一個DaemonSet也需要一個spec區

Pod模板

.spec.template是.spec的必需字段。

.spec.template是一個pod模板。除了是嵌套的並且沒有apiVersion或者kind之外,它的schema和pod是一樣的。

除了pod必需的字段,在DaemonSet中的pod模板必需指定合適的label(詳見pod selector)。

在DaemonSet中的pod模板必需要有一個Always的RestartPolicy。如果沒有明確指定,默認也是Aways。

Pod選擇器

.spec.selector字段是pod的選擇器。它的功能和job的.spec.selector一樣。

在Kubernetes1.8中,必需指定一個帶有.spec.template的pod選擇器。當pod選擇器為空時將不會再是默認的選擇器。選擇器默認和kubectl apply是不兼容的。一旦DaemonSet被創建,.spec.selector就不能變了。一旦改變了pod選擇器,可能會導致意外將這個pod變成「孤島」。用戶會很迷惑。

.spec.selector是有兩個字段組成的對象:

  • matchLabels - 和ReplicationController的.spec.selector是一樣的

  • matchExpressions - 通過制定key、values列表、operatorl來定制更加精細的選擇器。

指定了兩個,它們的作用關系是and。

一旦.spec.selector被指定,就必須和.spec.template.metadata.labels匹配。不匹配的配置會被API拒掉。

同時,用戶平時也不應該創建匹配這些選擇器的標簽。包括直接創建、通過其他的DaemonSet創建,或者通過其他的像ReplicaSet這樣的控制器來創建。否則,DaemonSet控制器會認為這些pod是自己創建的。但是如果說想手動創建一個值不同的pod放在node上做測試就另當別論了。

在指定node上運行pod

指定.spec.template.spec.nodeSelector,DaemonSet控制器會在node上創建一個匹配node選擇器的pod。同時,如果指定.spec.template.spec.affinity,這時候DaemonSet控制器會創建匹配node的affinity的pod。如果什么兩者都不指定,DaemonSet控制器將會在所有node上創建pod。

Daemon的pod是怎么被調度的

通過DaemonSet控制器來調度(1.12版本被禁用)

pod實際運行的設備通常是Kubernetes調度器來選擇的。但是DaemonSet控住器創建的pod是已經指定好了設備的(Pod在創建時.spec.nodeName已經被指定了,所以會被調度器忽略)。基於這個原因:

  • node節點上的字段unschedulable會被DaemonSet控制器忽略。

  • DaemonSet控制器在調度還沒開始時就會創建Pod來幫助啟動集群。

被默認調度器調度(1.12版本開始默認啟動)

DaemonSet確保所有有資格的node運行一個pod的一個實例。一般來說,Kubernetes控制器決定了一個Pod選擇哪個node。但是DaemonSet控制器卻負責創建和調度DaemonSet的pod。這引入了下面的問題:

  • 不一致的Pod行為:普通Pod會以Pending狀態創建出來等待調度。但是DaemonSet的Pod的初始狀態卻不是Pending。這讓用戶很疑惑。

  • 默認調度器處理Pod優先權(Pod preemption)。當preemption被啟用,DaemonSet控制器在做調度決策時就不考慮pod優先權。

ScheduleDaemonSetPods允許你使用默認調度器而不是DaemonSet控制器來調度。這是通過添加NodeAffinity項而不是.spec.nodeName到DaemonSet的Pod來實現的。默認調度被應用於綁定pod到目標宿主機。DaemonSet Pod的node affinity已經存在時會被替換。DaemonSet控制器只在創建或者修改DaemonSet Pod時才會這樣。不會修改DaemonSet的spec.template。

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

污點和容忍

Daemon Pod支持污點和容忍。下面的容忍會根據相應的特性被自動添加到DaemonSet。

 

總結

初學一個技術如果感覺無法下手,學了也記不住的趕腳。不如先從一個問題出發:為什么會有這個Pod存在?這樣先進行感知再系統學習。

相關閱讀

《兩地書》--K8s基礎知識

Kubernetes的污點和容忍(上篇)

Kubernetes的污點和容忍(下篇)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM