Table of Contents
写在前面 #
上章节中介绍了Deployment,ReplicaSet,ReplicationController等副本控制器的使用和场景,接下来介绍kubernetes系列教程控制器DaemonSet使用。
1. DaemonSet控制器 #
1.1 DaemonSet简介 #
介绍DaemonSet时我们先来思考一个问题:相信大家都接触过监控系统比如zabbix,监控系统需要在被监控机安装一个agent,安装agent通常会涉及到以下几个场景:
- 所有节点都必须安装agent以便采集监控数据
- 新加入的节点需要配置agent,手动或者运行脚本
- 节点下线后需要手动在监控系统中删除
kubernetes中经常涉及到在node上安装部署应用,它是如何解决上述的问题的呢?答案是DaemonSet。DaemonSet守护进程简称DS,适用于在所有节点或部分节点运行一个daemon守护进程,如监控我们安装部署时网络插件kube-flannel和kube-proxy,DaemonSet具有如下特点:
- DaemonSet确保所有节点运行一个Pod副本
- 指定节点运行一个Pod副本,通过标签选择器或者节点亲和性
- 新增节点会自动在节点增加一个Pod
- 移除节点时垃圾回收机制会自动清理Pod

DaemonSet适用于每个node节点均需要部署一个守护进程的场景,常见的场景例如:
- 日志采集agent,如fluentd或logstash
- 监控采集agent,如Prometheus Node Exporter,Sysdig Agent,Ganglia gmond
- 分布式集群组件,如Ceph MON,Ceph OSD,glusterd,Hadoop Yarn NodeManager等
- k8s必要运行组件,如网络flannel,weave,calico,kube-proxy等
安装k8s时默认在kube-system命名空间已经安装了有两个DaemonSet,分别为kube-flannel-ds-amd64和kube-proxy,分别负责flannel overlay网络的互通和service代理的实现,可以通过如下命令查看:
\1. 查看kube-system命令空间的DaemonSet列表,当前集群有三个node节点,所以每个DS会运行三个Pod副本
1[root@node-1 ~]# kubectl get ds -n kube-system
2NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
3kube-flannel-ds-amd64 3 3 3 3 3 beta.kubernetes.io/arch=amd64 46d
4kube-proxy 3 3 3 3 3 beta.kubernetes.io/os=linux 46d
\2. 查看Pod的副本情况,可以看到DaemonSet在每个节点都运行一个Pod

