一、简介
DaemonSet保证在每个Node上都运行一个Pod,如果 新增一个Node,这个Pod也会运行在新增的Node上,如果删除这个DadmonSet,就会清除它所创建的Pod。常用来部署一些集群日志收集,监控等全局应用。
常见的场景如下:
1、运行存储集群daemon,比如ceph,glusterd等;
2、运行一个日志收集daemon,比如logstash,fluentd等;
3、运行监控daemon,比如Prometheus Node Exporter,collectd,New Relic agent,Ganglia gmond等;
二、调度策略
通常情况下,通过DaemonSet创建的的Pod应该调度到那个节点是通过Kubernetes调度策略决定的,然而,当这个Pod被创建的时候,运行在那个节点上其实已经被提前决定了,所以它会忽略调度器。因此:
- DaemonSet控制器并不在乎Node的unschedulable字段;
- 即使调度器没有启动,DaemonSet控制器都可以创建Pod;
但是可以通过以下方法来让Pod运行到指定的Node上:
- nodeSelector:只调度到匹配指定label的Node上;
- nodeAffinity:功能更丰富的Node选择器,比如支持集合操作;
- podAffinity:调度到满足条件的Pod所在的Node上;
2.1、nodeSelector
就是给需要运行在的Node打标签,比如只运行在有ssd硬盘的node上,那么我们就可以给这些node打一个标签:
kubectl label nodes node-01 disktype=ssd
然后在DaemonSet的字段中定义nodeSelector为disktype=ssd:
spec:nodeSelector:disktype: ssd
2.2、nodeAffinity
nodeAffinity目前支持两种:requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution,分别代表必须满足条件和优选条件。比如下面的例子代表调度到包含标签kubernetes.io/e2e-az-name并且值为e2e-az1或e2e-az2的Node上,并且优选还带有标签another-node-label-key=another-node-label-value的Node。
apiVersion: v1kind: Podmetadata:name: with-node-affinityspec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/e2e-az-nameoperator: Invalues:- e2e-az1- e2e-az2preferredDuringSchedulingIgnoredDuringExecution:- weight: 1preference:matchExpressions:- key: another-node-label-keyoperator: Invalues:- another-node-label-valuecontainers:- name: with-node-affinityimage: gcr.io/google_containers/pause:2.0
2.3、podAffinity
podAffinity基于Pod的标签来选择Node,仅调度到满足条件Pod所在的Node上,支持podAffinity和podAntiAffinity。这个功能比较绕,以下面的例子为例:
- 如果一个“Node所在Zone中包含至少一个带有security=S1标签且运行中的Pod”,那么可以调度到该Node
- 不调度到“包含至少一个带有security=S2标签且运行中Pod”的Node上
apiVersion: v1kind: Podmetadata:name: with-pod-affinityspec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: securityoperator: Invalues:- S1topologyKey: failure-domain.beta.kubernetes.io/zonepodAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: securityoperator: Invalues:- S2topologyKey: kubernetes.io/hostnamecontainers:- name: with-pod-affinityimage: gcr.io/google_containers/pause:2.0
三、更新
DaemonSet支持滚动更新,其定义字段为updateStrategy,可以通过kubectl explain ds.spec.updateStrategy查看。
[root@master ~]# kubectl explain ds.spec.updateStrategyKIND: DaemonSetVERSION: extensions/v1beta1RESOURCE: updateStrategy <Object>DESCRIPTION:An update strategy to replace existing DaemonSet pods with new pods.FIELDS:rollingUpdate <Object>Rolling update config params. Present only if type = "RollingUpdate".type <string>Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default isOnDelete.
其rollingUpdate字段只有一个maxUnavailable,没有maxSurge,因为DaemonSet只允许在node上运行一个。
DaemonSet的更新策略有两个:
- RollingUpdate:滚动更新
- OnDelete:当删除Pod的时候更新,默认的更新策略;
四、例子
定义一个收集日志的DaemonSet,使用filebeat收集日志,通过filebeat收集日志传给redis:
# vim filebeat-ds.yaml
apiVersion: apps/v1kind: Deploymentmetadata:name: redisnamespace: defaultspec:replicas: 1selector:matchLabels:app: redisrole: cachedbtemplate:metadata:labels:app: redisrole: cachedbspec:containers:- name: redisimage: redis:5.0.5-alpineports:- name: rediscontainerPort: 6379---apiVersion: v1kind: Servicemetadata:name: redisnamespace: defaultspec:type: ClusterIPselector:app: redisrole: cachedbports:- port: 6379---apiVersion: apps/v1kind: DaemonSetmetadata:name: filebeat-dsnamespace: defaultspec:selector:matchLabels:app: filebeatrole: logstoragetemplate:metadata:labels:app: filebeatrole: logstoragespec:containers:- name: filebeatimage: ikubernetes/filebeat:5.6.5-alpineenv:- name: REDIS_HOSTvalue: redis.default.svc.cluster.local
我们创建这个YAML文件
# kubectl apply -f filebeat-ds.yaml
然后查看svc,pod的状态
[root@master daemonset]# kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 10.68.0.1 <none> 443/TCP 4d6hredis ClusterIP 10.68.213.73 <none> 6379/TCP 5s[root@master daemonset]# kubectl get podsNAME READY STATUS RESTARTS AGEfilebeat-ds-pgmzt 1/1 Running 0 2m50sfilebeat-ds-wx44z 1/1 Running 0 2m50sfilebeat-ds-zjv68 1/1 Running 0 2m50sredis-85c7ccb675-ks4rc 1/1 Running 0 4m2s
然后我们进filebeat容器搞一点测试数据:
# kubectl exec -it filebeat-ds-pgmzt -- /bin/bash# cd /var/log/containers/# echo "123" > a.log
然后进redis容器查看数据:
# kubectl exec -it redis-85c7ccb675-ks4rc -- /bin/sh/data # redis-cli -h redis.default.svc.cluster.local -p 6379redis.default.svc.cluster.local:6379> KEYS *1) "filebeat"redis.default.svc.cluster.local:6379>
