DaemonSet,就是用来部署守护进程的,DaemonSet用于在每个k8s节点中将守护进程的副本作为后台进程运行,说白了就是在每个节点部署一个Pod副本,当节点加入到k8s集群中,Pod会被调度到该节点上运行,当节点从集群中被移除后,该节点上的Pod都会被删除。

    • 集群存储守护程序,如glusterd、ceph要部署在每个节点上以提供持久化存储;
    • 节点监控守护程序,如prometheus监控集群,可以在每个节点上运行一个node-exporter进程来收集监控节点的信息;
    • 日志收集守护程序,如f’luentd或logstash,在每个节点上运行以收集容器的日志;
    • 节点网络插件,比如flannel、calico,在每个节点上运行为Pod提供网络服务。

    特别说明的一个就是关于DaemonSet运行的Pod的调度问题,正常情况下,Pod运行在哪个节点上是由k8s调度器策略来决定的,然而,由DaemonSet控制器创建的Pod实际上提前已经确定在哪个节点上了(Pod创建时指定了.spec.nodeName),所以:

    • DaemonSet并不关心一个节点的unshedulable字段,
    • DaemonSet可以创建Pod,及时调度器还没有启动。

    在每个节点上部署一个Nginx Pod:(nginx-ds.yaml)

    1. apiVersion: apps/v1
    2. kind: DaemonSet
    3. metadata:
    4. name: nginx-ds
    5. namespace: default
    6. spec:
    7. selector:
    8. matchLabels:
    9. k8s-app: nginx
    10. template:
    11. labels:
    12. k8s-app: nginx
    13. spec:
    14. containers:
    15. - name: nginx
    16. image: nginx:1.7.9
    17. ports:
    18. - name: http
    19. containerPort: 80

    直接创建:

    $ kubectl apply -f nginx-ds.yaml
    daemonset.apps/nginx-ds created
    

    创建完成,查看Pod的状态:

    $ kubectl get nodes
    NAME          STATUS   ROLES    AGE     VERSION
    ydzs-master   Ready    master   8d      v1.16.2
    ydzs-node1    Ready    <none>   8d      v1.16.2
    ydzs-node2    Ready    <none>   8d      v1.16.2
    ydzs-node3    Ready    <none>   6d23h   v1.16.2
    ydzs-node4    Ready    <none>   6d23h   v1.16.2
    $ kubectl get pods -l k8s-app=nginx -o wide
    NAME             READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
    nginx-ds-bpsb7   1/1     Running   0          75s   10.244.3.102   ydzs-node3   <none>           <none>
    nginx-ds-f4s2w   1/1     Running   0          75s   10.244.2.74    ydzs-node2   <none>           <none>
    nginx-ds-j9789   1/1     Running   0          75s   10.244.4.85    ydzs-node4   <none>           <none>
    nginx-ds-ngkt2   1/1     Running   0          75s   10.244.1.178   ydzs-node1   <none>           <none>
    

    除了master节点之外的节点上都有一个相应的Pod运行,因为master节点上默认被打上了污点,所以默认情况下不能调度普通的Pod上去。
    DaemonSet拓扑:
    image.png
    集群中的Pod和Node是一一对应的,而DaemonSet会管理全部机器上的Pod副本,负责对他们进行更新和删除。

    那么,DaemonSet控制器是如何保证每个Node上有且只有一个被管理的Pod的?

    • 首先控制器从etcd获取到所有Node列表,然后遍历所有的Node。
    • 根据资源对象定义是否有调度相关的配置,然后分别检查Node是否符合要求。
    • 在可运行的节点上检查是否已有对应的Pod,如果没有,则在这个Node上创建该Pod;如果有,并且数量大于1,那就把多余的Pod从这个节点上删除,如果有且只有1个,那就说明是正常的。

    在学习了资源调度后,也可以用Deployment来实现DaemonSet的效果,DaemonSet也有对应的更新策略,有onDeleteRollingupdate两种方式,默认为滚动更新。