1.2 DaemonSet定义 #
DaemonSet的定义和Deployment定义使用相类似,需要定义apiVersion,Kind,metadata和spec属性信息,spec中不需要定义replicas个数,spec.template即定义DS生成容器的模版信息,如下是运行一个fluentd-elasticsearch镜像容器的daemon守护进程,运行在每个node上通过fluentd采集日志上报到ElasticSearch。
\1. 通过yaml文件定义DaemonSet
1[root@node-1 happylau]# cat fluentd-es-daemonset.yaml
2apiVersion: apps/v1 #api版本信息
3kind: DaemonSet #类型为DaemonSet
4metadata: #元数据信息
5 name: fluentd-elasticsearch
6 namespace: kube-system #运行的命名空间
7 labels:
8 k8s-app: fluentd-logging
9spec: #DS模版
10 selector:
11 matchLabels:
12 name: fluentd-elasticsearch
13 template:
14 metadata:
15 labels:
16 name: fluentd-elasticsearch
17 spec:
18 tolerations:
19 - key: node-role.kubernetes.io/master
20 effect: NoSchedule
21 containers: #容器信息
22 - name: fluentd-elasticsearch
23 image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
24 resources: #resource资源
25 limits:
26 memory: 200Mi
27 requests:
28 cpu: 100m
29 memory: 200Mi
30 volumeMounts: #挂载存储,agent需要到这些目录采集日志
31 - name: varlog
32 mountPath: /var/log
33 - name: varlibdockercontainers
34 mountPath: /var/lib/docker/containers
35 readOnly: true
36 terminationGracePeriodSeconds: 30
37 volumes: #将主机的目录以hostPath的形式挂载到容器Pod中。
38 - name: varlog
39 hostPath:
40 path: /var/log
41 - name: varlibdockercontainers
42 hostPath:
43 path: /var/lib/docker/containers
DaemonSet定义注意事项:
- daemonset.spec.template定义Pod的模板信息,包含的metadata信息需要和selector保持一致
- template必须定义RestartPolicy的策略,切策略值为Always,保障服务异常时能自动重启恢复
- Pod运行在特定节点,支持指定调度策略,如nodeSelector,Node affinity,实现灵活调度
\2. 生成DaemonSet
1[root@node-1 happylau]# kubectl apply -f fluentd-es-daemonset.yaml
2daemonset.apps/fluentd-elasticsearch created
\3. 查看DaemonSet列表
1[root@node-1 happylau]# kubectl get daemonsets -n kube-system fluentd-elasticsearch
2NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
3fluentd-elasticsearch 3 3 3 3 3 <none> 16s
\4. 查看node上运行Pod的情况,在NODE列可以看到每个node都运行了一个Pod
1[root@node-1 happylau]# kubectl get pods -n kube-system -o wide |grep fluentd
2fluentd-elasticsearch-blpqb 1/1 Running 0 3m7s 10.244.2.79 node-3 <none> <none>
3fluentd-elasticsearch-ksdlt 1/1 Running 0 3m7s 10.244.0.11 node-1 <none> <none>
4fluentd-elasticsearch-shtkh 1/1 Running 0 3m7s 10.244.1.64 node-2 <none> <none>
\5. 查看DaemonSet详情,可以看到DaemonSet支持RollingUpdate滚动更新策略
1[root@node-1 happylau]# kubectl get daemonsets -n kube-system fluentd-elasticsearch -o yaml
2apiVersion: extensions/v1beta1
3kind: DaemonSet
4metadata:
5 annotations:
6 kubectl.kubernetes.io/last-applied-configuration: |
7 {"apiVersion":"apps/v1","kind":"DaemonSet","metadata":{"annotations":{},"labels":{"k8s-app":"fluentd-logging"},"name":"fluentd-elasticsearch","namespace":"kube-system"},"spec":{"selector":{"matchLabels":{"name":"fluentd-elasticsearch"}},"template":{"metadata":{"labels":{"name":"fluentd-elasticsearch"}},"spec":{"containers":[{"image":"quay.io/fluentd_elasticsearch/fluentd:v2.5.2","name":"fluentd-elasticsearch","resources":{"limits":{"memory":"200Mi"},"requests":{"cpu":"100m","memory":"200Mi"}},"volumeMounts":[{"mountPath":"/var/log","name":"varlog"},{"mountPath":"/var/lib/docker/containers","name":"varlibdockercontainers","readOnly":true}]}],"terminationGracePeriodSeconds":30,"tolerations":[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"}],"volumes":[{"hostPath":{"path":"/var/log"},"name":"varlog"},{"hostPath":{"path":"/var/lib/docker/containers"},"name":"varlibdockercontainers"}]}}}}
8 creationTimestamp: "2019-10-30T15:19:20Z"
9 generation: 1
10 labels:
11 k8s-app: fluentd-logging
12 name: fluentd-elasticsearch
13 namespace: kube-system
14 resourceVersion: "6046222"
15 selfLink: /apis/extensions/v1beta1/namespaces/kube-system/daemonsets/fluentd-elasticsearch
16 uid: c2c02c48-9f93-48f3-9d6c-32bfa671db0e
17spec:
18 revisionHistoryLimit: 10
19 selector:
20 matchLabels:
21 name: fluentd-elasticsearch
22 template:
23 metadata:
24 creationTimestamp: null
25 labels:
26 name: fluentd-elasticsearch
27 spec:
28 containers:
29 - image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
30 imagePullPolicy: IfNotPresent
31 name: fluentd-elasticsearch
32 resources:
33 limits:
34 memory: 200Mi
35 requests:
36 cpu: 100m
37 memory: 200Mi
38 terminationMessagePath: /dev/termination-log
39 terminationMessagePolicy: File
40 volumeMounts:
41 - mountPath: /var/log
42 name: varlog
43 - mountPath: /var/lib/docker/containers
44 name: varlibdockercontainers
45 readOnly: true
46 dnsPolicy: ClusterFirst
47 restartPolicy: Always #重启策略必须为Always,保障异常时能自动恢复
48 schedulerName: default-scheduler #默认调度策略
49 securityContext: {}
50 terminationGracePeriodSeconds: 30
51 tolerations:
52 - effect: NoSchedule
53 key: node-role.kubernetes.io/master
54 volumes:
55 - hostPath:
56 path: /var/log
57 type: ""
58 name: varlog
59 - hostPath:
60 path: /var/lib/docker/containers
61 type: ""
62 name: varlibdockercontainers
63 templateGeneration: 1
64 updateStrategy: #滚动更新策略
65 rollingUpdate:
66 maxUnavailable: 1
67 type: RollingUpdate
68status:
69 currentNumberScheduled: 3
70 desiredNumberScheduled: 3
71 numberAvailable: 3
72 numberMisscheduled: 0
73 numberReady: 3
74 observedGeneration: 1
75 updatedNumberScheduled: 3
1.3 滚动更新与回滚 #
\1. 更新镜像至最新版本
1[root@node-1 ~]# kubectl set image daemonsets fluentd-elasticsearch fluentd-elasticsearch=quay.io/fluentd_elasticsearch/fluentd:latest -n kube-system
2daemonset.extensions/fluentd-elasticsearch image updated
\2. 查看滚动更新状态
1[root@node-1 ~]# kubectl rollout status daemonset -n kube-system fluentd-elasticsearch
2Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 1 out of 3 new pods have been updated...
3Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 1 out of 3 new pods have been updated...
4Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 1 out of 3 new pods have been updated...
5Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 2 out of 3 new pods have been updated...
6Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 2 out of 3 new pods have been updated...
7Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 2 out of 3 new pods have been updated...
8Waiting for daemon set "fluentd-elasticsearch" rollout to finish: 2 of 3 updated pods are available...
9daemon set "fluentd-elasticsearch" successfully rolled out
\3. 查看DaemonSet详情,可以看到DS滚动更新的过程:DaemonSet先将node上的pod删除然后再创建

\4. 查看DaemonSet滚动更新版本,REVSION 1为初始的版本
1[root@node-1 ~]# kubectl rollout history daemonset -n kube-system fluentd-elasticsearch
2daemonset.extensions/fluentd-elasticsearch
3REVISION CHANGE-CAUSE
41 <none>
52 <none>
\5. 更新回退,如果配置没有符合到预期可以回滚到原始的版本
1[root@node-1 ~]# kubectl rollout undo daemonset -n kube-system fluentd-elasticsearch --to-revision=1
2daemonset.extensions/fluentd-elasticsearch rolled back
\6. 确认版本回退情况

\7. 观察版本回退的过程,回退的过程和和滚动更新过程类似,先删除Pod再创建

\8. 删除DaemonSet
1[root@node-1 ~]# kubectl delete daemonsets -n kube-system fluentd-elasticsearch
2daemonset.extensions "fluentd-elasticsearch" deleted
3[root@node-1 ~]# kubectl get pods -n kube-system |grep fluentd
4fluentd-elasticsearch-d6f6f 0/1 Terminating 0 110m
1.4 DaemonSet调度 #
前面kubernetes系列教程(七)深入玩转pod调度文章介绍了Pod的调度机制,DaemonSet通过kubernetes默认的调度器scheduler会在所有的node节点上运行一个Pod副本,可以通过如下三种方式将Pod运行在部分节点上:
- 指定nodeName节点运行
- 通过标签运行nodeSelector
- 通过亲和力调度node Affinity和node Anti-affinity
DaemonSet调度算法用于实现将Pod运行在特定的node节点上,如下以通过node affinity亲和力将Pod调度到部分的节点上node-2上为例。
\1. 为node添加一个app=web的labels
1[root@node-1 happylau]# kubectl get nodes --show-labels
2NAME STATUS ROLES AGE VERSION LABELS
3node-1 Ready master 47d v1.15.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node-1,kubernetes.io/os=linux,node-role.kubernetes.io/master=
4node-2 Ready <none> 47d v1.15.3 app=web,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node-2,kubernetes.io/os=linux
5node-3 Ready <none> 47d v1.15.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node-3,kubernetes.io/os=linux
\2. 添加node affinity亲和力调度算法,requiredDuringSchedulingIgnoredDuringExecution设置基本需要满足条件,preferredDuringSchedulingIgnoredDuringExecution设置优选满足条件
1[root@node-1 happylau]# cat fluentd-es-daemonset.yaml
2apiVersion: apps/v1
3kind: DaemonSet
4metadata:
5 name: fluentd-elasticsearch
6 namespace: kube-system
7 labels:
8 k8s-app: fluentd-logging
9spec:
10 selector:
11 matchLabels:
12 name: fluentd-elasticsearch
13 template:
14 metadata:
15 labels:
16 name: fluentd-elasticsearch
17 spec:
18 tolerations:
19 - key: node-role.kubernetes.io/master
20 effect: NoSchedule
21 containers:
22 - name: fluentd-elasticsearch
23 image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
24 resources:
25 limits:
26 memory: 200Mi
27 requests:
28 cpu: 100m
29 memory: 200Mi
30 volumeMounts:
31 - name: varlog
32 mountPath: /var/log
33 - name: varlibdockercontainers
34 mountPath: /var/lib/docker/containers
35 readOnly: true
36 affinity:
37 nodeAffinity:
38 preferredDuringSchedulingIgnoredDuringExecution: #优先满足条件
39 - weight: 1
40 preference:
41 matchExpressions:
42 - key: app
43 operator: In
44 values:
45 - web
46 requiredDuringSchedulingIgnoredDuringExecution: #要求满足条件
47 nodeSelectorTerms:
48 - matchExpressions:
49 - key: kubernetes.io/hostname
50 operator: In
51 values:
52 - node-2
53 - node-3
54 terminationGracePeriodSeconds: 30
55 volumes:
56 - name: varlog
57 hostPath:
58 path: /var/log
59 - name: varlibdockercontainers
60 hostPath:
61 path: /var/lib/docker/containers
\3. 生成DS,并查看列表
1[root@node-1 happylau]# kubectl delete ds -n kube-system fluentd-elasticsearch
2daemonset.extensions "fluentd-elasticsearch" deleted
3
4[root@node-1 happylau]# kubectl get daemonsets -n kube-system fluentd-elasticsearch
5NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
6fluentd-elasticsearch 1 1 1 1 1 <none> 112s
\4. 校验Pod运行的情况,DaemonSet的Pod调度到node-2节点上
1[root@node-1 happylau]# kubectl get pods -n kube-system -o wide
2NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES <none>
3fluentd-elasticsearch-9kngs 1/1 Running 0 2m39s 10.244.1.82 node-2 <none> <none>
写在最后 #
本文介绍了kubernetes中DaemonSet控制器,DS控制器能确保所有的节点运行一个特定的daemon守护进程,此外通过nodeSelector或node Affinity能够实现将Pod调度到特定的node节点。
参考文档 #
DaemonSet**:**https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/
『 转载 』该文章来源于网络,侵删。