DaemonSet 保证在每个 Node 上都运行一个容器副本,常用来部署一些集群的日志、监控或者其他系统管理应用。典型的应用包括:

  • 日志收集,比如 fluentd,logstash 等
  • 系统监控,比如 Prometheus Node Exporter,collectd,New Relic agent,Ganglia gmond 等
  • 系统程序,比如 kube-proxy, kube-dns, glusterd, ceph 等

API 版本对照表

Kubernetes 版本 Deployment 版本
v1.5-v1.6 extensions/v1beta1
v1.7-v1.15 apps/v1beta1
v1.8-v1.15 apps/v1beta2
v1.9+ apps/v1

使用 Fluentd 收集日志的例子:

  1. apiVersion: apps/v1
  2. kind: DaemonSet
  3. metadata:
  4. name: fluentd-elasticsearch
  5. namespace: kube-system
  6. labels:
  7. k8s-app: fluentd-logging
  8. spec:
  9. selector:
  10. matchLabels:
  11. name: fluentd-elasticsearch
  12. template:
  13. metadata:
  14. labels:
  15. name: fluentd-elasticsearch
  16. spec:
  17. tolerations:
  18. - key: node-role.kubernetes.io/master
  19. effect: NoSchedule
  20. containers:
  21. - name: fluentd-elasticsearch
  22. image: gcr.io/google-containers/fluentd-elasticsearch:1.20
  23. resources:
  24. limits:
  25. memory: 200Mi
  26. requests:
  27. cpu: 100m
  28. memory: 200Mi
  29. volumeMounts:
  30. - name: varlog
  31. mountPath: /var/log
  32. - name: varlibdockercontainers
  33. mountPath: /var/lib/docker/containers
  34. readOnly: true
  35. terminationGracePeriodSeconds: 30
  36. volumes:
  37. - name: varlog
  38. hostPath:
  39. path: /var/log
  40. - name: varlibdockercontainers
  41. hostPath:
  42. path: /var/lib/docker/containers

滚动更新

v1.6 + 支持 DaemonSet 的滚动更新,可以通过 .spec.updateStrategy.type 设置更新策略。目前支持两种策略

  • OnDelete:默认策略,更新模板后,只有手动删除了旧的 Pod 后才会创建新的 Pod
  • RollingUpdate:更新 DaemonSet 模版后,自动删除旧的 Pod 并创建新的 Pod

在使用 RollingUpdate 策略时,还可以设置

  • .spec.updateStrategy.rollingUpdate.maxUnavailable, 默认 1
  • spec.minReadySeconds,默认 0

回滚

v1.7 + 还支持回滚

  1. # 查询历史版本
  2. $ kubectl rollout history daemonset <daemonset-name>
  3. # 查询某个历史版本的详细信息
  4. $ kubectl rollout history daemonset <daemonset-name> --revision=1
  5. # 回滚
  6. $ kubectl rollout undo daemonset <daemonset-name> --to-revision=<revision>
  7. # 查询回滚状态
  8. $ kubectl rollout status ds/<daemonset-name>

指定 Node 节点

DaemonSet 会忽略 Node 的 unschedulable 状态,有两种方式来指定 Pod 只运行在指定的 Node 节点上:

  • nodeSelector:只调度到匹配指定 label 的 Node 上
  • nodeAffinity:功能更丰富的 Node 选择器,比如支持集合操作
  • podAffinity:调度到满足条件的 Pod 所在的 Node 上

nodeSelector 示例

首先给 Node 打上标签

  1. kubectl label nodes node-01 disktype=ssd

然后在 daemonset 中指定 nodeSelector 为 disktype=ssd

  1. spec:
  2. nodeSelector:
  3. disktype: ssd

nodeAffinity 示例

nodeAffinity 目前支持两种:requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution,分别代表必须满足条件和优选条件。比如下面的例子代表调度到包含标签 kubernetes.io/e2e-az-name 并且值为 e2e-az1 或 e2e-az2 的 Node 上,并且优选还带有标签 another-node-label-key=another-node-label-value 的 Node。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: with-node-affinity
  5. spec:
  6. affinity:
  7. nodeAffinity:
  8. requiredDuringSchedulingIgnoredDuringExecution:
  9. nodeSelectorTerms:
  10. - matchExpressions:
  11. - key: kubernetes.io/e2e-az-name
  12. operator: In
  13. values:
  14. - e2e-az1
  15. - e2e-az2
  16. preferredDuringSchedulingIgnoredDuringExecution:
  17. - weight: 1
  18. preference:
  19. matchExpressions:
  20. - key: another-node-label-key
  21. operator: In
  22. values:
  23. - another-node-label-value
  24. containers:
  25. - name: with-node-affinity
  26. image: gcr.io/google_containers/pause:2.0

podAffinity 示例

podAffinity 基于 Pod 的标签来选择 Node,仅调度到满足条件 Pod 所在的 Node 上,支持 podAffinity 和 podAntiAffinity。这个功能比较绕,以下面的例子为例:

  • 如果一个 “Node 所在 Zone 中包含至少一个带有 security=S1 标签且运行中的 Pod”,那么可以调度到该 Node
  • 不调度到 “包含至少一个带有 security=S2 标签且运行中 Pod” 的 Node 上
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: with-pod-affinity
  5. spec:
  6. affinity:
  7. podAffinity:
  8. requiredDuringSchedulingIgnoredDuringExecution:
  9. - labelSelector:
  10. matchExpressions:
  11. - key: security
  12. operator: In
  13. values:
  14. - S1
  15. topologyKey: failure-domain.beta.kubernetes.io/zone
  16. podAntiAffinity:
  17. preferredDuringSchedulingIgnoredDuringExecution:
  18. - weight: 100
  19. podAffinityTerm:
  20. labelSelector:
  21. matchExpressions:
  22. - key: security
  23. operator: In
  24. values:
  25. - S2
  26. topologyKey: kubernetes.io/hostname
  27. containers:
  28. - name: with-pod-affinity
  29. image: gcr.io/google_containers/pause:2.0

静态 Pod

除了 DaemonSet,还可以使用静态 Pod 来在每台机器上运行指定的 Pod,这需要 kubelet 在启动的时候指定 manifest 目录:

  1. kubelet --pod-manifest-path=/etc/kubernetes/manifests

然后将所需要的 Pod 定义文件放到指定的 manifest 目录中。

注意:静态 Pod 不能通过 API Server 来删除,但可以通过删除 manifest 文件来自动删除对应的 Pod。