Kubernetes的DaemonSet(上篇)

背景node

静儿做为美团容器化团队HULK的一员,常常须要和Kubernetes(k8s)打交道。第一次登录node(宿主机)的时候,发现连续登录几台都看到了Prometheus-Node-Exporter字样的docker进程。他们和普通的Pod(容器)同样,占用IP等资源,占用宿主机容许的pod数上限。后来经过看书了解到这是DaemonSet控制管理的Pod.docker

 

DaemonSet官方文档译文api

一个DaemonSet确保了全部的node上仅有一个的Pod的一个实例。当node被添加到集群中,Pod也被添加上去。当node被从集群移除,这些Pod会被垃圾回收。删除一个DaemonSet将会清理它建立的Pod。ruby

举一些DaemonSet典型用法的例子:app

  • 在每一个node上运行一个集群存储守护进程,例如glusterd、cephelasticsearch

  • 在每一个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请求。ui

写一个DaemonSet Spec

建立一个DaemonSet

在YAML文件中生命一个DaemonSet。daemonset.yaml文件描述了一个运行着fluentd-elasticsearch的docker镜像的DaemonSet。spa

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的污点和容忍(下篇)

相关文章
相关标签/搜索